WIP integrating new frame-decode and working out new storage APIS

This commit is contained in:
James Wilson
2025-09-24 16:38:48 +01:00
parent 9080b0b2ae
commit 9d5c1d5a24
21 changed files with 695 additions and 633 deletions
+1 -1
View File
@@ -76,7 +76,7 @@ pub mod metadata {
/// Submit dynamic transactions.
pub mod dynamic {
pub use subxt_core::dynamic::{
At, DecodedValue, DecodedValueThunk, Value, constant, runtime_api_call, storage, tx,
At, DecodedValue, DecodedValueThunk, Value, constant, runtime_api_call, tx, // storage // TODO re-add
view_function_call,
};
}
+89 -6
View File
@@ -4,11 +4,94 @@
//! Types associated with accessing and working with storage items.
mod storage_client;
mod storage_type;
// mod storage_client;
// mod storage_type;
pub use storage_client::StorageClient;
pub use storage_type::{Storage, StorageKeyValuePair};
pub use subxt_core::storage::address::{
Address, DefaultAddress, DynamicAddress, StaticAddress, StaticStorageKey, StorageKey, dynamic,
// pub use storage_client::StorageClient;
// pub use storage_type::{Storage, StorageKeyValuePair};
// pub use subxt_core::storage::address::{
// Address, DefaultAddress, DynamicAddress, StaticAddress, StaticStorageKey, StorageKey, dynamic,
// }; // TODO re-add
use crate::{
backend::BlockRef,
client::{OfflineClientT, OnlineClientT},
config::{Config, HashFor},
error::Error,
};
use derive_where::derive_where;
use std::{future::Future, marker::PhantomData};
/// Query the runtime storage.
#[derive_where(Clone; Client)]
pub struct StorageClient<T, Client> {
client: Client,
_marker: PhantomData<T>,
}
impl<T, Client> StorageClient<T, Client> {
/// Create a new [`StorageClient`]
pub fn new(client: Client) -> Self {
Self {
client,
_marker: PhantomData,
}
}
}
impl<T, Client> StorageClient<T, Client>
where
T: Config,
Client: OfflineClientT<T>,
{
/// Run the validation logic against some storage address you'd like to access. Returns `Ok(())`
/// if the address is valid (or if it's not possible to check since the address has no validation hash).
/// Return an error if the address was not valid or something went wrong trying to validate it (ie
/// the pallet or storage entry in question do not exist at all).
pub fn validate<Addr: Address>(&self, address: &Addr) -> Result<(), Error> {
subxt_core::storage::validate(address, &self.client.metadata()).map_err(Into::into)
}
/// Convert some storage address into the raw bytes that would be submitted to the node in order
/// to retrieve the entries at the root of the associated address.
pub fn address_root_bytes<Addr: Address>(&self, address: &Addr) -> Vec<u8> {
subxt_core::storage::get_address_root_bytes(address)
}
/// Convert some storage address into the raw bytes that would be submitted to the node in order
/// to retrieve an entry. This fails if [`Address::append_entry_bytes`] does; in the built-in
/// implementation this would be if the pallet and storage entry being asked for is not available on the
/// node you're communicating with, or if the metadata is missing some type information (which should not
/// happen).
pub fn address_bytes<Addr: Address>(&self, address: &Addr) -> Result<Vec<u8>, Error> {
subxt_core::storage::get_address_bytes(address, &self.client.metadata()).map_err(Into::into)
}
}
impl<T, Client> StorageClient<T, Client>
where
T: Config,
Client: OnlineClientT<T>,
{
/// Obtain storage at some block hash.
pub fn at(&self, block_ref: impl Into<BlockRef<HashFor<T>>>) -> Storage<T, Client> {
Storage::new(self.client.clone(), block_ref.into())
}
/// Obtain storage at the latest finalized block.
pub fn at_latest(
&self,
) -> impl Future<Output = Result<Storage<T, Client>, Error>> + Send + 'static {
// Clone and pass the client in like this so that we can explicitly
// return a Future that's Send + 'static, rather than tied to &self.
let client = self.client.clone();
async move {
// get the ref for the latest finalized block and use that.
let block_ref = client.backend().latest_finalized_block_ref().await?;
Ok(Storage::new(client, block_ref))
}
}
}