[v0.50.0] Allow visiting extrinsic fields in subxt_historic (#2124)

* Allow visiting extrinsic fields

* fmt

* Don't use local scale-decode dep

* Clippy and tidy

* Extend 'subxt codegen' CLI to work with legacy metadatas

* Simplify historic extrinsics example now that AccountId32s have paths/names

* clippy

* clippy

* clippy..

* Allow visiting storage values, too, and clean up extrinsic visiting a little by narrowing lifetime

* Try to fix flaky test

* Add custom value decode to extrinsics example

* Remove useless else branch ra thought I needed

* Simplify examples
This commit is contained in:
James Wilson
2025-11-21 15:32:32 +00:00
committed by GitHub
parent 1a0e218d32
commit 3bbba1b005
16 changed files with 871 additions and 37 deletions
+57 -2
View File
@@ -374,6 +374,27 @@ impl Metadata {
<Self as codec::Decode>::decode(&mut bytes)
}
/// Convert V16 metadata into [`Metadata`].
pub fn from_v16(
metadata: frame_metadata::v16::RuntimeMetadataV16,
) -> Result<Self, TryFromError> {
metadata.try_into()
}
/// Convert V15 metadata into [`Metadata`].
pub fn from_v15(
metadata: frame_metadata::v15::RuntimeMetadataV15,
) -> Result<Self, TryFromError> {
metadata.try_into()
}
/// Convert V14 metadata into [`Metadata`].
pub fn from_v14(
metadata: frame_metadata::v14::RuntimeMetadataV14,
) -> Result<Self, TryFromError> {
metadata.try_into()
}
/// Convert V13 metadata into [`Metadata`], given the necessary extra type information.
#[cfg(feature = "legacy")]
pub fn from_v13(
@@ -1222,6 +1243,38 @@ impl<'a> CustomValueMetadata<'a> {
}
}
/// Decode SCALE encoded metadata.
///
/// - The default assumption is that metadata is encoded as [`frame_metadata::RuntimeMetadataPrefixed`]. This is the
/// expected format that metadata is encoded into.
/// - if this fails, we also try to decode as [`frame_metadata::RuntimeMetadata`].
/// - If this all fails, we also try to decode as [`frame_metadata::OpaqueMetadata`].
pub fn decode_runtime_metadata(
input: &[u8],
) -> Result<frame_metadata::RuntimeMetadata, codec::Error> {
use codec::Decode;
let err = match frame_metadata::RuntimeMetadataPrefixed::decode(&mut &*input) {
Ok(md) => return Ok(md.1),
Err(e) => e,
};
if let Ok(md) = frame_metadata::RuntimeMetadata::decode(&mut &*input) {
return Ok(md);
}
// frame_metadata::OpaqueMetadata is a vec of bytes. If we can decode the length, AND
// the length definitely corresponds to the number of remaining bytes, then we try to
// decode the inner bytes.
if let Ok(len) = codec::Compact::<u64>::decode(&mut &*input) {
if input.len() == len.0 as usize {
return decode_runtime_metadata(input);
}
}
Err(err)
}
// Support decoding metadata from the "wire" format directly into this.
// Errors may be lost in the case that the metadata content is somehow invalid.
impl codec::Decode for Metadata {
@@ -1231,9 +1284,11 @@ impl codec::Decode for Metadata {
frame_metadata::RuntimeMetadata::V14(md) => md.try_into(),
frame_metadata::RuntimeMetadata::V15(md) => md.try_into(),
frame_metadata::RuntimeMetadata::V16(md) => md.try_into(),
_ => return Err("Cannot try_into() to Metadata: unsupported metadata version".into()),
_ => {
return Err("Metadata::decode failed: Cannot try_into() to Metadata: unsupported metadata version".into())
},
};
metadata.map_err(|_e| "Cannot try_into() to Metadata.".into())
metadata.map_err(|_| "Metadata::decode failed: Cannot try_into() to Metadata".into())
}
}