1pub use moonbeam_core_primitives::{AccountId, Balance, Block, BlockNumber, Hash, Header, Index};
17use sc_client_api::{Backend as BackendT, BlockchainEvents, KeysIter, MerkleValue, PairsIter};
18use sp_api::{CallApiAt, ProvideRuntimeApi};
19use sp_blockchain::HeaderBackend;
20use sp_consensus::BlockStatus;
21use sp_runtime::{
22 generic::SignedBlock,
23 traits::{BlakeTwo256, Block as BlockT, NumberFor},
24 Justifications,
25};
26use sp_storage::{ChildInfo, StorageData, StorageKey};
27use std::sync::Arc;
28
29pub trait RuntimeApiCollection:
34 sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
35 + sp_api::ApiExt<Block>
36 + sp_block_builder::BlockBuilder<Block>
37 + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
38 + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
39 + sp_api::Metadata<Block>
40 + sp_offchain::OffchainWorkerApi<Block>
41 + sp_session::SessionKeys<Block>
42 + fp_rpc::ConvertTransactionRuntimeApi<Block>
43 + fp_rpc::EthereumRuntimeRPCApi<Block>
44 + moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block>
45 + moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block>
46 + nimbus_primitives::NimbusApi<Block>
47 + cumulus_primitives_core::CollectCollationInfo<Block>
48 + session_keys_primitives::VrfApi<Block>
49 + async_backing_primitives::UnincludedSegmentApi<Block>
50 + xcm_runtime_apis::fees::XcmPaymentApi<Block>
51{
52}
53
54impl<Api> RuntimeApiCollection for Api where
55 Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
56 + sp_api::ApiExt<Block>
57 + sp_block_builder::BlockBuilder<Block>
58 + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
59 + pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
60 + sp_api::Metadata<Block>
61 + sp_offchain::OffchainWorkerApi<Block>
62 + sp_session::SessionKeys<Block>
63 + fp_rpc::ConvertTransactionRuntimeApi<Block>
64 + fp_rpc::EthereumRuntimeRPCApi<Block>
65 + moonbeam_rpc_primitives_debug::DebugRuntimeApi<Block>
66 + moonbeam_rpc_primitives_txpool::TxPoolRuntimeApi<Block>
67 + nimbus_primitives::NimbusApi<Block>
68 + cumulus_primitives_core::CollectCollationInfo<Block>
69 + session_keys_primitives::VrfApi<Block>
70 + async_backing_primitives::UnincludedSegmentApi<Block>
71 + xcm_runtime_apis::fees::XcmPaymentApi<Block>
72{
73}
74
75pub trait AbstractClient<Block, Backend>:
79 BlockchainEvents<Block>
80 + Sized
81 + Send
82 + Sync
83 + ProvideRuntimeApi<Block>
84 + HeaderBackend<Block>
85 + CallApiAt<Block, StateBackend = Backend::State>
86where
87 Block: BlockT,
88 Backend: BackendT<Block>,
89 Backend::State: sc_client_api::backend::StateBackend<BlakeTwo256>,
90 Self::Api: RuntimeApiCollection,
91{
92}
93
94impl<Block, Backend, Client> AbstractClient<Block, Backend> for Client
95where
96 Block: BlockT,
97 Backend: BackendT<Block>,
98 Backend::State: sc_client_api::backend::StateBackend<BlakeTwo256>,
99 Client: BlockchainEvents<Block>
100 + ProvideRuntimeApi<Block>
101 + HeaderBackend<Block>
102 + Sized
103 + Send
104 + Sync
105 + CallApiAt<Block, StateBackend = Backend::State>,
106 Client::Api: RuntimeApiCollection,
107{
108}
109
110pub trait ExecuteWithClient {
124 type Output;
126
127 fn execute_with_client<Client, Api, Backend>(self, client: Arc<Client>) -> Self::Output
129 where
130 Backend: sc_client_api::Backend<Block>,
131 Backend::State: sc_client_api::backend::StateBackend<BlakeTwo256>,
132 Api: crate::RuntimeApiCollection,
133 Client: AbstractClient<Block, Backend, Api = Api> + 'static;
134}
135
136pub trait ClientHandle {
144 fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output;
146}
147
148#[derive(Clone)]
150pub enum Client {
151 #[cfg(feature = "moonbeam-native")]
152 Moonbeam(Arc<crate::FullClient<moonbeam_runtime::RuntimeApi>>),
153 #[cfg(feature = "moonriver-native")]
154 Moonriver(Arc<crate::FullClient<moonriver_runtime::RuntimeApi>>),
155 #[cfg(feature = "moonbase-native")]
156 Moonbase(Arc<crate::FullClient<moonbase_runtime::RuntimeApi>>),
157}
158
159#[cfg(feature = "moonbeam-native")]
160impl From<Arc<crate::FullClient<moonbeam_runtime::RuntimeApi>>> for Client {
161 fn from(client: Arc<crate::FullClient<moonbeam_runtime::RuntimeApi>>) -> Self {
162 Self::Moonbeam(client)
163 }
164}
165
166#[cfg(feature = "moonriver-native")]
167impl From<Arc<crate::FullClient<moonriver_runtime::RuntimeApi>>> for Client {
168 fn from(client: Arc<crate::FullClient<moonriver_runtime::RuntimeApi>>) -> Self {
169 Self::Moonriver(client)
170 }
171}
172
173#[cfg(feature = "moonbase-native")]
174impl From<Arc<crate::FullClient<moonbase_runtime::RuntimeApi>>> for Client {
175 fn from(client: Arc<crate::FullClient<moonbase_runtime::RuntimeApi>>) -> Self {
176 Self::Moonbase(client)
177 }
178}
179
180impl ClientHandle for Client {
181 fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output {
182 match self {
183 #[cfg(feature = "moonbeam-native")]
184 Self::Moonbeam(client) => T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone()),
185 #[cfg(feature = "moonriver-native")]
186 Self::Moonriver(client) => T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone()),
187 #[cfg(feature = "moonbase-native")]
188 Self::Moonbase(client) => T::execute_with_client::<_, _, crate::FullBackend>(t, client.clone()),
189 }
190 }
191}
192
193macro_rules! match_client {
194 ($self:ident, $method:ident($($param:ident),*)) => {
195 match $self {
196 #[cfg(feature = "moonbeam-native")]
197 Self::Moonbeam(client) => client.$method($($param),*),
198 #[cfg(feature = "moonriver-native")]
199 Self::Moonriver(client) => client.$method($($param),*),
200 #[cfg(feature = "moonbase-native")]
201 Self::Moonbase(client) => client.$method($($param),*),
202 }
203 };
204}
205
206impl sc_client_api::UsageProvider<Block> for Client {
207 fn usage_info(&self) -> sc_client_api::ClientInfo<Block> {
208 match_client!(self, usage_info())
209 }
210}
211
212impl sc_client_api::BlockBackend<Block> for Client {
213 fn block_body(
214 &self,
215 hash: <Block as BlockT>::Hash,
216 ) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
217 match_client!(self, block_body(hash))
218 }
219
220 fn block_indexed_body(
221 &self,
222 hash: <Block as BlockT>::Hash,
223 ) -> sp_blockchain::Result<Option<Vec<Vec<u8>>>> {
224 match_client!(self, block_indexed_body(hash))
225 }
226
227 fn block(
228 &self,
229 hash: <Block as BlockT>::Hash,
230 ) -> sp_blockchain::Result<Option<SignedBlock<Block>>> {
231 match_client!(self, block(hash))
232 }
233
234 fn block_status(&self, hash: <Block as BlockT>::Hash) -> sp_blockchain::Result<BlockStatus> {
235 match_client!(self, block_status(hash))
236 }
237
238 fn justifications(
239 &self,
240 hash: <Block as BlockT>::Hash,
241 ) -> sp_blockchain::Result<Option<Justifications>> {
242 match_client!(self, justifications(hash))
243 }
244
245 fn block_hash(
246 &self,
247 number: NumberFor<Block>,
248 ) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
249 match_client!(self, block_hash(number))
250 }
251
252 fn indexed_transaction(
253 &self,
254 hash: <Block as BlockT>::Hash,
255 ) -> sp_blockchain::Result<Option<Vec<u8>>> {
256 match_client!(self, indexed_transaction(hash))
257 }
258
259 fn has_indexed_transaction(
260 &self,
261 hash: <Block as BlockT>::Hash,
262 ) -> sp_blockchain::Result<bool> {
263 match_client!(self, has_indexed_transaction(hash))
264 }
265
266 fn requires_full_sync(&self) -> bool {
267 match_client!(self, requires_full_sync())
268 }
269}
270
271impl sc_client_api::StorageProvider<Block, crate::FullBackend> for Client {
272 fn storage(
273 &self,
274 hash: <Block as BlockT>::Hash,
275 key: &StorageKey,
276 ) -> sp_blockchain::Result<Option<StorageData>> {
277 match_client!(self, storage(hash, key))
278 }
279
280 fn storage_hash(
281 &self,
282 hash: <Block as BlockT>::Hash,
283 key: &StorageKey,
284 ) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
285 match_client!(self, storage_hash(hash, key))
286 }
287
288 fn storage_keys(
289 &self,
290 hash: <Block as BlockT>::Hash,
291 prefix: Option<&StorageKey>,
292 start_key: Option<&StorageKey>,
293 ) -> sp_blockchain::Result<
294 KeysIter<<crate::FullBackend as sc_client_api::Backend<Block>>::State, Block>,
295 > {
296 match_client!(self, storage_keys(hash, prefix, start_key))
297 }
298
299 fn storage_pairs(
300 &self,
301 hash: <Block as BlockT>::Hash,
302 key_prefix: Option<&StorageKey>,
303 start_key: Option<&StorageKey>,
304 ) -> sp_blockchain::Result<
305 PairsIter<<crate::FullBackend as sc_client_api::Backend<Block>>::State, Block>,
306 > {
307 match_client!(self, storage_pairs(hash, key_prefix, start_key))
308 }
309
310 fn child_storage(
311 &self,
312 hash: <Block as BlockT>::Hash,
313 child_info: &ChildInfo,
314 key: &StorageKey,
315 ) -> sp_blockchain::Result<Option<StorageData>> {
316 match_client!(self, child_storage(hash, child_info, key))
317 }
318
319 fn child_storage_keys(
320 &self,
321 hash: <Block as BlockT>::Hash,
322 child_info: ChildInfo,
323 prefix: Option<&StorageKey>,
324 start_key: Option<&StorageKey>,
325 ) -> sp_blockchain::Result<
326 KeysIter<<crate::FullBackend as sc_client_api::Backend<Block>>::State, Block>,
327 > {
328 match_client!(
329 self,
330 child_storage_keys(hash, child_info, prefix, start_key)
331 )
332 }
333
334 fn child_storage_hash(
335 &self,
336 hash: <Block as BlockT>::Hash,
337 child_info: &ChildInfo,
338 key: &StorageKey,
339 ) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
340 match_client!(self, child_storage_hash(hash, child_info, key))
341 }
342
343 fn closest_merkle_value(
344 &self,
345 hash: <Block as BlockT>::Hash,
346 key: &StorageKey,
347 ) -> sp_blockchain::Result<Option<MerkleValue<<Block as BlockT>::Hash>>> {
348 match_client!(self, closest_merkle_value(hash, key))
349 }
350
351 fn child_closest_merkle_value(
352 &self,
353 hash: <Block as BlockT>::Hash,
354 child_info: &ChildInfo,
355 key: &StorageKey,
356 ) -> sp_blockchain::Result<Option<MerkleValue<<Block as BlockT>::Hash>>> {
357 match_client!(self, child_closest_merkle_value(hash, child_info, key))
358 }
359}
360
361impl sp_blockchain::HeaderBackend<Block> for Client {
362 fn header(&self, hash: Hash) -> sp_blockchain::Result<Option<Header>> {
363 match_client!(self, header(hash))
364 }
365
366 fn info(&self) -> sp_blockchain::Info<Block> {
367 match_client!(self, info())
368 }
369
370 fn status(&self, hash: Hash) -> sp_blockchain::Result<sp_blockchain::BlockStatus> {
371 match_client!(self, status(hash))
372 }
373
374 fn number(&self, hash: Hash) -> sp_blockchain::Result<Option<BlockNumber>> {
375 match_client!(self, number(hash))
376 }
377
378 fn hash(&self, number: NumberFor<Block>) -> sp_blockchain::Result<Option<Hash>> {
379 match_client!(self, hash(number))
380 }
381}