avail_rust_client/clients/
rpc_api.rs

1use crate::{Client, clients::main_client::sleep_on_retry};
2use avail_rust_core::{
3	AvailHeader, H256, HashNumber,
4	ext::{
5		codec::Decode,
6		subxt_rpcs::{
7			client::RpcParams,
8			methods::legacy::{RuntimeVersion, SystemHealth},
9		},
10	},
11	grandpa::GrandpaJustification,
12	rpc::{
13		self, BlockWithJustifications,
14		author::SessionKeys,
15		kate::{BlockLength, Cell, GDataProof, GRow, ProofResponse},
16		rpc_methods::RpcMethods,
17		system::{NodeRole, PeerInfo, SyncState, SystemProperties, fetch_events_v1_types, fetch_extrinsics_v1_types},
18	},
19};
20
21#[derive(Clone)]
22pub struct RpcAPI {
23	client: Client,
24}
25
26impl RpcAPI {
27	pub fn new(client: Client) -> Self {
28		Self { client }
29	}
30
31	pub async fn call<T: serde::de::DeserializeOwned>(
32		&self,
33		method: &str,
34		params: RpcParams,
35	) -> Result<T, avail_rust_core::Error> {
36		Ok(rpc::call_raw(&self.client.rpc_client, method, params).await?)
37	}
38
39	pub async fn system_account_next_index(&self, address: &str) -> Result<u32, avail_rust_core::Error> {
40		Ok(rpc::system::account_next_index(&self.client.rpc_client, address).await?)
41	}
42
43	pub async fn system_chain(&self) -> Result<String, avail_rust_core::Error> {
44		Ok(rpc::system::chain(&self.client.rpc_client).await?)
45	}
46
47	pub async fn system_chain_type(&self) -> Result<String, avail_rust_core::Error> {
48		Ok(rpc::system::chain_type(&self.client.rpc_client).await?)
49	}
50
51	pub async fn system_health(&self) -> Result<SystemHealth, avail_rust_core::Error> {
52		Ok(rpc::system::health(&self.client.rpc_client).await?)
53	}
54
55	pub async fn system_local_listen_addresses(&self) -> Result<Vec<String>, avail_rust_core::Error> {
56		Ok(rpc::system::local_listen_addresses(&self.client.rpc_client).await?)
57	}
58
59	pub async fn system_local_peer_id(&self) -> Result<String, avail_rust_core::Error> {
60		Ok(rpc::system::local_peer_id(&self.client.rpc_client).await?)
61	}
62
63	pub async fn system_name(&self) -> Result<String, avail_rust_core::Error> {
64		Ok(rpc::system::name(&self.client.rpc_client).await?)
65	}
66
67	pub async fn system_node_roles(&self) -> Result<Vec<NodeRole>, avail_rust_core::Error> {
68		Ok(rpc::system::node_roles(&self.client.rpc_client).await?)
69	}
70
71	pub async fn system_peers(&self) -> Result<Vec<PeerInfo>, avail_rust_core::Error> {
72		Ok(rpc::system::peers(&self.client.rpc_client).await?)
73	}
74
75	pub async fn system_properties(&self) -> Result<SystemProperties, avail_rust_core::Error> {
76		Ok(rpc::system::properties(&self.client.rpc_client).await?)
77	}
78
79	pub async fn system_sync_state(&self) -> Result<SyncState, avail_rust_core::Error> {
80		Ok(rpc::system::sync_state(&self.client.rpc_client).await?)
81	}
82
83	pub async fn system_sync_state_ext(&self, retry_on_error: bool) -> Result<SyncState, avail_rust_core::Error> {
84		const MESSAGE: &str = "Failed to execute RPC: system_sync_state";
85
86		let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
87		loop {
88			match rpc::system::sync_state(&self.client.rpc_client).await {
89				Ok(x) => return Ok(x),
90				Err(err) if !retry_on_error => {
91					return Err(err.into());
92				},
93				Err(err) => {
94					let Some(duration) = sleep_duration.pop() else {
95						return Err(err.into());
96					};
97					sleep_on_retry(duration, MESSAGE, &err.to_string()).await;
98				},
99			};
100		}
101	}
102
103	pub async fn system_version(&self) -> Result<String, avail_rust_core::Error> {
104		Ok(rpc::system::version(&self.client.rpc_client).await?)
105	}
106
107	pub async fn chain_get_block(
108		&self,
109		at: Option<H256>,
110	) -> Result<Option<BlockWithJustifications>, avail_rust_core::Error> {
111		Ok(rpc::chain::get_block(&self.client.rpc_client, at).await?)
112	}
113
114	pub async fn chain_get_block_hash(
115		&self,
116		block_height: Option<u32>,
117	) -> Result<Option<H256>, avail_rust_core::Error> {
118		Ok(rpc::chain::get_block_hash(&self.client.rpc_client, block_height).await?)
119	}
120
121	pub async fn chain_get_block_hash_ext(
122		&self,
123		block_height: Option<u32>,
124		retry_on_error: bool,
125		retry_on_none: bool,
126	) -> Result<Option<H256>, avail_rust_core::Error> {
127		const MESSAGE: &str = "Failed to fetch block hash";
128
129		let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
130		loop {
131			match rpc::chain::get_block_hash(&self.client.rpc_client, block_height).await {
132				Ok(Some(x)) => return Ok(Some(x)),
133				Ok(None) if !retry_on_none => {
134					return Ok(None);
135				},
136				Ok(None) => {
137					let Some(duration) = sleep_duration.pop() else {
138						return Ok(None);
139					};
140					sleep_on_retry(duration, MESSAGE, "Option<None>").await;
141				},
142				Err(err) if !retry_on_error => {
143					return Err(err.into());
144				},
145				Err(err) => {
146					let Some(duration) = sleep_duration.pop() else {
147						return Err(err.into());
148					};
149					sleep_on_retry(duration, MESSAGE, &err.to_string()).await;
150				},
151			};
152		}
153	}
154
155	pub async fn chain_get_finalized_head(&self) -> Result<H256, avail_rust_core::Error> {
156		Ok(rpc::chain::get_finalized_head(&self.client.rpc_client).await?)
157	}
158
159	pub async fn chain_get_finalized_head_ext(&self, retry_on_error: bool) -> Result<H256, avail_rust_core::Error> {
160		const MESSAGE: &str = "Failed to execute RPC: chain_getFinalized_Head";
161
162		let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
163		loop {
164			match rpc::chain::get_finalized_head(&self.client.rpc_client).await {
165				Ok(x) => return Ok(x),
166				Err(err) if !retry_on_error => {
167					return Err(err.into());
168				},
169				Err(err) => {
170					let Some(duration) = sleep_duration.pop() else {
171						return Err(err.into());
172					};
173					sleep_on_retry(duration, MESSAGE, &err.to_string()).await;
174				},
175			};
176		}
177	}
178
179	pub async fn chain_get_header(&self, at: Option<H256>) -> Result<Option<AvailHeader>, avail_rust_core::Error> {
180		Ok(rpc::chain::get_header(&self.client.rpc_client, at).await?)
181	}
182
183	pub async fn author_rotate_keys(&self) -> Result<SessionKeys, avail_rust_core::Error> {
184		rpc::author::rotate_keys(&self.client.rpc_client).await
185	}
186
187	pub async fn author_submit_extrinsic(&self, extrinsic: &[u8]) -> Result<H256, avail_rust_core::Error> {
188		Ok(rpc::author::submit_extrinsic(&self.client.rpc_client, extrinsic).await?)
189	}
190
191	pub async fn state_get_runtime_version(&self, at: Option<H256>) -> Result<RuntimeVersion, avail_rust_core::Error> {
192		Ok(rpc::state::get_runtime_version(&self.client.rpc_client, at).await?)
193	}
194
195	pub async fn state_call(
196		&self,
197		method: &str,
198		data: &[u8],
199		at: Option<H256>,
200	) -> Result<String, avail_rust_core::Error> {
201		Ok(rpc::state::call(&self.client.rpc_client, method, data, at).await?)
202	}
203
204	pub async fn state_get_metadata(&self, at: Option<H256>) -> Result<Vec<u8>, avail_rust_core::Error> {
205		rpc::state::get_metadata(&self.client.rpc_client, at).await
206	}
207
208	pub async fn state_get_storage(
209		&self,
210		key: &str,
211		at: Option<H256>,
212	) -> Result<Option<Vec<u8>>, avail_rust_core::Error> {
213		rpc::state::get_storage(&self.client.rpc_client, key, at).await
214	}
215
216	pub async fn state_get_keys_paged(
217		&self,
218		prefix: Option<String>,
219		count: u32,
220		start_key: Option<String>,
221		at: Option<H256>,
222	) -> Result<Vec<String>, avail_rust_core::Error> {
223		rpc::state::get_keys_paged(&self.client.rpc_client, prefix, count, start_key, at).await
224	}
225
226	pub async fn rpc_methods(&self) -> Result<RpcMethods, avail_rust_core::Error> {
227		Ok(rpc::rpc_methods::call(&self.client.rpc_client).await?)
228	}
229
230	pub async fn chainspec_v1_genesishash(&self) -> Result<H256, avail_rust_core::Error> {
231		rpc::chainspec::v1_genesishash(&self.client.rpc_client).await
232	}
233
234	pub async fn kate_block_length(&self, at: Option<H256>) -> Result<BlockLength, avail_rust_core::Error> {
235		Ok(rpc::kate::block_length(&self.client.rpc_client, at).await?)
236	}
237
238	pub async fn kate_query_data_proof(
239		&self,
240		transaction_index: u32,
241		at: Option<H256>,
242	) -> Result<ProofResponse, avail_rust_core::Error> {
243		Ok(rpc::kate::query_data_proof(&self.client.rpc_client, transaction_index, at).await?)
244	}
245
246	pub async fn kate_query_proof(
247		&self,
248		cells: Vec<Cell>,
249		at: Option<H256>,
250	) -> Result<Vec<GDataProof>, avail_rust_core::Error> {
251		Ok(rpc::kate::query_proof(&self.client.rpc_client, cells, at).await?)
252	}
253
254	pub async fn kate_query_rows(&self, rows: Vec<u32>, at: Option<H256>) -> Result<Vec<GRow>, avail_rust_core::Error> {
255		Ok(rpc::kate::query_rows(&self.client.rpc_client, rows, at).await?)
256	}
257
258	pub async fn grandpa_block_justification(
259		&self,
260		at: u32,
261	) -> Result<Option<GrandpaJustification>, avail_rust_core::Error> {
262		let result = rpc::grandpa::block_justification(&self.client.rpc_client, at).await?;
263		let Some(result) = result else {
264			return Ok(None);
265		};
266
267		let justification = const_hex::decode(result.trim_start_matches("0x"))
268			.map_err(|x| avail_rust_core::Error::from(x.to_string()))?;
269
270		let justification = GrandpaJustification::decode(&mut justification.as_slice()).map_err(|e| e.to_string())?;
271		Ok(Some(justification))
272	}
273
274	pub async fn grandpa_block_justification_ext(
275		&self,
276		at: u32,
277		retry_on_error: bool,
278	) -> Result<Option<GrandpaJustification>, avail_rust_core::Error> {
279		const MESSAGE: &str = "Failed to execute RPC: grandpa_blockJustification";
280
281		let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
282		let result = loop {
283			match rpc::grandpa::block_justification(&self.client.rpc_client, at).await {
284				Ok(x) => break x,
285				Err(err) if !retry_on_error => {
286					return Err(err.into());
287				},
288				Err(err) => {
289					let Some(duration) = sleep_duration.pop() else {
290						return Err(err.into());
291					};
292					sleep_on_retry(duration, MESSAGE, &err.to_string()).await;
293				},
294			};
295		};
296
297		let Some(result) = result else {
298			return Ok(None);
299		};
300
301		let justification = const_hex::decode(result.trim_start_matches("0x"))
302			.map_err(|x| avail_rust_core::Error::from(x.to_string()))?;
303
304		let justification = GrandpaJustification::decode(&mut justification.as_slice()).map_err(|e| e.to_string())?;
305		Ok(Some(justification))
306	}
307
308	pub async fn system_fetch_events_v1(
309		&self,
310		at: H256,
311		options: fetch_events_v1_types::Options,
312	) -> Result<fetch_events_v1_types::Output, avail_rust_core::Error> {
313		Ok(rpc::system::fetch_events_v1(&self.client.rpc_client, at, Some(options)).await?)
314	}
315
316	pub async fn system_fetch_events_v1_ext(
317		&self,
318		at: H256,
319		options: fetch_events_v1_types::Options,
320		retry_on_error: bool,
321	) -> Result<fetch_events_v1_types::Output, avail_rust_core::Error> {
322		const MESSAGE: &str = "Failed to execute RPC: system_FetchEventsV1";
323
324		let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
325		loop {
326			match self.system_fetch_events_v1(at, options.clone()).await {
327				Ok(x) => return Ok(x),
328				Err(err) if !retry_on_error => {
329					return Err(err);
330				},
331				Err(err) => {
332					let Some(duration) = sleep_duration.pop() else {
333						return Err(err);
334					};
335					sleep_on_retry(duration, MESSAGE, &err.to_string()).await;
336				},
337			};
338		}
339	}
340
341	pub async fn system_fetch_extrinsics_v1(
342		&self,
343		block_id: HashNumber,
344		options: fetch_extrinsics_v1_types::Options,
345	) -> Result<fetch_extrinsics_v1_types::Output, avail_rust_core::Error> {
346		Ok(rpc::system::fetch_extrinsics_v1(&self.client.rpc_client, block_id, Some(options)).await?)
347	}
348
349	pub async fn system_fetch_extrinsics_v1_ext(
350		&self,
351		block_id: HashNumber,
352		options: fetch_extrinsics_v1_types::Options,
353		retry_on_error: bool,
354	) -> Result<fetch_extrinsics_v1_types::Output, avail_rust_core::Error> {
355		const MESSAGE: &str = "Failed to execute RPC: system_FetchExtrinsicsV1";
356
357		let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
358		loop {
359			match self.system_fetch_extrinsics_v1(block_id, options.clone()).await {
360				Ok(x) => return Ok(x),
361				Err(err) if !retry_on_error => {
362					return Err(err);
363				},
364				Err(err) => {
365					let Some(duration) = sleep_duration.pop() else {
366						return Err(err);
367					};
368					sleep_on_retry(duration, MESSAGE, &err.to_string()).await;
369				},
370			};
371		}
372	}
373}