subxt-historic: add support for returning the default values of storage entries (#2072)

This commit is contained in:
James Wilson
2025-09-02 11:32:09 +01:00
committed by GitHub
parent 2a498d4dda
commit abcda67fc0
8 changed files with 73 additions and 15 deletions
+51 -4
View File
@@ -7,6 +7,7 @@ use crate::client::{OfflineClientAtBlockT, OnlineClientAtBlockT};
use crate::config::Config;
use crate::error::{StorageEntryIsNotAMap, StorageEntryIsNotAPlainValue, StorageError};
use crate::storage::storage_info::with_info;
use std::borrow::Cow;
use storage_info::AnyStorageInfo;
pub use storage_entry::StorageEntry;
@@ -208,6 +209,16 @@ where
pub fn storage_name(&self) -> &str {
&self.storage_name
}
/// Return the default value for this storage entry, if there is one. Returns `None` if there
/// is no default value.
pub fn default(&self) -> Option<StorageValue<'_, 'atblock>> {
with_info!(info = &self.info => {
info.info.default_value.as_ref().map(|default_value| {
StorageValue::new(&self.info, default_value.clone())
})
})
}
}
impl<'atblock, Client, T> StorageEntryPlainClient<'atblock, Client, T>
@@ -220,7 +231,17 @@ where
let key_bytes = self.key();
fetch(self.client, &key_bytes)
.await
.map(|v| v.map(|bytes| StorageValue::new(&self.info, bytes)))
.map(|v| v.map(|bytes| StorageValue::new(&self.info, Cow::Owned(bytes))))
}
/// Fetch the value for this storage entry as per [`StorageEntryPlainClient::fetch`], but return the default
/// value for the storage entry if one exists and the entry does not exist.
pub async fn fetch_or_default(
&self,
) -> Result<Option<StorageValue<'_, 'atblock>>, StorageError> {
self.fetch()
.await
.map(|option_val| option_val.or_else(|| self.default()))
}
/// The key for this storage entry.
@@ -255,6 +276,16 @@ where
pub fn storage_name(&self) -> &str {
&self.storage_name
}
/// Return the default value for this storage entry, if there is one. Returns `None` if there
/// is no default value.
pub fn default(&self) -> Option<StorageValue<'_, 'atblock>> {
with_info!(info = &self.info => {
info.info.default_value.as_ref().map(|default_value| {
StorageValue::new(&self.info, default_value.clone())
})
})
}
}
impl<'atblock, Client, T> StorageEntryMapClient<'atblock, Client, T>
@@ -283,7 +314,18 @@ where
let key_bytes = self.key(keys)?;
fetch(self.client, &key_bytes)
.await
.map(|v| v.map(|bytes| StorageValue::new(&self.info, bytes)))
.map(|v| v.map(|bytes| StorageValue::new(&self.info, Cow::Owned(bytes))))
}
/// Fetch a specific key in this map as per [`StorageEntryMapClient::fetch`], but return the default
/// value for the storage entry if one exists and the entry was not found.
pub async fn fetch_or_default<Keys: IntoStorageKeys>(
&self,
keys: Keys,
) -> Result<Option<StorageValue<'_, 'atblock>>, StorageError> {
self.fetch(keys)
.await
.map(|option_val| option_val.or_else(|| self.default()))
}
/// Iterate over the values underneath the provided keys.
@@ -324,8 +366,13 @@ where
Err(e) => return Some(Err(StorageError::RpcError { reason: e })),
};
item.value
.map(|value| Ok(StorageEntry::new(&self.info, item.key.0, value.0)))
item.value.map(|value| {
Ok(StorageEntry::new(
&self.info,
item.key.0,
Cow::Owned(value.0),
))
})
});
Ok(Box::pin(sub))
+6 -1
View File
@@ -3,6 +3,7 @@ use super::storage_key::StorageKey;
use super::storage_value::StorageValue;
use crate::error::{StorageKeyError, StorageValueError};
use scale_decode::DecodeAsType;
use std::borrow::Cow;
/// This represents a storage entry, which is a key-value pair in the storage.
pub struct StorageEntry<'entry, 'atblock> {
@@ -13,7 +14,11 @@ pub struct StorageEntry<'entry, 'atblock> {
impl<'entry, 'atblock> StorageEntry<'entry, 'atblock> {
/// Create a new storage entry.
pub fn new(info: &'entry AnyStorageInfo<'atblock>, key: Vec<u8>, value: Vec<u8>) -> Self {
pub fn new(
info: &'entry AnyStorageInfo<'atblock>,
key: Vec<u8>,
value: Cow<'atblock, [u8]>,
) -> Self {
Self {
key,
value: StorageValue::new(info, value),
+1 -1
View File
@@ -85,7 +85,7 @@ impl<'atblock> From<StorageInfo<'atblock, u32, scale_info::PortableRegistry>>
}
pub struct StorageInfo<'atblock, TypeId, Resolver> {
pub info: frame_decode::storage::StorageInfo<TypeId>,
pub info: frame_decode::storage::StorageInfo<'atblock, TypeId>,
pub resolver: &'atblock Resolver,
}
+4 -3
View File
@@ -2,16 +2,17 @@ use super::storage_info::AnyStorageInfo;
use super::storage_info::with_info;
use crate::error::StorageValueError;
use scale_decode::DecodeAsType;
use std::borrow::Cow;
/// This represents a storage value.
pub struct StorageValue<'entry, 'atblock> {
pub(crate) info: &'entry AnyStorageInfo<'atblock>,
bytes: Vec<u8>,
bytes: Cow<'atblock, [u8]>,
}
impl<'entry, 'atblock> StorageValue<'entry, 'atblock> {
/// Create a new storage value.
pub fn new(info: &'entry AnyStorageInfo<'atblock>, bytes: Vec<u8>) -> Self {
pub fn new(info: &'entry AnyStorageInfo<'atblock>, bytes: Cow<'atblock, [u8]>) -> Self {
Self { info, bytes }
}
@@ -22,7 +23,7 @@ impl<'entry, 'atblock> StorageValue<'entry, 'atblock> {
/// Consume this storage value and return the raw bytes.
pub fn into_bytes(self) -> Vec<u8> {
self.bytes
self.bytes.to_vec()
}
/// Decode this storage value.