Skip to content

Commit 4c09dbc

Browse files
committed
refactor: ditch subxt, import runtime
1 parent b66af47 commit 4c09dbc

File tree

13 files changed

+190
-763
lines changed

13 files changed

+190
-763
lines changed

Cargo.lock

Lines changed: 61 additions & 546 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ axum-test = "18"
5656
base64 = "0.21"
5757
bigdecimal = { version = "0.4.5", features = ["serde"] }
5858
bincode = "1.3.3"
59+
cfg-if = { version = "1.0.4" }
5960
clap = { version = "4.5.3", features = ["derive", "env"] }
6061
chrono = "0.4"
6162
codec = { package = "parity-scale-codec", version = "3.0.0", features = [

backend/lib/Cargo.toml

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ axum-extra = { workspace = true }
1313
axum-jwt = { workspace = true }
1414
base64 = { workspace = true }
1515
bigdecimal = { workspace = true }
16+
cfg-if = { workspace = true }
1617
chrono = { workspace = true, features = ["serde"] }
18+
codec = { workspace = true }
1719
diesel = { workspace = true }
1820
diesel-async = { workspace = true }
1921
futures = { workspace = true }
22+
frame-support = { workspace = true }
2023
headers = { workspace = true }
2124
hex = { workspace = true }
2225
hex-literal = { workspace = true }
@@ -30,7 +33,6 @@ rustls-pemfile = { workspace = true }
3033
rustls-platform-verifier = { workspace = true }
3134
serde = { workspace = true }
3235
serde_json = { workspace = true }
33-
subxt = { workspace = true, features = ["native", "jsonrpsee"] }
3436
thiserror = { workspace = true }
3537
tokio = { workspace = true, features = ["full"] }
3638
tokio-stream = { workspace = true }
@@ -40,15 +42,14 @@ tower-http = { workspace = true }
4042
tracing = { workspace = true }
4143
tracing-bunyan-formatter = { workspace = true }
4244
tracing-subscriber = { workspace = true }
45+
trie-db = { workspace = true }
4346
tokio-postgres = { workspace = true }
4447
tokio-postgres-rustls = { workspace = true }
4548
uuid = { version = "1.18", features = ["v7"] }
4649

4750
# Workspace dependencies
48-
codec = { workspace = true }
4951
sc-network = { workspace = true }
5052
sc-network-types = { workspace = true }
51-
# sh-solochain-evm-runtime = { workspace = true, features = ["std"] }
5253
shc-common = { workspace = true, default-features = true }
5354
shc-file-manager = { workspace = true }
5455
shc-indexer-db = { workspace = true, default-features = true }
@@ -59,8 +60,10 @@ shp-types = { workspace = true }
5960
sp-core = { workspace = true }
6061
sp-runtime = { workspace = true }
6162
sp-trie = { workspace = true }
62-
# pallet-storage-providers = { workspace = true, features = ["std"] }
63-
trie-db = { workspace = true }
63+
pallet-storage-providers = { workspace = true, features = ["std"] }
64+
65+
# Optional deps
66+
sh-solochain-evm-runtime = { workspace = true, features = ["std"], optional = true }
6467

6568
[dev-dependencies]
6669
alloy-signer = "0.8"
@@ -72,5 +75,8 @@ testcontainers = "0.24"
7275
testcontainers-modules = { version = "0.12", features = ["postgres"] }
7376

7477
[features]
75-
default = []
76-
mocks = []
78+
default = ["solochain"]
79+
mocks = ["solochain"]
80+
81+
# Runtime selection
82+
solochain = ["dep:sh-solochain-evm-runtime"]

backend/lib/src/data/rpc/client.rs

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
11
//! StorageHub RPC client implementation
22
3-
use std::{future::Future, sync::Arc};
3+
use std::sync::Arc;
44

55
use bigdecimal::BigDecimal;
6+
use codec::Decode;
67
use jsonrpsee::core::traits::ToRpcParams;
78
use serde::de::DeserializeOwned;
8-
use subxt::{
9-
dynamic::{DecodedValueThunk, Value},
10-
storage::Address,
11-
utils::Yes,
12-
OnlineClient, PolkadotConfig,
13-
};
149
use tracing::debug;
1510

16-
// use pallet_storage_providers::types::MainStorageProvider;
17-
// use sh_solochain_evm_runtime::Runtime;
1811
use shc_indexer_db::OnchainMspId;
1912
use shc_rpc::{
2013
GetFileFromFileStorageResult, GetValuePropositionsResult, RpcProviderId, SaveFileToDisk,
2114
};
22-
// use sp_core::{blake2_256, storage::StorageKey, twox_128};
15+
use sp_core::storage::StorageKey;
2316

2417
use crate::data::rpc::{
2518
connection::error::{RpcConnectionError, RpcResult},
@@ -86,20 +79,32 @@ impl StorageHubRpcClient {
8679
///
8780
/// # Arguments:
8881
/// - `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>>
9183
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,
9585
{
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+
};
9996

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+
})?;
101104

102-
transform(result).await
105+
R::decode(&mut response.as_slice())
106+
.map(Some)
107+
.map_err(|e| RpcConnectionError::Serialization(e.to_string()))
103108
}
104109

105110
/// Call a JSON-RPC method on the connected node
@@ -138,47 +143,28 @@ impl StorageHubRpcClient {
138143
.map(|price| price.into())
139144
}
140145

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");
144149

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,
147152
provider.as_h256(),
148153
)
149154
.await
150-
.map(|capacity| capacity.into())
155+
.map(|users| users.len())
151156
}
152157

