1use crate::{
14 api::Result,
15 rpc::{Request, Subscribe},
16 Api, ReadProof,
17};
18use ac_compose_macros::rpc_params;
19use ac_node_api::MetadataError;
20use ac_primitives::config::Config;
21#[cfg(all(not(feature = "sync-api"), not(feature = "std")))]
22use alloc::boxed::Box;
23use alloc::{borrow::ToOwned, string::String, vec, vec::Vec};
24use codec::{Decode, Encode};
25use core::cmp;
26use log::*;
27use serde::de::DeserializeOwned;
28use sp_storage::{StorageChangeSet, StorageData, StorageKey};
29
30const STORAGE_KEYS_PAGED_MAX_COUNT: u32 = 1000;
33
34pub type StorageChangeSetSubscriptionFor<Client, Hash> =
35 <Client as Subscribe>::Subscription<StorageChangeSet<Hash>>;
36
37#[maybe_async::maybe_async(?Send)]
39pub trait GetStorage {
40 type Hash;
41 async fn get_storage<V: Decode>(
45 &self,
46 pallet: &'static str,
47 storage_item: &'static str,
48 at_block: Option<Self::Hash>,
49 ) -> Result<Option<V>>;
50
51 async fn get_storage_map<K: Encode, V: Decode>(
55 &self,
56 pallet: &'static str,
57 storage_item: &'static str,
58 map_key: K,
59 at_block: Option<Self::Hash>,
60 ) -> Result<Option<V>>;
61
62 async fn get_storage_map_key_prefix(
64 &self,
65 pallet: &'static str,
66 storage_item: &'static str,
67 ) -> Result<StorageKey>;
68
69 async fn get_storage_double_map_key_prefix<K: Encode>(
70 &self,
71 storage_prefix: &'static str,
72 storage_key_name: &'static str,
73 first: K,
74 ) -> Result<StorageKey>;
75
76 async fn get_storage_double_map<K: Encode, Q: Encode, V: Decode>(
80 &self,
81 pallet: &'static str,
82 storage_item: &'static str,
83 first_double_map_key: K,
84 second_double_map_key: Q,
85 at_block: Option<Self::Hash>,
86 ) -> Result<Option<V>>;
87
88 async fn get_storage_by_key<V: Decode>(
92 &self,
93 storage_key: StorageKey,
94 at_block: Option<Self::Hash>,
95 ) -> Result<Option<V>>;
96
97 async fn get_storage_keys_paged_limited(
106 &self,
107 prefix: Option<StorageKey>,
108 count: u32,
109 start_key: Option<StorageKey>,
110 at_block: Option<Self::Hash>,
111 ) -> Result<Vec<StorageKey>>;
112
113 async fn get_storage_keys_paged(
120 &self,
121 prefix: Option<StorageKey>,
122 count: u32,
123 start_key: Option<StorageKey>,
124 at_block: Option<Self::Hash>,
125 ) -> Result<Vec<StorageKey>>;
126
127 async fn get_opaque_storage_by_key(
131 &self,
132 storage_key: StorageKey,
133 at_block: Option<Self::Hash>,
134 ) -> Result<Option<Vec<u8>>>;
135
136 async fn get_storage_value_proof(
140 &self,
141 pallet: &'static str,
142 storage_item: &'static str,
143 at_block: Option<Self::Hash>,
144 ) -> Result<Option<ReadProof<Self::Hash>>>;
145
146 async fn get_storage_map_proof<K: Encode>(
150 &self,
151 pallet: &'static str,
152 storage_item: &'static str,
153 map_key: K,
154 at_block: Option<Self::Hash>,
155 ) -> Result<Option<ReadProof<Self::Hash>>>;
156
157 async fn get_storage_double_map_proof<K: Encode, Q: Encode>(
161 &self,
162 pallet: &'static str,
163 storage_item: &'static str,
164 first_double_map_key: K,
165 second_double_map_key: Q,
166 at_block: Option<Self::Hash>,
167 ) -> Result<Option<ReadProof<Self::Hash>>>;
168
169 async fn get_storage_proof_by_keys(
173 &self,
174 keys: Vec<StorageKey>,
175 at_block: Option<Self::Hash>,
176 ) -> Result<Option<ReadProof<Self::Hash>>>;
177
178 async fn get_keys(
179 &self,
180 key: StorageKey,
181 at_block: Option<Self::Hash>,
182 ) -> Result<Option<Vec<String>>>;
183
184 async fn get_constant<C: Decode>(
185 &self,
186 pallet: &'static str,
187 constant: &'static str,
188 ) -> Result<C>;
189}
190
191#[maybe_async::maybe_async(?Send)]
192impl<T, Client> GetStorage for Api<T, Client>
193where
194 T: Config,
195 Client: Request,
196{
197 type Hash = T::Hash;
198
199 async fn get_storage<V: Decode>(
200 &self,
201 pallet: &'static str,
202 storage_item: &'static str,
203 at_block: Option<Self::Hash>,
204 ) -> Result<Option<V>> {
205 let storagekey = self.metadata().storage_value_key(pallet, storage_item)?;
206 info!("storage key is: 0x{}", hex::encode(&storagekey));
207 self.get_storage_by_key(storagekey, at_block).await
208 }
209
210 async fn get_storage_map<K: Encode, V: Decode>(
211 &self,
212 pallet: &'static str,
213 storage_item: &'static str,
214 map_key: K,
215 at_block: Option<Self::Hash>,
216 ) -> Result<Option<V>> {
217 let storagekey = self.metadata().storage_map_key::<K>(pallet, storage_item, map_key)?;
218 info!("storage key is: 0x{}", hex::encode(&storagekey));
219 self.get_storage_by_key(storagekey, at_block).await
220 }
221
222 async fn get_storage_map_key_prefix(
223 &self,
224 pallet: &'static str,
225 storage_item: &'static str,
226 ) -> Result<StorageKey> {
227 self.metadata()
228 .storage_map_key_prefix(pallet, storage_item)
229 .map_err(|e| e.into())
230 }
231
232 async fn get_storage_double_map<K: Encode, Q: Encode, V: Decode>(
233 &self,
234 pallet: &'static str,
235 storage_item: &'static str,
236 first_double_map_key: K,
237 second_double_map_key: Q,
238 at_block: Option<Self::Hash>,
239 ) -> Result<Option<V>> {
240 let storagekey = self.metadata().storage_double_map_key::<K, Q>(
241 pallet,
242 storage_item,
243 first_double_map_key,
244 second_double_map_key,
245 )?;
246 info!("storage key is: 0x{}", hex::encode(&storagekey));
247 self.get_storage_by_key(storagekey, at_block).await
248 }
249
250 async fn get_storage_double_map_key_prefix<K: Encode>(
251 &self,
252 storage_prefix: &'static str,
253 storage_key_name: &'static str,
254 first: K,
255 ) -> Result<StorageKey> {
256 self.metadata()
257 .storage_double_map_key_prefix(storage_prefix, storage_key_name, first)
258 .map_err(|e| e.into())
259 }
260
261 async fn get_storage_by_key<V: Decode>(
262 &self,
263 storage_key: StorageKey,
264 at_block: Option<Self::Hash>,
265 ) -> Result<Option<V>> {
266 let s = self.get_opaque_storage_by_key(storage_key, at_block).await?;
267 match s {
268 Some(storage) => Ok(Some(Decode::decode(&mut storage.as_slice())?)),
269 None => Ok(None),
270 }
271 }
272
273 async fn get_storage_keys_paged_limited(
274 &self,
275 storage_key_prefix: Option<StorageKey>,
276 count: u32,
277 start_key: Option<StorageKey>,
278 at_block: Option<Self::Hash>,
279 ) -> Result<Vec<StorageKey>> {
280 let storage = self
281 .client()
282 .request(
283 "state_getKeysPaged",
284 rpc_params![storage_key_prefix, count, start_key, at_block],
285 )
286 .await?;
287 Ok(storage)
288 }
289
290 async fn get_storage_keys_paged(
291 &self,
292 storage_key_prefix: Option<StorageKey>,
293 count: u32,
294 start_key: Option<StorageKey>,
295 at_block: Option<Self::Hash>,
296 ) -> Result<Vec<StorageKey>> {
297 let mut storage_keys: Vec<StorageKey> = Vec::new();
298 let mut keys_left_to_fetch = count;
299 let mut new_start_key = start_key;
300
301 while keys_left_to_fetch > 0 {
302 let new_count = cmp::min(STORAGE_KEYS_PAGED_MAX_COUNT, keys_left_to_fetch);
303 let mut keys = self
304 .get_storage_keys_paged_limited(
305 storage_key_prefix.clone(),
306 new_count,
307 new_start_key,
308 at_block,
309 )
310 .await?;
311 let num_keys = keys.len() as u32;
312 storage_keys.append(&mut keys);
313 if num_keys < new_count {
314 break
315 }
316 keys_left_to_fetch -= new_count;
317 new_start_key = keys.last().map(|x| x.to_owned());
318 }
319
320 Ok(storage_keys)
321 }
322
323 async fn get_opaque_storage_by_key(
324 &self,
325 storage_key: StorageKey,
326 at_block: Option<Self::Hash>,
327 ) -> Result<Option<Vec<u8>>> {
328 let storage: Option<StorageData> = self
329 .client()
330 .request("state_getStorage", rpc_params![storage_key, at_block])
331 .await?;
332 Ok(storage.map(|storage_data| storage_data.0))
333 }
334
335 async fn get_storage_value_proof(
336 &self,
337 pallet: &'static str,
338 storage_item: &'static str,
339 at_block: Option<Self::Hash>,
340 ) -> Result<Option<ReadProof<Self::Hash>>> {
341 let storagekey = self.metadata().storage_value_key(pallet, storage_item)?;
342 info!("storage key is: 0x{}", hex::encode(&storagekey));
343 self.get_storage_proof_by_keys(vec![storagekey], at_block).await
344 }
345
346 async fn get_storage_map_proof<K: Encode>(
347 &self,
348 pallet: &'static str,
349 storage_item: &'static str,
350 map_key: K,
351 at_block: Option<Self::Hash>,
352 ) -> Result<Option<ReadProof<Self::Hash>>> {
353 let storagekey = self.metadata().storage_map_key::<K>(pallet, storage_item, map_key)?;
354 info!("storage key is: 0x{}", hex::encode(&storagekey));
355 self.get_storage_proof_by_keys(vec![storagekey], at_block).await
356 }
357
358 async fn get_storage_double_map_proof<K: Encode, Q: Encode>(
359 &self,
360 pallet: &'static str,
361 storage_item: &'static str,
362 first_double_map_key: K,
363 second_double_map_key: Q,
364 at_block: Option<Self::Hash>,
365 ) -> Result<Option<ReadProof<Self::Hash>>> {
366 let storage_key = self.metadata().storage_double_map_key::<K, Q>(
367 pallet,
368 storage_item,
369 first_double_map_key,
370 second_double_map_key,
371 )?;
372 info!("storage key is: 0x{}", hex::encode(&storage_key));
373 self.get_storage_proof_by_keys(vec![storage_key], at_block).await
374 }
375
376 async fn get_storage_proof_by_keys(
377 &self,
378 storage_keys: Vec<StorageKey>,
379 at_block: Option<Self::Hash>,
380 ) -> Result<Option<ReadProof<Self::Hash>>> {
381 let proof = self
382 .client()
383 .request("state_getReadProof", rpc_params![storage_keys, at_block])
384 .await?;
385 Ok(proof)
386 }
387
388 async fn get_keys(
389 &self,
390 storage_key: StorageKey,
391 at_block: Option<Self::Hash>,
392 ) -> Result<Option<Vec<String>>> {
393 let keys = self
394 .client()
395 .request("state_getKeys", rpc_params![storage_key, at_block])
396 .await?;
397 Ok(keys)
398 }
399
400 async fn get_constant<C: Decode>(
401 &self,
402 pallet: &'static str,
403 constant: &'static str,
404 ) -> Result<C> {
405 let c = self
406 .metadata()
407 .pallet_by_name_err(pallet)?
408 .constant_by_name(constant)
409 .ok_or(MetadataError::ConstantNotFound(constant))?;
410
411 Ok(Decode::decode(&mut c.value.as_slice())?)
412 }
413}
414
415#[maybe_async::maybe_async(?Send)]
416pub trait SubscribeState {
417 type Client: Subscribe;
418 type Hash: DeserializeOwned;
419
420 async fn subscribe_state(
421 &self,
422 pallet: &str,
423 storage_key: &str,
424 ) -> Result<StorageChangeSetSubscriptionFor<Self::Client, Self::Hash>>;
425}
426
427#[maybe_async::maybe_async(?Send)]
428impl<T, Client> SubscribeState for Api<T, Client>
429where
430 T: Config,
431 Client: Subscribe,
432{
433 type Client = Client;
434 type Hash = T::Hash;
435
436 async fn subscribe_state(
437 &self,
438 pallet: &str,
439 storage_key_name: &str,
440 ) -> Result<StorageChangeSetSubscriptionFor<Self::Client, Self::Hash>> {
441 debug!("subscribing to events");
442 let key = crate::storage_key(pallet, storage_key_name);
443 self.client()
444 .subscribe("state_subscribeStorage", rpc_params![vec![key]], "state_unsubscribeStorage")
445 .await
446 .map_err(|e| e.into())
447 }
448}