sc_rpc_spec_v2/common/
storage.rs1use std::{marker::PhantomData, sync::Arc};
22
23use sc_client_api::{Backend, ChildInfo, StorageKey, StorageProvider};
24use sp_runtime::traits::Block as BlockT;
25
26use super::events::{StorageResult, StorageResultType};
27use crate::hex_string;
28
29pub struct Storage<Client, Block, BE> {
31 client: Arc<Client>,
33 _phandom: PhantomData<(BE, Block)>,
34}
35
36impl<Client, Block, BE> Storage<Client, Block, BE> {
37 pub fn new(client: Arc<Client>) -> Self {
39 Self { client, _phandom: PhantomData }
40 }
41}
42
43pub struct QueryIter {
45 pub query_key: StorageKey,
47 pub pagination_start_key: Option<StorageKey>,
49 pub ty: IterQueryType,
51}
52
53pub enum IterQueryType {
55 Value,
57 Hash,
59}
60
61pub type QueryResult = Result<Option<StorageResult>, String>;
63
64pub type QueryIterResult = Result<(Vec<StorageResult>, Option<QueryIter>), String>;
66
67impl<Client, Block, BE> Storage<Client, Block, BE>
68where
69 Block: BlockT + 'static,
70 BE: Backend<Block> + 'static,
71 Client: StorageProvider<Block, BE> + 'static,
72{
73 pub fn query_value(
75 &self,
76 hash: Block::Hash,
77 key: &StorageKey,
78 child_key: Option<&ChildInfo>,
79 ) -> QueryResult {
80 let result = if let Some(child_key) = child_key {
81 self.client.child_storage(hash, child_key, key)
82 } else {
83 self.client.storage(hash, key)
84 };
85
86 result
87 .map(|opt| {
88 QueryResult::Ok(opt.map(|storage_data| StorageResult {
89 key: hex_string(&key.0),
90 result: StorageResultType::Value(hex_string(&storage_data.0)),
91 }))
92 })
93 .unwrap_or_else(|error| QueryResult::Err(error.to_string()))
94 }
95
96 pub fn query_hash(
98 &self,
99 hash: Block::Hash,
100 key: &StorageKey,
101 child_key: Option<&ChildInfo>,
102 ) -> QueryResult {
103 let result = if let Some(child_key) = child_key {
104 self.client.child_storage_hash(hash, child_key, key)
105 } else {
106 self.client.storage_hash(hash, key)
107 };
108
109 result
110 .map(|opt| {
111 QueryResult::Ok(opt.map(|storage_data| StorageResult {
112 key: hex_string(&key.0),
113 result: StorageResultType::Hash(hex_string(&storage_data.as_ref())),
114 }))
115 })
116 .unwrap_or_else(|error| QueryResult::Err(error.to_string()))
117 }
118
119 pub fn query_merkle_value(
121 &self,
122 hash: Block::Hash,
123 key: &StorageKey,
124 child_key: Option<&ChildInfo>,
125 ) -> QueryResult {
126 let result = if let Some(child_key) = child_key {
127 self.client.child_closest_merkle_value(hash, child_key, key)
128 } else {
129 self.client.closest_merkle_value(hash, key)
130 };
131
132 result
133 .map(|opt| {
134 QueryResult::Ok(opt.map(|storage_data| {
135 let result = match &storage_data {
136 sc_client_api::MerkleValue::Node(data) => hex_string(&data.as_slice()),
137 sc_client_api::MerkleValue::Hash(hash) => hex_string(&hash.as_ref()),
138 };
139
140 StorageResult {
141 key: hex_string(&key.0),
142 result: StorageResultType::ClosestDescendantMerkleValue(result),
143 }
144 }))
145 })
146 .unwrap_or_else(|error| QueryResult::Err(error.to_string()))
147 }
148
149 pub fn query_iter_pagination(
153 &self,
154 query: QueryIter,
155 hash: Block::Hash,
156 child_key: Option<&ChildInfo>,
157 count: usize,
158 ) -> QueryIterResult {
159 let QueryIter { ty, query_key, pagination_start_key } = query;
160
161 let mut keys_iter = if let Some(child_key) = child_key {
162 self.client.child_storage_keys(
163 hash,
164 child_key.to_owned(),
165 Some(&query_key),
166 pagination_start_key.as_ref(),
167 )
168 } else {
169 self.client.storage_keys(hash, Some(&query_key), pagination_start_key.as_ref())
170 }
171 .map_err(|err| err.to_string())?;
172
173 let mut ret = Vec::with_capacity(count);
174 let mut next_pagination_key = None;
175 for _ in 0..count {
176 let Some(key) = keys_iter.next() else { break };
177
178 next_pagination_key = Some(key.clone());
179
180 let result = match ty {
181 IterQueryType::Value => self.query_value(hash, &key, child_key),
182 IterQueryType::Hash => self.query_hash(hash, &key, child_key),
183 }?;
184
185 if let Some(value) = result {
186 ret.push(value);
187 }
188 }
189
190 let maybe_next_query = keys_iter.next().map(|_| QueryIter {
192 ty,
193 query_key,
194 pagination_start_key: next_pagination_key,
195 });
196 Ok((ret, maybe_next_query))
197 }
198}