153158
/// Retrieve the MSP information for the given provider
154159
///
155160
/// 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
157161
pub async fn get_msp_info(
158162
&self,
159163
provider: OnchainMspId,
160164
) -> RpcResult<Option<state_queries::MspInfo>> {
161165
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
182168
}
183169

184170
/// Returns whether the given `file_key` is expected to be received by the MSP node

backend/lib/src/data/rpc/connection/error.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,36 +28,6 @@ pub enum RpcConnectionError {
2828
Other(String),
2929
}
3030

31-
impl From<subxt::Error> for RpcConnectionError {
32-
fn from(value: subxt::Error) -> Self {
33-
match value {
34-
subxt::Error::Io(error) => Self::Transport(error.to_string()),
35-
subxt::Error::Rpc(rpc_error) => Self::Rpc(rpc_error.to_string()),
36-
err @ subxt::Error::Runtime(_) | err @ subxt::Error::Transaction(_) => {
37-
Self::Other(err.to_string())
38-
}
39-
err @ subxt::Error::Metadata(_)
40-
| err @ subxt::Error::Block(_)
41-
| err @ subxt::Error::Codec(_)
42-
| err @ subxt::Error::MetadataDecoding(_)
43-
| err @ subxt::Error::Extrinsic(_)
44-
| err @ subxt::Error::StorageAddress(_)
45-
| err @ subxt::Error::Serialization(_)
46-
| err @ subxt::Error::Decode(_)
47-
| err @ subxt::Error::Encode(_) => Self::Serialization(err.to_string()),
48-
subxt::Error::Unknown(items) => Self::Serialization(format!(
49-
"Unable to decode received data: {}",
50-
hex::encode(items)
51-
)),
52-
subxt::Error::Other(other) => Self::Other(other),
53-
unknown_variant => Self::Other(format!(
54-
"Unknown error received from subxt: {:?}",
55-
unknown_variant
56-
)),
57-
}
58-
}
59-
}
60-
6131
/// Result type for RPC operations
6232
pub type RpcResult<T> = Result<T, RpcConnectionError>;
6333

backend/lib/src/data/rpc/connection/mod.rs

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ use std::fmt::Debug;
55
use async_trait::async_trait;
66
use jsonrpsee::core::traits::ToRpcParams;
77
use serde::de::DeserializeOwned;
8-
use serde_json::value::RawValue;
9-
use subxt::backend::rpc::RpcClientT;
108

119
#[cfg(feature = "mocks")]
1210
use crate::data::rpc::mock_connection::MockConnection;
@@ -81,48 +79,3 @@ impl RpcConnection for AnyRpcConnection {
8179
}
8280
}
8381
}
84-
85-
struct Params(Option<Box<RawValue>>);
86-
87-
impl ToRpcParams for Params {
88-
fn to_rpc_params(self) -> Result<Option<Box<RawValue>>, serde_json::Error> {
89-
Ok(self.0)
90-
}
91-
}
92-
93-
// FIXME: implement
94-
#[allow(unused_variables)]
95-
impl RpcClientT for AnyRpcConnection {
96-
fn request_raw<'a>(
97-
&'a self,
98-
method: &'a str,
99-
params: Option<Box<RawValue>>,
100-
) -> subxt::backend::rpc::RawRpcFuture<'a, Box<RawValue>> {
101-
Box::pin(async move {
102-
match self {
103-
AnyRpcConnection::Real(conn) => {
104-
conn.call(method, Params(params)).await.map_err(|e| todo!())
105-
}
106-
#[cfg(feature = "mocks")]
107-
AnyRpcConnection::Mock(conn) => {
108-
conn.call(method, Params(params)).await.map_err(|e| todo!())
109-
}
110-
}
111-
})
112-
}
113-
114-
fn subscribe_raw<'a>(
115-
&'a self,
116-
sub: &'a str,
117-
params: Option<Box<RawValue>>,
118-
unsub: &'a str,
119-
) -> subxt::backend::rpc::RawRpcFuture<'a, subxt::backend::rpc::RawRpcSubscription> {
120-
Box::pin(async move {
121-
match self {
122-
AnyRpcConnection::Real(ws_connection) => todo!(),
123-
#[cfg(feature = "mocks")]
124-
AnyRpcConnection::Mock(conn) => todo!(),
125-
}
126-
})
127-
}
128-
}

