Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ The format is based on [Keep a Changelog].

[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/

## 0.13.0 (2025-11-14)

- Separate the iterating over entries from the core `frame-decode` `*Info` traits; One only needs to implement `*Info` traits to work with `frame-decode`; the other traits are convenience traits.
- Make `Entry` type generic so that it can potentially be used in more places, expose it, and expose concrete versions from each module.
- Expose Kusama RC and AH types (though keep these hidden until the types are more complete).
- Remove `helpers::list_storage_entries_any`: it was a bit of an anomaly to have this and not a version for any other thing. Better to keep this upstream for now.

## 0.12.1 (2025-11-12)

- Add `map_ids()` functions to `RuntimeApiInfo`, `StorageInfo` and `ViewFunctionInfo` to make translating the `TypeId` parameter simpler.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "frame-decode"
version = "0.12.1"
version = "0.13.0"
edition = "2024"
description = "Decode extrinsics and storage from Substrate based chains"
license = "Apache-2.0"
Expand Down
62 changes: 49 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ pub mod storage {
//! from modern or historic runtimes.
//! - See [`encode_storage_key_prefix`] to encode storage prefixes, and [`encode_storage_key`] to encode
//! storage keys.
//! - See [`StorageTypeInfo`] for the underlying trait which extracts the relevant information.
//! - See [`StorageTypeInfo`] for the underlying trait which provides storage entry information.
//! - See [`StorageEntryInfo`] for a underlying trait which provides information about the available
//! storage entries.

pub use crate::methods::Entry;
pub use crate::methods::storage_decoder::{
StorageKey, StorageKeyDecodeError, StorageKeyPart, StorageKeyPartValue,
StorageKeyValueDecodeError, StorageValueDecodeError,
Expand All @@ -68,7 +69,8 @@ pub mod storage {
encode_storage_key_with_info, encode_storage_key_with_info_to,
};
pub use crate::methods::storage_type_info::{
StorageHasher, StorageInfo, StorageInfoError, StorageKeyInfo, StorageTypeInfo,
StorageEntry, StorageEntryInfo, StorageHasher, StorageInfo, StorageInfoError,
StorageKeyInfo, StorageTypeInfo,
};
pub use crate::utils::{
DecodableValues, EncodableValues, IntoDecodableValues, IntoEncodableValues,
Expand All @@ -81,13 +83,14 @@ pub mod constants {
//! - See [`decode_constant`] and [`decode_constant_with_info`] to decode constants
//! - See [`ConstantTypeInfo`] for the underlying trait which extracts constant
//! information from metadata.
//! - See [`ConstantEntryInfo`] for a underlying trait which provides information about the available
//! constants.

pub use crate::methods::Entry;
pub use crate::methods::constant_decoder::{
ConstantDecodeError, decode_constant, decode_constant_with_info,
};
pub use crate::methods::constant_type_info::{
ConstantInfo, ConstantInfoError, ConstantTypeInfo,
ConstantEntry, ConstantEntryInfo, ConstantInfo, ConstantInfoError, ConstantTypeInfo,
};
}

Expand All @@ -98,8 +101,9 @@ pub mod runtime_apis {
//! the name and inputs to make a Runtime API call.
//! - See [`decode_runtime_api_response`] to decode Runtime API responses.
//! - See [`RuntimeApiTypeInfo`] for the underlying trait which extracts the relevant information.
//! - See [`RuntimeApiEntryInfo`] for a underlying trait which provides information about the available
//! Runtime APIs.

pub use crate::methods::Entry;
pub use crate::methods::runtime_api_decoder::{
RuntimeApiDecodeError, decode_runtime_api_response, decode_runtime_api_response_with_info,
};
Expand All @@ -108,7 +112,8 @@ pub mod runtime_apis {
encode_runtime_api_inputs_with_info_to, encode_runtime_api_name,
};
pub use crate::methods::runtime_api_type_info::{
RuntimeApiInfo, RuntimeApiInfoError, RuntimeApiInput, RuntimeApiTypeInfo,
RuntimeApiEntry, RuntimeApiEntryInfo, RuntimeApiInfo, RuntimeApiInfoError, RuntimeApiInput,
RuntimeApiTypeInfo,
};
pub use crate::utils::{EncodableValues, IntoEncodableValues};
}
Expand All @@ -120,8 +125,9 @@ pub mod view_functions {
//! and the encoded input data required to call a given View Function.
//! - See [`decode_view_function_response`] to decode View Function responses.
//! - See [`ViewFunctionTypeInfo`] for the underlying trait which extracts the relevant information.
//! - See [`ViewFunctionEntryInfo`] for a underlying trait which provides information about the available
//! View Functions.

pub use crate::methods::Entry;
pub use crate::methods::view_function_decoder::{
ViewFunctionDecodeError, decode_view_function_response,
decode_view_function_response_with_info,
Expand All @@ -131,7 +137,8 @@ pub mod view_functions {
encode_view_function_inputs_to, encode_view_function_inputs_with_info_to,
};
pub use crate::methods::view_function_type_info::{
ViewFunctionInfo, ViewFunctionInfoError, ViewFunctionInput, ViewFunctionTypeInfo,
ViewFunctionEntry, ViewFunctionEntryInfo, ViewFunctionInfo, ViewFunctionInfoError,
ViewFunctionInput, ViewFunctionTypeInfo,
};
pub use crate::utils::{EncodableValues, IntoEncodableValues};
}
Expand All @@ -142,12 +149,15 @@ pub mod custom_values {
//! - See [`decode_custom_value`] and [`decode_custom_value_with_info`] to decode custom values
//! - See [`CustomValueTypeInfo`] for the underlying trait which extracts custom value
//! information from metadata.
//! - See [`CustomValueEntryInfo`] for a underlying trait which provides information about the available
//! custom values.

pub use crate::methods::custom_value_decoder::{
CustomValueDecodeError, decode_custom_value, decode_custom_value_with_info,
};
pub use crate::methods::custom_value_type_info::{
CustomValue, CustomValueInfo, CustomValueInfoError, CustomValueTypeInfo,
CustomValue, CustomValueEntryInfo, CustomValueInfo, CustomValueInfoError,
CustomValueTypeInfo,
};
}

Expand All @@ -162,8 +172,30 @@ pub mod legacy_types {
pub fn relay_chain() -> scale_info_legacy::ChainTypeRegistry {
// This is a convenience function to load the Polkadot relay chain types.
// It is used in the examples in this crate.
let bytes = include_bytes!("../types/polkadot_types.yaml");
serde_yaml::from_slice(bytes).expect("Polkadot types are valid YAML")
let bytes = include_bytes!("../types/polkadot_relay_types.yaml");
serde_yaml::from_slice(bytes).expect("Polkadot RC types are valid YAML")
}
}

// Hidden until the types are ready.
#[doc(hidden)]
pub mod kusama {
//! Legacy types for Kusama chains.

/// Legacy types for the Kusama Relay Chain.
pub fn relay_chain() -> scale_info_legacy::ChainTypeRegistry {
// This is a convenience function to load the Polkadot relay chain types.
// It is used in the examples in this crate.
let bytes = include_bytes!("../types/kusama_relay_types.yaml");
serde_yaml::from_slice(bytes).expect("Kusama RC types are valid YAML")
}

/// Legacy types for the Kusama Asset Hub.
pub fn asset_hub() -> scale_info_legacy::ChainTypeRegistry {
// This is a convenience function to load the Polkadot relay chain types.
// It is used in the examples in this crate.
let bytes = include_bytes!("../types/kusama_assethub_types.yaml");
serde_yaml::from_slice(bytes).expect("Kusama AssetHub types are valid YAML")
}
}
}
Expand All @@ -177,9 +209,11 @@ pub mod helpers {
//! will use a tracing visitor (if the `error-tracing` feature is enabled) to provide more
//! information in the event that decoding fails.

pub use crate::methods::Entry;

pub use crate::utils::{
DecodableValues, DecodeErrorTrace, EncodableValues, IntoDecodableValues,
IntoEncodableValues, decode_with_error_tracing, list_storage_entries_any,
IntoEncodableValues, decode_with_error_tracing,
};
#[cfg(feature = "legacy")]
pub use crate::utils::{type_registry_from_metadata, type_registry_from_metadata_any};
Expand All @@ -205,6 +239,8 @@ mod test {
#[test]
fn test_deserializing_legacy_types() {
let _ = crate::legacy_types::polkadot::relay_chain();
let _ = crate::legacy_types::kusama::relay_chain();
let _ = crate::legacy_types::kusama::asset_hub();
}

macro_rules! impls_trait {
Expand Down
40 changes: 25 additions & 15 deletions src/methods/constant_type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,25 @@ pub trait ConstantTypeInfo {
pallet_name: &str,
constant_name: &str,
) -> Result<ConstantInfo<'_, Self::TypeId>, ConstantInfoError<'_>>;
/// Iterate over all of the available Constants.
fn constants(&self) -> impl Iterator<Item = Entry<'_>>;
}

/// This can be implemented for anything capable of providing information about the available Constants
pub trait ConstantEntryInfo {
/// Iterate over all of the available Constants, returning [`Entry`] as we go.
fn constant_entries(&self) -> impl Iterator<Item = ConstantEntry<'_>>;
/// Iterate over all of the available Constants, returning a pair of `(pallet_name, constant_name)` as we go.
fn constant_tuples(&self) -> impl Iterator<Item = (Cow<'_, str>, Cow<'_, str>)> {
Entry::tuples_of(self.constant_entries())
}
/// Iterate over all of the available constants in a given pallet.
fn constants_in_pallet(&self, pallet: &str) -> impl Iterator<Item = Cow<'_, str>> {
Entry::entries_in(self.constants(), pallet)
Entry::entries_in(self.constant_entries(), pallet)
}
}

/// An entry denoting a pallet or a constant name.
pub type ConstantEntry<'a> = Entry<Cow<'a, str>, Cow<'a, str>>;

/// An error returned trying to access Constant information.
#[non_exhaustive]
#[allow(missing_docs)]
Expand Down Expand Up @@ -82,6 +93,7 @@ impl<'info> ConstantInfoError<'info> {
}

/// Information about a Constant.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ConstantInfo<'info, TypeId: Clone> {
/// The bytes representing this constant.
///
Expand All @@ -98,7 +110,6 @@ macro_rules! impl_constant_type_info_for_v14_to_v16 {
use $path as path;
impl ConstantTypeInfo for path::$name {
type TypeId = u32;

fn constant_info(
&self,
pallet_name: &str,
Expand Down Expand Up @@ -128,17 +139,17 @@ macro_rules! impl_constant_type_info_for_v14_to_v16 {
type_id: constant.ty.id,
})
}

fn constants(&self) -> impl Iterator<Item = Entry<'_>> {
}
impl ConstantEntryInfo for path::$name {
fn constant_entries(&self) -> impl Iterator<Item = ConstantEntry<'_>> {
self.pallets.iter().flat_map(|p| {
core::iter::once(Entry::In(Cow::Borrowed(&p.name))).chain(
core::iter::once(Entry::In(Cow::Borrowed(&*p.name))).chain(
p.constants
.iter()
.map(|c| Entry::Name(Cow::Borrowed(&c.name))),
.map(|c| Entry::Name(Cow::Borrowed(&*c.name))),
)
})
}

fn constants_in_pallet(
&self,
pallet_name: &str,
Expand Down Expand Up @@ -175,7 +186,6 @@ mod legacy {
use $path as path;
impl ConstantTypeInfo for path::$name {
type TypeId = LookupName;

fn constant_info(
&self,
pallet_name: &str,
Expand Down Expand Up @@ -209,21 +219,21 @@ mod legacy {
type_id,
})
}

fn constants(&self) -> impl Iterator<Item = Entry<'_>> {
}
impl ConstantEntryInfo for path::$name {
fn constant_entries(&self) -> impl Iterator<Item = ConstantEntry<'_>> {
as_decoded(&self.modules).iter().flat_map(|module| {
let pallet_name = as_decoded(&module.name);
let constants = as_decoded(&module.constants);

core::iter::once(Entry::In(Cow::Borrowed(pallet_name))).chain(
core::iter::once(Entry::In(Cow::Borrowed(&**pallet_name))).chain(
constants.iter().map(|c| {
let constant_name = as_decoded(&c.name);
Entry::Name(Cow::Borrowed(constant_name))
Entry::Name(Cow::Borrowed(&**constant_name))
}),
)
})
}

fn constants_in_pallet(
&self,
pallet_name: &str,
Expand Down
13 changes: 9 additions & 4 deletions src/methods/custom_value_type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ pub trait CustomValueTypeInfo {
&self,
name: &str,
) -> Result<CustomValueInfo<'_, Self::TypeId>, CustomValueInfoError>;
/// Iterate over all of the available Custom Values.
}

/// This can be implemented for anything capable of providing information about the available Custom Values
pub trait CustomValueEntryInfo {
/// Iterate over all of the available Custom Values, returning [`CustomValue`] as we go.
fn custom_values(&self) -> impl Iterator<Item = CustomValue<'_>>;
}

Expand All @@ -39,6 +43,7 @@ pub struct CustomValueInfoError {
}

/// Information about a Custom Value.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CustomValueInfo<'info, TypeId: Clone> {
/// The bytes representing this custom value.
///
Expand All @@ -52,7 +57,7 @@ pub struct CustomValueInfo<'info, TypeId: Clone> {
}

/// The identifier for a single Custom Value.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CustomValue<'info> {
/// The name of this Custom Value.
pub name: Cow<'info, str>,
Expand All @@ -64,7 +69,6 @@ macro_rules! impl_custom_value_type_info_for_v15_to_v16 {
use $path as path;
impl CustomValueTypeInfo for path::$name {
type TypeId = u32;

fn custom_value_info(
&self,
name: &str,
Expand All @@ -82,7 +86,8 @@ macro_rules! impl_custom_value_type_info_for_v15_to_v16 {
type_id: custom_value.ty.id,
})
}

}
impl CustomValueEntryInfo for path::$name {
fn custom_values(&self) -> impl Iterator<Item = CustomValue<'_>> {
self.custom.map.iter().map(|(name, _)| CustomValue {
name: Cow::Borrowed(name),
Expand Down
8 changes: 4 additions & 4 deletions src/methods/extrinsic_type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ impl ExtrinsicInfoError<'_> {
}

/// An argument with a name and type ID.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExtrinsicInfoArg<'info, TypeId> {
/// Argument name.
pub name: Cow<'info, str>,
Expand All @@ -224,7 +224,7 @@ pub struct ExtrinsicInfoArg<'info, TypeId> {
}

/// Extrinsic call data information.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExtrinsicCallInfo<'info, TypeId> {
/// Name of the pallet.
pub pallet_name: Cow<'info, str>,
Expand All @@ -235,7 +235,7 @@ pub struct ExtrinsicCallInfo<'info, TypeId> {
}

/// Extrinsic signature information.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExtrinsicSignatureInfo<TypeId> {
/// Type ID of the address.
pub address_id: TypeId,
Expand All @@ -244,7 +244,7 @@ pub struct ExtrinsicSignatureInfo<TypeId> {
}

/// Extrinsic extension information.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExtrinsicExtensionInfo<'info, TypeId> {
/// Names and type IDs of the transaction extensions.
pub extension_ids: Vec<ExtrinsicInfoArg<'info, TypeId>>,
Expand Down
Loading
Loading