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 grandpa_block_justification_json(
309 &self,
310 at: u32,
311 ) -> Result<Option<GrandpaJustification>, avail_rust_core::Error> {
312 let result = rpc::grandpa::block_justification_json(&self.client.rpc_client, at).await?;
313 let Some(result) = result else {
314 return Ok(None);
315 };
316
317 let justification: GrandpaJustification = serde_json::from_str(result.as_str()).map_err(|e| e.to_string())?;
318 Ok(Some(justification))
319 }
320
321 pub async fn grandpa_block_justification_json_ext(
322 &self,
323 at: u32,
324 retry_on_error: bool,
325 ) -> Result<Option<GrandpaJustification>, avail_rust_core::Error> {
326 const MESSAGE: &str = "Failed to execute RPC: grandpa_blockJustificationJson";
327
328 let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
329 let result = loop {
330 match rpc::grandpa::block_justification_json(&self.client.rpc_client, at).await {
331 Ok(x) => break x,
332 Err(err) if !retry_on_error => {
333 return Err(err.into());
334 },
335 Err(err) => {
336 let Some(duration) = sleep_duration.pop() else {
337 return Err(err.into());
338 };
339 sleep_on_retry(duration, MESSAGE, &err.to_string()).await;
340 },
341 };
342 };
343
344 let Some(result) = result else {
345 return Ok(None);
346 };
347
348 let justification: GrandpaJustification = serde_json::from_str(result.as_str()).map_err(|e| e.to_string())?;
349 Ok(Some(justification))
350 }
351
352 pub async fn system_fetch_events_v1(
353 &self,
354 at: H256,
355 options: fetch_events_v1_types::Options,
356 ) -> Result<fetch_events_v1_types::Output, avail_rust_core::Error> {
357 Ok(rpc::system::fetch_events_v1(&self.client.rpc_client, at, Some(options)).await?)
358 }
359
360 pub async fn system_fetch_events_v1_ext(
361 &self,
362 at: H256,
363 options: fetch_events_v1_types::Options,
364 retry_on_error: bool,
365 ) -> Result<fetch_events_v1_types::Output, avail_rust_core::Error> {
366 const MESSAGE: &str = "Failed to execute RPC: system_FetchEventsV1";
367
368 let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
369 loop {
370 match self.system_fetch_events_v1(at, options.clone()).await {
371 Ok(x) => return Ok(x),
372 Err(err) if !retry_on_error => {
373 return Err(err);
374 },
375 Err(err) => {
376 let Some(duration) = sleep_duration.pop() else {
377 return Err(err);
378 };
379 sleep_on_retry(duration, MESSAGE, &err.to_string()).await;
380 },
381 };
382 }
383 }
384
385 pub async fn system_fetch_extrinsics_v1(
386 &self,
387 block_id: HashNumber,
388 options: fetch_extrinsics_v1_types::Options,
389 ) -> Result<fetch_extrinsics_v1_types::Output, avail_rust_core::Error> {
390 Ok(rpc::system::fetch_extrinsics_v1(&self.client.rpc_client, block_id, Some(options)).await?)
391 }
392
393 pub async fn system_fetch_extrinsics_v1_ext(
394 &self,
395 block_id: HashNumber,
396 options: fetch_extrinsics_v1_types::Options,
397 retry_on_error: bool,
398 ) -> Result<fetch_extrinsics_v1_types::Output, avail_rust_core::Error> {
399 const MESSAGE: &str = "Failed to execute RPC: system_FetchExtrinsicsV1";
400
401 let mut sleep_duration: Vec<u64> = vec![8, 5, 3, 2, 1];
402 loop {
403 match self.system_fetch_extrinsics_v1(block_id, options.clone()).await {
404 Ok(x) => return Ok(x),
405 Err(err) if !retry_on_error => {
406 return Err(err);
407 },
408 Err(err) => {
409 let Some(duration) = sleep_duration.pop() else {
410 return Err(err);
411 };
412 sleep_on_retry(duration, MESSAGE, &err.to_string()).await;
413 },
414 };
415 }
416 }
417}