backend/lib/src/data/rpc/mock_connection.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use tokio::{
1616
};
1717
use tracing::{debug, error};
1818

19+
use frame_support::storage::StoragePrefixedMap;
1920
use shc_common::types::FileMetadata;
2021
use shc_rpc::{
2122
GetFileFromFileStorageResult, GetValuePropositionsResult, RpcProviderId, SaveFileToDisk,
@@ -30,7 +31,7 @@ use crate::{
3031
},
3132
data::rpc::{
3233
connection::error::{RpcConnectionError, RpcResult},
33-
methods, runtime_apis, state_queries, RpcConnection,
34+
methods, runtime_apis, RpcConnection,
3435
},
3536
models::msp_info::{ValueProposition, ValuePropositionWithId},
3637
test_utils::random_bytes_32,
@@ -159,9 +160,9 @@ impl MockConnection {
159160
let price = format!("0x{}", hex::encode(MOCK_PRICE_PER_GIGA_UNIT.encode()));
160161
serde_json::json!(price)
161162
}
162-
runtime_apis::AVAILABLE_CAPACITY => {
163-
// SCALE-encoded DUMMY MSP capacity
164-
serde_json::json!("0x006db3fc1f00000000")
163+
runtime_apis::NUM_OF_USERS => {
164+
// SCALE-encoded DUMMY MSP users list
165+
serde_json::json!("0x040b17ca3a1454cd058b231090c6fd635dd348659a")
165166
}
166167
api => {
167168
error!(api= %hex::encode(api), "no mock registered for requested runtime api");
@@ -185,7 +186,10 @@ impl MockConnection {
185186

186187
match storage_key {
187188
// we just always return the same MSP for this query
188-
msp if msp.starts_with(state_queries::MSP_INFO_KEY_PREFIX.as_slice()) => {
189+
msp if msp.starts_with(
190+
crate::runtime::MainStorageProvidersStorageMap::final_prefix().as_slice(),
191+
) =>
192+
{
189193
// this is some sample data returned by the RPC during tests
190194
// it should be the SCALE-encoded MainStorageProvider for the solochain runtime
191195
serde_json::json!("0x0000002000000000934c0300000000000449012f6970342f3137322e31382e302e332f7463702f33303335302f7032702f313244334b6f6f575355767a38514d35583474664161534c4572415a6a523270756f6a6f313670554c42487971544d474b744e5601000000000000000000000000000000010000000d0000004c31b93792ab99e2553bff747199b7a4951185b24c31b93792ab99e2553bff747199b7a4951185b20d000000")
@@ -328,11 +332,13 @@ impl RpcConnection for MockConnection {
328332
}
329333
methods::API_CALL => self.mock_runtime_apis(params).await,
330334
methods::STATE_QUERY => self.mock_state_queries(params).await,
331-
_ => {
335+
method => {
332336
let responses = self.responses.read().await;
333-
responses
337+
let response = responses
334338
.get(method)
335-
.cloned()
339+
.cloned();
340+
341+
response
336342
.unwrap_or(serde_json::json!(null))
337343
}
338344
};

backend/lib/src/data/rpc/runtime_apis.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub const CURRENT_PRICE: &str = "PaymentStreamsApi_get_current_price_per_giga_un
88
// TODO: get type from runtime
99
pub type CurrentPrice = u128;
1010

11-
pub const AVAILABLE_CAPACITY: &str = "StorageProvidersApi_query_available_storage_capacity";
11+
pub const NUM_OF_USERS: &str = "PaymentStreamsApi_get_users_of_payment_streams_of_provider";
1212

1313
// TODO: get type from runtime
14-
pub type AvailableCapacity = u64;
14+
pub type NumOfUsers = Vec<crate::runtime::AccountId>;

0 commit comments

Comments
 (0)