Add ability to iterate and visit event fields and storage values

This commit is contained in:
James Wilson
2025-12-15 16:37:17 +00:00
parent dfabd6609c
commit 4d47acd24b
3 changed files with 75 additions and 13 deletions
+57
View File
@@ -21,6 +21,7 @@ use crate::error::{
use crate::events::{self, DecodeAsEvent};
use frame_decode::extrinsics::Extrinsic as ExtrinsicInfo;
use scale_decode::{DecodeAsFields, DecodeAsType};
use scale_info::PortableRegistry;
use std::marker::PhantomData;
use std::sync::Arc;
use subxt_metadata::Metadata;
@@ -353,6 +354,19 @@ where
Ok(decoded)
}
/// Iterate over each of the fields in the call data.
pub fn iter_call_data_fields(
&self,
) -> impl Iterator<Item = ExtrinsicCallDataField<'atblock, '_>> {
let ext_bytes = self.bytes();
self.info.call_data().map(|field| ExtrinsicCallDataField {
bytes: &ext_bytes[field.range()],
name: field.name(),
type_id: *field.ty(),
metadata: self.metadata,
})
}
}
impl<'atblock, T, C> Extrinsic<'atblock, T, C>
@@ -366,6 +380,49 @@ where
}
}
/// A field in the extrinsic call data.
pub struct ExtrinsicCallDataField<'atblock, 'extrinsic> {
bytes: &'extrinsic [u8],
name: &'extrinsic str,
type_id: u32,
metadata: &'atblock Metadata,
}
impl<'atblock, 'extrinsic> ExtrinsicCallDataField<'atblock, 'extrinsic> {
/// The bytes for this field.
pub fn bytes(&self) -> &'extrinsic [u8] {
self.bytes
}
/// Name of this field.
pub fn name(&self) -> &'extrinsic str {
self.name
}
/// The type ID for this field.
pub fn type_id(&self) -> u32 {
self.type_id
}
/// Decode this field into the given type.
pub fn decode_as<E: DecodeAsType>(&self) -> Result<E, scale_decode::Error> {
E::decode_as_type(&mut &*self.bytes, self.type_id, self.metadata.types())
}
/// Visit this field with the provided visitor, returning the output from it.
pub fn visit<V, R>(&self, visitor: V) -> Result<V::Value<'extrinsic, 'atblock>, V::Error>
where
V: scale_decode::visitor::Visitor<TypeResolver = PortableRegistry>,
{
scale_decode::visitor::decode_with_visitor(
&mut &*self.bytes,
self.type_id,
self.metadata.types(),
visitor,
)
}
}
/// The events associated with a given extrinsic.
#[derive(Debug)]
pub struct ExtrinsicEvents<T: Config> {
-13
View File
@@ -250,19 +250,6 @@ where
.await
.map_err(StorageError::CannotIterateValues)?;
// .map(move |kv| {
// let kv = match kv {
// Ok(kv) => kv,
// Err(e) => return Err(StorageError::StreamFailure(e)),
// };
// Ok(StorageKeyValue::new(
// info.clone(),
// types,
// kv.key.into(),
// kv.value,
// ))
// });
Ok(StorageEntries {
info,
stream,
+18
View File
@@ -37,6 +37,11 @@ impl<'info, Value: DecodeAsType> StorageValue<'info, Value> {
&self.bytes
}
/// The type ID for this storage value.
pub fn type_id(&self) -> u32 {
self.info.value_id
}
/// Consume this storage value and return the raw bytes.
pub fn into_bytes(self) -> Vec<u8> {
self.bytes.to_vec()
@@ -67,4 +72,17 @@ impl<'info, Value: DecodeAsType> StorageValue<'info, Value> {
Ok(value)
}
/// Visit this storage value with the provided visitor, returning the output from it.
pub fn visit<V, R>(&self, visitor: V) -> Result<V::Value<'_, 'info>, V::Error>
where
V: scale_decode::visitor::Visitor<TypeResolver = PortableRegistry>,
{
scale_decode::visitor::decode_with_visitor(
&mut &*self.bytes,
self.type_id(),
self.types,
visitor,
)
}
}