substrate_api_client/api/runtime_api/
mod.rs

1/*
2   Copyright 2019 Supercomputing Systems AG
3   Licensed under the Apache License, Version 2.0 (the "License");
4   you may not use this file except in compliance with the License.
5   You may obtain a copy of the License at
6	   http://www.apache.org/licenses/LICENSE-2.0
7   Unless required by applicable law or agreed to in writing, software
8   distributed under the License is distributed on an "AS IS" BASIS,
9   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10   See the License for the specific language governing permissions and
11   limitations under the License.
12*/
13
14pub use self::{
15	account_nonce::*, api_core::*, authority_discovery::*, block_builder::*, metadata::*, mmr::*,
16	session_keys::*, staking::*, transaction_payment::*, transaction_payment_call::*,
17};
18
19pub mod account_nonce;
20pub mod api_core;
21pub mod authority_discovery;
22pub mod block_builder;
23pub mod metadata;
24pub mod mmr;
25pub mod session_keys;
26pub mod staking;
27pub mod transaction_payment;
28pub mod transaction_payment_call;
29
30use crate::{api::Result, rpc::Request};
31use ac_compose_macros::rpc_params;
32use ac_primitives::config::Config;
33#[cfg(all(not(feature = "sync-api"), not(feature = "std")))]
34use alloc::boxed::Box;
35use alloc::{sync::Arc, vec::Vec};
36use codec::Decode;
37use core::marker::PhantomData;
38use sp_core::Bytes;
39
40#[derive(Clone)]
41pub struct RuntimeApiClient<T, Client> {
42	client: Arc<Client>,
43	_phantom: PhantomData<T>,
44}
45
46impl<T, Client> RuntimeApiClient<T, Client> {
47	pub fn new(client: Arc<Client>) -> Self {
48		Self { client, _phantom: PhantomData }
49	}
50}
51
52#[maybe_async::maybe_async(?Send)]
53pub trait RuntimeApi {
54	type Hash;
55
56	/// Query a runtime api call with automatic decoding to the expected return type.
57	async fn runtime_call<V: Decode>(
58		&self,
59		method: &str,
60		data: Vec<Vec<u8>>,
61		at_block: Option<Self::Hash>,
62	) -> Result<V>;
63
64	/// Query a raw runtime api call without decoding.
65	async fn opaque_runtime_call(
66		&self,
67		method: &str,
68		data: Vec<Vec<u8>>,
69		at_block: Option<Self::Hash>,
70	) -> Result<Bytes>;
71
72	// Perform a rpc call to a builtin on the chain.
73	async fn rpc_call(
74		&self,
75		method: &str,
76		data: Option<Bytes>,
77		at_block: Option<Self::Hash>,
78	) -> Result<Bytes>;
79}
80
81#[maybe_async::maybe_async(?Send)]
82impl<T, Client> RuntimeApi for RuntimeApiClient<T, Client>
83where
84	T: Config,
85	Client: Request,
86{
87	type Hash = T::Hash;
88
89	async fn runtime_call<V: Decode>(
90		&self,
91		method: &str,
92		data: Vec<Vec<u8>>,
93		at_block: Option<Self::Hash>,
94	) -> Result<V> {
95		let bytes = self.opaque_runtime_call(method, data, at_block).await?;
96		Ok(Decode::decode(&mut bytes.0.as_slice())?)
97	}
98
99	async fn opaque_runtime_call(
100		&self,
101		method: &str,
102		data: Vec<Vec<u8>>,
103		at_block: Option<Self::Hash>,
104	) -> Result<Bytes> {
105		let data = match data.is_empty() {
106			true => None,
107			false => {
108				let mut appended_data = Vec::new();
109				for mut item in data {
110					appended_data.append(&mut item);
111				}
112				Some(appended_data.into())
113			},
114		};
115		self.rpc_call(method, data, at_block).await
116	}
117
118	async fn rpc_call(
119		&self,
120		method: &str,
121		data: Option<Bytes>,
122		at_block: Option<Self::Hash>,
123	) -> Result<Bytes> {
124		let extracted_data: Bytes = match data {
125			Some(data) => data,
126			None => Vec::new().into(),
127		};
128		let return_bytes = self
129			.client
130			.request("state_call", rpc_params![method, extracted_data, at_block])
131			.await?;
132		Ok(return_bytes)
133	}
134}