|
1 | 1 | //! StorageHub RPC client implementation |
2 | 2 |
|
3 | | -use std::{future::Future, sync::Arc}; |
| 3 | +use std::sync::Arc; |
4 | 4 |
|
5 | 5 | use bigdecimal::BigDecimal; |
| 6 | +use codec::Decode; |
6 | 7 | use jsonrpsee::core::traits::ToRpcParams; |
7 | 8 | use serde::de::DeserializeOwned; |
8 | | -use subxt::{ |
9 | | - dynamic::{DecodedValueThunk, Value}, |
10 | | - storage::Address, |
11 | | - utils::Yes, |
12 | | - OnlineClient, PolkadotConfig, |
13 | | -}; |
14 | 9 | use tracing::debug; |
15 | 10 |
|
16 | | -// use pallet_storage_providers::types::MainStorageProvider; |
17 | | -// use sh_solochain_evm_runtime::Runtime; |
18 | 11 | use shc_indexer_db::OnchainMspId; |
19 | 12 | use shc_rpc::{ |
20 | 13 | GetFileFromFileStorageResult, GetValuePropositionsResult, RpcProviderId, SaveFileToDisk, |
21 | 14 | }; |
22 | | -// use sp_core::{blake2_256, storage::StorageKey, twox_128}; |
| 15 | +use sp_core::storage::StorageKey; |
23 | 16 |
|
24 | 17 | use crate::data::rpc::{ |
25 | 18 | connection::error::{RpcConnectionError, RpcResult}, |
@@ -86,20 +79,32 @@ impl StorageHubRpcClient { |
86 | 79 | /// |
87 | 80 | /// # Arguments: |
88 | 81 | /// - `key` is the storage key to attempt reading |
89 | | - /// - `transform` is a closure to transform the raw storage value returned by the API into the target type |
90 | | - pub async fn query_storage<K, F, FT, R>(&self, key: K, transform: F) -> RpcResult<Option<R>> |
| 82 | + pub async fn query_storage<R>(&self, key: StorageKey) -> RpcResult<Option<R>> |
91 | 83 | where |
92 | | - K: Address<Target = DecodedValueThunk, IsFetchable = Yes>, |
93 | | - FT: Future<Output = RpcResult<Option<R>>>, |
94 | | - F: Fn(Result<Option<K::Target>, subxt::Error>) -> FT, |
| 84 | + R: Decode, |
95 | 85 | { |
96 | | - //FIXME: replace Config for DH/SH one |
97 | | - let api = |
98 | | - OnlineClient::<PolkadotConfig>::from_rpc_client(Arc::clone(&self.connection)).await?; |
| 86 | + let encoded = format!("0x{}", hex::encode(&key.0)); |
| 87 | + debug!(key = encoded, "reading storage"); |
| 88 | + |
| 89 | + let response = self |
| 90 | + .call::<_, Option<String>>(methods::STATE_QUERY, jsonrpsee::rpc_params![encoded]) |
| 91 | + .await?; |
| 92 | + |
| 93 | + let Some(response) = response else { |
| 94 | + return Ok(None); |
| 95 | + }; |
99 | 96 |
|
100 | | - let result = api.storage().at_latest().await?.fetch(&key).await; |
| 97 | + // the RPC replies with scale-encoded response as a hex string |
| 98 | + let response = hex::decode(response.trim_start_matches("0x")).map_err(|e| { |
| 99 | + RpcConnectionError::Serialization(format!( |
| 100 | + "RPC runtime API did not respond with a valid hex string: {}", |
| 101 | + e.to_string() |
| 102 | + )) |
| 103 | + })?; |
101 | 104 |
|
102 | | - transform(result).await |
| 105 | + R::decode(&mut response.as_slice()) |
| 106 | + .map(Some) |
| 107 | + .map_err(|e| RpcConnectionError::Serialization(e.to_string())) |
103 | 108 | } |
104 | 109 |
|
105 | 110 | /// Call a JSON-RPC method on the connected node |
@@ -138,47 +143,28 @@ impl StorageHubRpcClient { |
138 | 143 | .map(|price| price.into()) |
139 | 144 | } |
140 | 145 |
|
141 | | - /// Retrieve the current available capacity for given provider, in storage units |
142 | | - pub async fn get_available_capacity(&self, provider: OnchainMspId) -> RpcResult<BigDecimal> { |
143 | | - debug!(target: "rpc::client::get_available_capacity", "Runtime API: get_available_capacity"); |
| 146 | + /// Retrieve the current number of active users |
| 147 | + pub async fn get_number_of_active_users(&self, provider: OnchainMspId) -> RpcResult<usize> { |
| 148 | + debug!(target: "rpc::client::get_number_of_active_users", "Runtime API: get_users_of_payment_streams_of_provider"); |
144 | 149 |
|
145 | | - self.call_runtime_api::<_, runtime_apis::AvailableCapacity>( |
146 | | - runtime_apis::AVAILABLE_CAPACITY, |
| 150 | + self.call_runtime_api::<_, runtime_apis::NumOfUsers>( |
| 151 | + runtime_apis::NUM_OF_USERS, |
147 | 152 | provider.as_h256(), |
148 | 153 | ) |
149 | 154 | .await |
150 | | - .map(|capacity| capacity.into()) |
| 155 | + .map(|users| users.len()) |
151 | 156 | } |
152 | 157 |
|
153 | 158 | /// Retrieve the MSP information for the given provider |
154 | 159 | /// |
155 | 160 | /// This function will read into the chain state from the Provider pallet's MainStorageProviders map |
156 | | - // TODO: replace return value with proper typing from runtime |
157 | 161 | pub async fn get_msp_info( |
158 | 162 | &self, |
159 | 163 | provider: OnchainMspId, |
160 | 164 | ) -> RpcResult<Option<state_queries::MspInfo>> { |
161 | 165 | debug!(target: "rpc::client::get_msp", provider = %provider, "State Query: get_msp_info"); |
162 | | - let key = subxt::dynamic::storage( |
163 | | - state_queries::MSP_INFO_MODULE, |
164 | | - state_queries::MSP_INFO_METHOD, |
165 | | - vec![Value::from_bytes(provider.as_bytes())], |
166 | | - ); |
167 | | - |
168 | | - self.query_storage(key, |storage| async move { |
169 | | - let Some(_value) = storage? |
170 | | - .map(|storage| storage.to_value()) |
171 | | - .transpose() |
172 | | - .map_err(subxt::Error::from)? |
173 | | - else { |
174 | | - return Ok(None); |
175 | | - }; |
176 | | - |
177 | | - //FIXME: convert to MspInfo |
178 | | - |
179 | | - Ok(None) |
180 | | - }) |
181 | | - .await |
| 166 | + self.query_storage(state_queries::msp_info_key(provider)) |
| 167 | + .await |
182 | 168 | } |
183 | 169 |
|
184 | 170 | /// Returns whether the given `file_key` is expected to be received by the MSP node |
|
0 commit comments