frequency_service/rpc/
frequency_rpc.rs1#![deny(
3 rustdoc::broken_intra_doc_links,
4 rustdoc::missing_crate_level_docs,
5 rustdoc::invalid_codeblock_attributes,
6 missing_docs
7)]
8
9use common_helpers::rpc::map_rpc_result;
10use common_primitives::rpc::RpcEvent;
11use jsonrpsee::{
12 core::{async_trait, RpcResult},
13 proc_macros::rpc,
14 types::error::ErrorObject,
15};
16use parity_scale_codec::{Codec, Decode, Encode};
17use sc_transaction_pool_api::{InPoolTransaction, TransactionPool};
18use sp_api::ProvideRuntimeApi;
19use sp_blockchain::HeaderBackend;
20use sp_runtime::traits::{AtLeast32Bit, Block as BlockT, One};
21use std::sync::Arc;
22use substrate_frame_rpc_system::AccountNonceApi;
23use system_runtime_api::AdditionalRuntimeApi;
24
25const MAX_RETURNED_MISSING_NONCE_SIZE: usize = 1000;
28#[rpc(client, server)]
30pub trait FrequencyRpcApi<B: BlockT, AccountId, Nonce> {
31 #[method(name = "frequency_getEvents")]
33 fn get_events(&self, at: B::Hash) -> RpcResult<Vec<RpcEvent>>;
34 #[method(name = "frequency_getMissingNonceValues")]
36 fn get_missing_nonce_values(&self, account: AccountId) -> RpcResult<Vec<Nonce>>;
37}
38
39pub struct FrequencyRpcHandler<P: TransactionPool, C, M> {
41 client: Arc<C>,
42 pool: Arc<P>,
43 _marker: std::marker::PhantomData<M>,
44}
45
46impl<P: TransactionPool, C, M> FrequencyRpcHandler<P, C, M> {
47 pub fn new(client: Arc<C>, pool: Arc<P>) -> Self {
49 Self { client, pool, _marker: Default::default() }
50 }
51}
52
53#[async_trait]
54impl<P, C, Block, AccountId, Nonce> FrequencyRpcApiServer<Block, AccountId, Nonce>
55 for FrequencyRpcHandler<P, C, Block>
56where
57 Block: BlockT,
58 C: HeaderBackend<Block>,
59 C: Send + Sync + 'static,
60 C: ProvideRuntimeApi<Block>,
61 C::Api: AdditionalRuntimeApi<Block>,
62 C::Api: AccountNonceApi<Block, AccountId, Nonce>,
63 P: TransactionPool + 'static,
64 AccountId: Clone + Codec,
65 Nonce: Clone + Encode + Decode + AtLeast32Bit + 'static,
66{
67 fn get_events(&self, at: <Block as BlockT>::Hash) -> RpcResult<Vec<RpcEvent>> {
68 let api = self.client.runtime_api();
69 map_rpc_result(api.get_events(at))
70 }
71
72 fn get_missing_nonce_values(&self, account: AccountId) -> RpcResult<Vec<Nonce>> {
73 let api = self.client.runtime_api();
74 let best = self.client.info().best_hash;
75
76 let nonce = api
77 .account_nonce(best, account.clone())
78 .map_err(|e| ErrorObject::owned(1, "Unable to query nonce.", Some(e.to_string())))?;
79 Ok(get_missing_nonces(&*self.pool, account, nonce))
80 }
81}
82
83fn get_missing_nonces<P, AccountId, Nonce>(pool: &P, account: AccountId, nonce: Nonce) -> Vec<Nonce>
85where
86 P: TransactionPool,
87 AccountId: Clone + Encode,
88 Nonce: Clone + Encode + Decode + AtLeast32Bit + 'static,
89{
90 let mut current_nonce = nonce.clone();
96 let encoded_account = account.clone().encode();
97 let mut current_tag = (account.clone(), nonce).encode();
98 for tx in pool.ready() {
99 if tx.provides().get(0) == Some(¤t_tag) {
102 current_nonce += One::one();
103 current_tag = (account.clone(), current_nonce.clone()).encode();
104 }
105 }
106
107 let mut result = vec![];
108 let mut my_in_future: Vec<_> = pool
109 .futures()
110 .into_iter()
111 .filter_map(|x| match x.provides().get(0) {
112 Some(tag) if tag.starts_with(&encoded_account) => {
114 if let Ok(nonce) = Nonce::decode(&mut &tag[encoded_account.len()..]) {
115 return Some(nonce)
116 }
117 None
118 },
119 _ => None,
120 })
121 .collect();
122 my_in_future.sort();
123
124 for future_nonce in my_in_future {
125 while current_nonce < future_nonce {
126 result.push(current_nonce.clone());
127 current_nonce += One::one();
128
129 if result.len() == MAX_RETURNED_MISSING_NONCE_SIZE {
131 return result
132 }
133 }
134
135 current_nonce += One::one();
137 }
138
139 result
140}