subxt_metadata/
lib.rs

1// Copyright 2019-2025 Parity Technologies (UK) Ltd.
2// This file is dual-licensed as Apache-2.0 or GPL-3.0.
3// see LICENSE for license details.
4
5//! A representation of the metadata provided by a substrate based node.
6//! This representation is optimized to be used by Subxt and related crates,
7//! and is independent of the different versions of metadata that can be
8//! provided from a node.
9//!
10//! Typically, this will be constructed by either:
11//!
12//! 1. Calling `Metadata::decode()` given some metadata bytes obtained
13//!    from a node (this uses [`codec::Decode`]).
14//! 2. Obtaining [`frame_metadata::RuntimeMetadataPrefixed`], and then
15//!    using `.try_into()` to convert it into [`Metadata`].
16
17#![cfg_attr(not(feature = "std"), no_std)]
18#![deny(missing_docs)]
19
20extern crate alloc;
21
22mod from;
23mod utils;
24
25use alloc::borrow::Cow;
26use alloc::collections::BTreeMap;
27use alloc::string::String;
28use alloc::sync::Arc;
29use alloc::vec::Vec;
30use frame_decode::extrinsics::{
31    ExtrinsicCallInfo, ExtrinsicExtensionInfo, ExtrinsicInfoArg, ExtrinsicInfoError,
32    ExtrinsicSignatureInfo,
33};
34use hashbrown::HashMap;
35use scale_info::{PortableRegistry, Variant, form::PortableForm};
36use utils::{
37    ordered_map::OrderedMap,
38    validation::{HASH_LEN, get_custom_value_hash},
39    variant_index::VariantIndex,
40};
41
42type ArcStr = Arc<str>;
43
44pub use from::SUPPORTED_METADATA_VERSIONS;
45pub use from::TryFromError;
46pub use utils::validation::MetadataHasher;
47
48type CustomMetadataInner = frame_metadata::v15::CustomMetadata<PortableForm>;
49
50/// Node metadata. This can be constructed by providing some compatible [`frame_metadata`]
51/// which is then decoded into this. We aim to preserve all of the existing information in
52/// the incoming metadata while optimizing the format a little for Subxt's use cases.
53#[derive(Debug, Clone)]
54pub struct Metadata {
55    /// Type registry containing all types used in the metadata.
56    types: PortableRegistry,
57    /// Metadata of all the pallets.
58    pallets: OrderedMap<ArcStr, PalletMetadataInner>,
59    /// Find the location in the pallet Vec by pallet index.
60    pallets_by_index: HashMap<u8, usize>,
61    /// Metadata of the extrinsic.
62    extrinsic: ExtrinsicMetadata,
63    /// The types of the outer enums.
64    outer_enums: OuterEnumsMetadata,
65    /// The type Id of the `DispatchError` type, which Subxt makes use of.
66    dispatch_error_ty: Option<u32>,
67    /// Details about each of the runtime API traits.
68    apis: OrderedMap<ArcStr, RuntimeApiMetadataInner>,
69    /// Allows users to add custom types to the metadata. A map that associates a string key to a `CustomValueMetadata`.
70    custom: CustomMetadataInner,
71}
72
73// Since we've abstracted away from frame-metadatas, we impl this on our custom Metadata
74// so that it can be used by `frame-decode` to obtain the relevant extrinsic info.
75impl frame_decode::extrinsics::ExtrinsicTypeInfo for Metadata {
76    type TypeId = u32;
77
78    fn get_call_info(
79        &self,
80        pallet_index: u8,
81        call_index: u8,
82    ) -> Result<ExtrinsicCallInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
83        let pallet = self.pallet_by_index(pallet_index).ok_or({
84            ExtrinsicInfoError::PalletNotFound {
85                index: pallet_index,
86            }
87        })?;
88
89        let call = pallet.call_variant_by_index(call_index).ok_or_else(|| {
90            ExtrinsicInfoError::CallNotFound {
91                index: call_index,
92                pallet_index,
93                pallet_name: Cow::Borrowed(pallet.name()),
94            }
95        })?;
96
97        Ok(ExtrinsicCallInfo {
98            pallet_name: Cow::Borrowed(pallet.name()),
99            call_name: Cow::Borrowed(&call.name),
100            args: call
101                .fields
102                .iter()
103                .map(|f| ExtrinsicInfoArg {
104                    name: Cow::Borrowed(f.name.as_deref().unwrap_or("")),
105                    id: f.ty.id,
106                })
107                .collect(),
108        })
109    }
110
111    fn get_signature_info(
112        &self,
113    ) -> Result<ExtrinsicSignatureInfo<Self::TypeId>, ExtrinsicInfoError<'_>> {
114        Ok(ExtrinsicSignatureInfo {
115            address_id: self.extrinsic().address_ty,
116            signature_id: self.extrinsic().signature_ty,
117        })
118    }
119
120    fn get_extension_info(
121        &self,
122        extension_version: Option<u8>,
123    ) -> Result<ExtrinsicExtensionInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
124        let extension_version = extension_version.unwrap_or_else(|| {
125            // We have some transaction, probably a V4 one with no extension version,
126            // but our metadata may support multiple versions. Use the metadata to decide
127            // what version to assume we'll decode it as.
128            self.extrinsic()
129                .transaction_extension_version_to_use_for_decoding()
130        });
131
132        let extension_ids = self
133            .extrinsic()
134            .transaction_extensions_by_version(extension_version)
135            .ok_or(ExtrinsicInfoError::ExtrinsicExtensionVersionNotFound { extension_version })?
136            .map(|f| ExtrinsicInfoArg {
137                name: Cow::Borrowed(f.identifier()),
138                id: f.extra_ty(),
139            })
140            .collect();
141
142        Ok(ExtrinsicExtensionInfo { extension_ids })
143    }
144}
145
146impl Metadata {
147    /// Access the underlying type registry.
148    pub fn types(&self) -> &PortableRegistry {
149        &self.types
150    }
151
152    /// Mutable access to the underlying type registry.
153    pub fn types_mut(&mut self) -> &mut PortableRegistry {
154        &mut self.types
155    }
156
157    /// The type ID of the `DispatchError` type, if it exists.
158    pub fn dispatch_error_ty(&self) -> Option<u32> {
159        self.dispatch_error_ty
160    }
161
162    /// Return details about the extrinsic format.
163    pub fn extrinsic(&self) -> &ExtrinsicMetadata {
164        &self.extrinsic
165    }
166
167    /// Return details about the outer enums.
168    pub fn outer_enums(&self) -> OuterEnumsMetadata {
169        self.outer_enums
170    }
171
172    /// An iterator over all of the available pallets.
173    pub fn pallets(&self) -> impl ExactSizeIterator<Item = PalletMetadata<'_>> {
174        self.pallets.values().iter().map(|inner| PalletMetadata {
175            inner,
176            types: self.types(),
177        })
178    }
179
180    /// Access a pallet given its encoded variant index.
181    pub fn pallet_by_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
182        let inner = self
183            .pallets_by_index
184            .get(&variant_index)
185            .and_then(|i| self.pallets.get_by_index(*i))?;
186
187        Some(PalletMetadata {
188            inner,
189            types: self.types(),
190        })
191    }
192
193    /// Access a pallet given its name.
194    pub fn pallet_by_name(&self, pallet_name: &str) -> Option<PalletMetadata<'_>> {
195        let inner = self.pallets.get_by_key(pallet_name)?;
196
197        Some(PalletMetadata {
198            inner,
199            types: self.types(),
200        })
201    }
202
203    /// An iterator over all of the runtime APIs.
204    pub fn runtime_api_traits(&self) -> impl ExactSizeIterator<Item = RuntimeApiMetadata<'_>> {
205        self.apis.values().iter().map(|inner| RuntimeApiMetadata {
206            inner,
207            types: self.types(),
208        })
209    }
210
211    /// Access a runtime API trait given its name.
212    pub fn runtime_api_trait_by_name(&'_ self, name: &str) -> Option<RuntimeApiMetadata<'_>> {
213        let inner = self.apis.get_by_key(name)?;
214        Some(RuntimeApiMetadata {
215            inner,
216            types: self.types(),
217        })
218    }
219
220    /// Access a view function given its query ID, if any.
221    pub fn view_function_by_query_id(
222        &'_ self,
223        query_id: &[u8; 32],
224    ) -> Option<ViewFunctionMetadata<'_>> {
225        // Dev note: currently, we only have pallet view functions, and here
226        // we just do a naive thing of iterating over the pallets to find the one
227        // we're looking for. Eventually we should construct a separate map of view
228        // functions for easy querying here.
229        self.pallets()
230            .flat_map(|p| p.view_functions())
231            .find(|vf| vf.query_id() == query_id)
232    }
233
234    /// Returns custom user defined types
235    pub fn custom(&self) -> CustomMetadata<'_> {
236        CustomMetadata {
237            types: self.types(),
238            inner: &self.custom,
239        }
240    }
241
242    /// Obtain a unique hash representing this metadata or specific parts of it.
243    pub fn hasher(&self) -> MetadataHasher {
244        MetadataHasher::new(self)
245    }
246
247    /// Get type hash for a type in the registry
248    pub fn type_hash(&self, id: u32) -> Option<[u8; HASH_LEN]> {
249        self.types.resolve(id)?;
250        Some(crate::utils::validation::get_type_hash(&self.types, id))
251    }
252}
253
254/// Metadata for a specific pallet.
255#[derive(Debug, Clone, Copy)]
256pub struct PalletMetadata<'a> {
257    inner: &'a PalletMetadataInner,
258    types: &'a PortableRegistry,
259}
260
261impl<'a> PalletMetadata<'a> {
262    /// The pallet name.
263    pub fn name(&self) -> &'a str {
264        &self.inner.name
265    }
266
267    /// The pallet index.
268    pub fn index(&self) -> u8 {
269        self.inner.index
270    }
271
272    /// The pallet docs.
273    pub fn docs(&self) -> &'a [String] {
274        &self.inner.docs
275    }
276
277    /// Type ID for the pallet's Call type, if it exists.
278    pub fn call_ty_id(&self) -> Option<u32> {
279        self.inner.call_ty
280    }
281
282    /// Type ID for the pallet's Event type, if it exists.
283    pub fn event_ty_id(&self) -> Option<u32> {
284        self.inner.event_ty
285    }
286
287    /// Type ID for the pallet's Error type, if it exists.
288    pub fn error_ty_id(&self) -> Option<u32> {
289        self.inner.error_ty
290    }
291
292    /// Return metadata about the pallet's storage entries.
293    pub fn storage(&self) -> Option<&'a StorageMetadata> {
294        self.inner.storage.as_ref()
295    }
296
297    /// Return all of the event variants, if an event type exists.
298    pub fn event_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
299        VariantIndex::get(self.inner.event_ty, self.types)
300    }
301
302    /// Return an event variant given it's encoded variant index.
303    pub fn event_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
304        self.inner.event_variant_index.lookup_by_index(
305            variant_index,
306            self.inner.event_ty,
307            self.types,
308        )
309    }
310
311    /// Does this pallet have any view functions?
312    pub fn has_view_functions(&self) -> bool {
313        !self.inner.view_functions.is_empty()
314    }
315
316    /// Return an iterator over the View Functions in this pallet, if any.
317    pub fn view_functions(
318        &self,
319    ) -> impl ExactSizeIterator<Item = ViewFunctionMetadata<'a>> + use<'a> {
320        self.inner
321            .view_functions
322            .values()
323            .iter()
324            .map(|vf: &'a _| ViewFunctionMetadata {
325                inner: vf,
326                types: self.types,
327            })
328    }
329
330    /// Return the view function with a given name, if any
331    pub fn view_function_by_name(&self, name: &str) -> Option<ViewFunctionMetadata<'a>> {
332        self.inner
333            .view_functions
334            .get_by_key(name)
335            .map(|vf: &'a _| ViewFunctionMetadata {
336                inner: vf,
337                types: self.types,
338            })
339    }
340
341    /// Iterate (in no particular order) over the associated type names and type IDs for this pallet.
342    pub fn associated_types(&self) -> impl ExactSizeIterator<Item = (&'a str, u32)> + use<'a> {
343        self.inner
344            .associated_types
345            .iter()
346            .map(|(name, ty)| (&**name, *ty))
347    }
348
349    /// Fetch an associated type ID given the associated type name.
350    pub fn associated_type_id(&self, name: &str) -> Option<u32> {
351        self.inner.associated_types.get(name).copied()
352    }
353
354    /// Return all of the call variants, if a call type exists.
355    pub fn call_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
356        VariantIndex::get(self.inner.call_ty, self.types)
357    }
358
359    /// Return a call variant given it's encoded variant index.
360    pub fn call_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
361        self.inner
362            .call_variant_index
363            .lookup_by_index(variant_index, self.inner.call_ty, self.types)
364    }
365
366    /// Return a call variant given it's name.
367    pub fn call_variant_by_name(&self, call_name: &str) -> Option<&'a Variant<PortableForm>> {
368        self.inner
369            .call_variant_index
370            .lookup_by_name(call_name, self.inner.call_ty, self.types)
371    }
372
373    /// Return all of the error variants, if an error type exists.
374    pub fn error_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
375        VariantIndex::get(self.inner.error_ty, self.types)
376    }
377
378    /// Return an error variant given it's encoded variant index.
379    pub fn error_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
380        self.inner.error_variant_index.lookup_by_index(
381            variant_index,
382            self.inner.error_ty,
383            self.types,
384        )
385    }
386
387    /// Return constant details given the constant name.
388    pub fn constant_by_name(&self, name: &str) -> Option<&'a ConstantMetadata> {
389        self.inner.constants.get_by_key(name)
390    }
391
392    /// An iterator over the constants in this pallet.
393    pub fn constants(&self) -> impl ExactSizeIterator<Item = &'a ConstantMetadata> + use<'a> {
394        self.inner.constants.values().iter()
395    }
396
397    /// Return a hash for the storage entry, or None if it was not found.
398    pub fn storage_hash(&self, entry_name: &str) -> Option<[u8; HASH_LEN]> {
399        crate::utils::validation::get_storage_hash(self, entry_name)
400    }
401
402    /// Return a hash for the constant, or None if it was not found.
403    pub fn constant_hash(&self, constant_name: &str) -> Option<[u8; HASH_LEN]> {
404        crate::utils::validation::get_constant_hash(self, constant_name)
405    }
406
407    /// Return a hash for the call, or None if it was not found.
408    pub fn call_hash(&self, call_name: &str) -> Option<[u8; HASH_LEN]> {
409        crate::utils::validation::get_call_hash(self, call_name)
410    }
411
412    /// Return a hash for the entire pallet.
413    pub fn hash(&self) -> [u8; HASH_LEN] {
414        crate::utils::validation::get_pallet_hash(*self)
415    }
416}
417
418#[derive(Debug, Clone)]
419struct PalletMetadataInner {
420    /// Pallet name.
421    name: ArcStr,
422    /// Pallet index.
423    index: u8,
424    /// Pallet storage metadata.
425    storage: Option<StorageMetadata>,
426    /// Type ID for the pallet Call enum.
427    call_ty: Option<u32>,
428    /// Call variants by name/u8.
429    call_variant_index: VariantIndex,
430    /// Type ID for the pallet Event enum.
431    event_ty: Option<u32>,
432    /// Event variants by name/u8.
433    event_variant_index: VariantIndex,
434    /// Type ID for the pallet Error enum.
435    error_ty: Option<u32>,
436    /// Error variants by name/u8.
437    error_variant_index: VariantIndex,
438    /// Map from constant name to constant details.
439    constants: OrderedMap<ArcStr, ConstantMetadata>,
440    /// Details about each of the pallet view functions.
441    view_functions: OrderedMap<ArcStr, ViewFunctionMetadataInner>,
442    /// Mapping from associated type to type ID describing its shape.
443    associated_types: BTreeMap<String, u32>,
444    /// Pallet documentation.
445    docs: Vec<String>,
446}
447
448/// Metadata for the storage entries in a pallet.
449#[derive(Debug, Clone)]
450pub struct StorageMetadata {
451    /// The common prefix used by all storage entries.
452    prefix: String,
453    /// Map from storage entry name to details.
454    entries: OrderedMap<ArcStr, StorageEntryMetadata>,
455}
456
457impl StorageMetadata {
458    /// The common prefix used by all storage entries.
459    pub fn prefix(&self) -> &str {
460        &self.prefix
461    }
462
463    /// An iterator over the storage entries.
464    pub fn entries(&self) -> &[StorageEntryMetadata] {
465        self.entries.values()
466    }
467
468    /// Return a specific storage entry given its name.
469    pub fn entry_by_name(&self, name: &str) -> Option<&StorageEntryMetadata> {
470        self.entries.get_by_key(name)
471    }
472}
473
474/// Metadata for a single storage entry.
475#[derive(Debug, Clone)]
476pub struct StorageEntryMetadata {
477    /// Variable name of the storage entry.
478    name: ArcStr,
479    /// An `Option` modifier of that storage entry.
480    modifier: StorageEntryModifier,
481    /// Type of the value stored in the entry.
482    entry_type: StorageEntryType,
483    /// Default value (SCALE encoded).
484    default: Vec<u8>,
485    /// Storage entry documentation.
486    docs: Vec<String>,
487}
488
489impl StorageEntryMetadata {
490    /// Name of this entry.
491    pub fn name(&self) -> &str {
492        &self.name
493    }
494    /// Is the entry value optional or does it have a default value.
495    pub fn modifier(&self) -> StorageEntryModifier {
496        self.modifier
497    }
498    /// Type of the storage entry.
499    pub fn entry_type(&self) -> &StorageEntryType {
500        &self.entry_type
501    }
502    /// The SCALE encoded default value for this entry.
503    pub fn default_bytes(&self) -> &[u8] {
504        &self.default
505    }
506    /// Storage entry documentation.
507    pub fn docs(&self) -> &[String] {
508        &self.docs
509    }
510}
511
512/// The type of a storage entry.
513#[derive(Debug, Clone)]
514pub enum StorageEntryType {
515    /// Plain storage entry (just the value).
516    Plain(u32),
517    /// A storage map.
518    Map {
519        /// One or more hashers, should be one hasher per key element.
520        hashers: Vec<StorageHasher>,
521        /// The type of the key, can be a tuple with elements for each of the hashers.
522        key_ty: u32,
523        /// The type of the value.
524        value_ty: u32,
525    },
526}
527
528impl StorageEntryType {
529    /// The type of the value.
530    pub fn value_ty(&self) -> u32 {
531        match self {
532            StorageEntryType::Map { value_ty, .. } | StorageEntryType::Plain(value_ty) => *value_ty,
533        }
534    }
535
536    /// The type of the key, can be a tuple with elements for each of the hashers. None for a Plain storage entry.
537    pub fn key_ty(&self) -> Option<u32> {
538        match self {
539            StorageEntryType::Map { key_ty, .. } => Some(*key_ty),
540            StorageEntryType::Plain(_) => None,
541        }
542    }
543}
544
545/// Hasher used by storage maps.
546#[derive(Debug, Clone, Copy)]
547pub enum StorageHasher {
548    /// 128-bit Blake2 hash.
549    Blake2_128,
550    /// 256-bit Blake2 hash.
551    Blake2_256,
552    /// Multiple 128-bit Blake2 hashes concatenated.
553    Blake2_128Concat,
554    /// 128-bit XX hash.
555    Twox128,
556    /// 256-bit XX hash.
557    Twox256,
558    /// Multiple 64-bit XX hashes concatenated.
559    Twox64Concat,
560    /// Identity hashing (no hashing).
561    Identity,
562}
563
564impl StorageHasher {
565    /// The hash produced by a [`StorageHasher`] can have these two components, in order:
566    ///
567    /// 1. A fixed size hash. (not present for [`StorageHasher::Identity`]).
568    /// 2. The SCALE encoded key that was used as an input to the hasher (only present for
569    ///    [`StorageHasher::Twox64Concat`], [`StorageHasher::Blake2_128Concat`] or [`StorageHasher::Identity`]).
570    ///
571    /// This function returns the number of bytes used to represent the first of these.
572    pub fn len_excluding_key(&self) -> usize {
573        match self {
574            StorageHasher::Blake2_128Concat => 16,
575            StorageHasher::Twox64Concat => 8,
576            StorageHasher::Blake2_128 => 16,
577            StorageHasher::Blake2_256 => 32,
578            StorageHasher::Twox128 => 16,
579            StorageHasher::Twox256 => 32,
580            StorageHasher::Identity => 0,
581        }
582    }
583
584    /// Returns true if the key used to produce the hash is appended to the hash itself.
585    pub fn ends_with_key(&self) -> bool {
586        matches!(
587            self,
588            StorageHasher::Blake2_128Concat | StorageHasher::Twox64Concat | StorageHasher::Identity
589        )
590    }
591}
592
593/// Is the storage entry optional, or does it have a default value.
594#[derive(Debug, Clone, Copy, Eq, PartialEq)]
595pub enum StorageEntryModifier {
596    /// The storage entry returns an `Option<T>`, with `None` if the key is not present.
597    Optional,
598    /// The storage entry returns `T::Default` if the key is not present.
599    Default,
600}
601
602/// Metadata for a single constant.
603#[derive(Debug, Clone)]
604pub struct ConstantMetadata {
605    /// Name of the pallet constant.
606    name: ArcStr,
607    /// Type of the pallet constant.
608    ty: u32,
609    /// Value stored in the constant (SCALE encoded).
610    value: Vec<u8>,
611    /// Constant documentation.
612    docs: Vec<String>,
613}
614
615impl ConstantMetadata {
616    /// Name of the pallet constant.
617    pub fn name(&self) -> &str {
618        &self.name
619    }
620    /// Type of the pallet constant.
621    pub fn ty(&self) -> u32 {
622        self.ty
623    }
624    /// Value stored in the constant (SCALE encoded).
625    pub fn value(&self) -> &[u8] {
626        &self.value
627    }
628    /// Constant documentation.
629    pub fn docs(&self) -> &[String] {
630        &self.docs
631    }
632}
633
634/// Metadata for the extrinsic type.
635#[derive(Debug, Clone)]
636pub struct ExtrinsicMetadata {
637    /// The type of the address that signs the extrinsic.
638    /// Used to help decode tx signatures.
639    address_ty: u32,
640    /// The type of the extrinsic's signature.
641    /// Used to help decode tx signatures.
642    signature_ty: u32,
643    /// Which extrinsic versions are supported by this chain.
644    supported_versions: Vec<u8>,
645    /// The signed extensions in the order they appear in the extrinsic.
646    transaction_extensions: Vec<TransactionExtensionMetadataInner>,
647    /// Different versions of transaction extensions can exist. Each version
648    /// is a u8 which corresponds to the indexes of the transaction extensions
649    /// seen in the above Vec, in order, that exist at that version.
650    transaction_extensions_by_version: BTreeMap<u8, Vec<u32>>,
651}
652
653impl ExtrinsicMetadata {
654    /// Which extrinsic versions are supported.
655    pub fn supported_versions(&self) -> &[u8] {
656        &self.supported_versions
657    }
658
659    /// The extra/additional information associated with the extrinsic.
660    pub fn transaction_extensions_by_version(
661        &self,
662        version: u8,
663    ) -> Option<impl Iterator<Item = TransactionExtensionMetadata<'_>>> {
664        let extension_indexes = self.transaction_extensions_by_version.get(&version)?;
665        let iter = extension_indexes.iter().map(|index| {
666            let tx_metadata = self
667                .transaction_extensions
668                .get(*index as usize)
669                .expect("transaction extension should exist if index is in transaction_extensions_by_version");
670
671            TransactionExtensionMetadata {
672                identifier: &tx_metadata.identifier,
673                extra_ty: tx_metadata.extra_ty,
674                additional_ty: tx_metadata.additional_ty,
675            }
676        });
677
678        Some(iter)
679    }
680
681    /// When constructing a v5 extrinsic, use this transaction extensions version.
682    pub fn transaction_extension_version_to_use_for_encoding(&self) -> u8 {
683        *self
684            .transaction_extensions_by_version
685            .keys()
686            .max()
687            .expect("At least one version of transaction extensions is expected")
688    }
689
690    /// An iterator of the transaction extensions to use when encoding a transaction. Basically equivalent to
691    /// `self.transaction_extensions_by_version(self.transaction_extension_version_to_use_for_encoding()).unwrap()`
692    pub fn transaction_extensions_to_use_for_encoding(
693        &self,
694    ) -> impl Iterator<Item = TransactionExtensionMetadata<'_>> {
695        let encoding_version = self.transaction_extension_version_to_use_for_encoding();
696        self.transaction_extensions_by_version(encoding_version)
697            .unwrap()
698    }
699
700    /// When presented with a v4 extrinsic that has no version, treat it as being this version.
701    pub fn transaction_extension_version_to_use_for_decoding(&self) -> u8 {
702        *self
703            .transaction_extensions_by_version
704            .keys()
705            .max()
706            .expect("At least one version of transaction extensions is expected")
707    }
708}
709
710/// Metadata for the signed extensions used by extrinsics.
711#[derive(Debug, Clone)]
712pub struct TransactionExtensionMetadata<'a> {
713    /// The unique transaction extension identifier, which may be different from the type name.
714    identifier: &'a str,
715    /// The type of the transaction extension, with the data to be included in the extrinsic.
716    extra_ty: u32,
717    /// The type of the additional signed data, with the data to be included in the signed payload.
718    additional_ty: u32,
719}
720
721#[derive(Debug, Clone)]
722struct TransactionExtensionMetadataInner {
723    identifier: String,
724    extra_ty: u32,
725    additional_ty: u32,
726}
727
728impl<'a> TransactionExtensionMetadata<'a> {
729    /// The unique signed extension identifier, which may be different from the type name.
730    pub fn identifier(&self) -> &'a str {
731        self.identifier
732    }
733    /// The type of the signed extension, with the data to be included in the extrinsic.
734    pub fn extra_ty(&self) -> u32 {
735        self.extra_ty
736    }
737    /// The type of the additional signed data, with the data to be included in the signed payload
738    pub fn additional_ty(&self) -> u32 {
739        self.additional_ty
740    }
741}
742
743/// Metadata for the outer enums.
744#[derive(Debug, Clone, Copy)]
745pub struct OuterEnumsMetadata {
746    /// The type of the outer call enum.
747    call_enum_ty: u32,
748    /// The type of the outer event enum.
749    event_enum_ty: u32,
750    /// The type of the outer error enum.
751    error_enum_ty: u32,
752}
753
754impl OuterEnumsMetadata {
755    /// The type of the outer call enum.
756    pub fn call_enum_ty(&self) -> u32 {
757        self.call_enum_ty
758    }
759
760    /// The type of the outer event enum.
761    pub fn event_enum_ty(&self) -> u32 {
762        self.event_enum_ty
763    }
764
765    /// The type of the outer error enum.
766    pub fn error_enum_ty(&self) -> u32 {
767        self.error_enum_ty
768    }
769}
770
771/// Metadata for the available runtime APIs.
772#[derive(Debug, Clone, Copy)]
773pub struct RuntimeApiMetadata<'a> {
774    inner: &'a RuntimeApiMetadataInner,
775    types: &'a PortableRegistry,
776}
777
778impl<'a> RuntimeApiMetadata<'a> {
779    /// Trait name.
780    pub fn name(&self) -> &'a str {
781        &self.inner.name
782    }
783    /// Trait documentation.
784    pub fn docs(&self) -> &[String] {
785        &self.inner.docs
786    }
787    /// An iterator over the trait methods.
788    pub fn methods(&self) -> impl ExactSizeIterator<Item = RuntimeApiMethodMetadata<'a>> + use<'a> {
789        self.inner
790            .methods
791            .values()
792            .iter()
793            .map(|item| RuntimeApiMethodMetadata {
794                trait_name: &self.inner.name,
795                inner: item,
796                types: self.types,
797            })
798    }
799    /// Get a specific trait method given its name.
800    pub fn method_by_name(&self, name: &str) -> Option<RuntimeApiMethodMetadata<'a>> {
801        self.inner
802            .methods
803            .get_by_key(name)
804            .map(|item| RuntimeApiMethodMetadata {
805                trait_name: &self.inner.name,
806                inner: item,
807                types: self.types,
808            })
809    }
810    /// Return a hash for the runtime API trait.
811    pub fn hash(&self) -> [u8; HASH_LEN] {
812        crate::utils::validation::get_runtime_apis_hash(*self)
813    }
814}
815
816#[derive(Debug, Clone)]
817struct RuntimeApiMetadataInner {
818    /// Trait name.
819    name: ArcStr,
820    /// Trait methods.
821    methods: OrderedMap<ArcStr, RuntimeApiMethodMetadataInner>,
822    /// Trait documentation.
823    docs: Vec<String>,
824}
825
826/// Metadata for a single runtime API method.
827#[derive(Debug, Clone)]
828pub struct RuntimeApiMethodMetadata<'a> {
829    trait_name: &'a str,
830    inner: &'a RuntimeApiMethodMetadataInner,
831    types: &'a PortableRegistry,
832}
833
834impl<'a> RuntimeApiMethodMetadata<'a> {
835    /// Method name.
836    pub fn name(&self) -> &'a str {
837        &self.inner.name
838    }
839    /// Method documentation.
840    pub fn docs(&self) -> &[String] {
841        &self.inner.docs
842    }
843    /// Method inputs.
844    pub fn inputs(&self) -> impl ExactSizeIterator<Item = &'a MethodParamMetadata> + use<'a> {
845        self.inner.inputs.iter()
846    }
847    /// Method return type.
848    pub fn output_ty(&self) -> u32 {
849        self.inner.output_ty
850    }
851    /// Return a hash for the method.
852    pub fn hash(&self) -> [u8; HASH_LEN] {
853        crate::utils::validation::get_runtime_api_hash(self)
854    }
855}
856
857#[derive(Debug, Clone)]
858struct RuntimeApiMethodMetadataInner {
859    /// Method name.
860    name: ArcStr,
861    /// Method parameters.
862    inputs: Vec<MethodParamMetadata>,
863    /// Method output type.
864    output_ty: u32,
865    /// Method documentation.
866    docs: Vec<String>,
867}
868
869/// Metadata for the available View Functions. Currently these exist only
870/// at the pallet level, but eventually they could exist at the runtime level too.
871#[derive(Debug, Clone, Copy)]
872pub struct ViewFunctionMetadata<'a> {
873    inner: &'a ViewFunctionMetadataInner,
874    types: &'a PortableRegistry,
875}
876
877impl<'a> ViewFunctionMetadata<'a> {
878    /// Method name.
879    pub fn name(&self) -> &'a str {
880        &self.inner.name
881    }
882    /// Query ID. This is used to query the function. Roughly, it is constructed by doing
883    /// `twox_128(pallet_name) ++ twox_128("fn_name(fnarg_types) -> return_ty")` .
884    pub fn query_id(&self) -> &'a [u8; 32] {
885        &self.inner.query_id
886    }
887    /// Method documentation.
888    pub fn docs(&self) -> &'a [String] {
889        &self.inner.docs
890    }
891    /// Method inputs.
892    pub fn inputs(&self) -> impl ExactSizeIterator<Item = &'a MethodParamMetadata> + use<'a> {
893        self.inner.inputs.iter()
894    }
895    /// Method return type.
896    pub fn output_ty(&self) -> u32 {
897        self.inner.output_ty
898    }
899    /// Return a hash for the method. The query ID of a view function validates it to some
900    /// degree, but only takes type _names_ into account. This hash takes into account the
901    /// actual _shape_ of each argument and the return type.
902    pub fn hash(&self) -> [u8; HASH_LEN] {
903        crate::utils::validation::get_view_function_hash(self)
904    }
905}
906
907#[derive(Debug, Clone)]
908struct ViewFunctionMetadataInner {
909    /// View function name.
910    name: ArcStr,
911    /// View function query ID.
912    query_id: [u8; 32],
913    /// Input types.
914    inputs: Vec<MethodParamMetadata>,
915    /// Output type.
916    output_ty: u32,
917    /// Documentation.
918    docs: Vec<String>,
919}
920
921/// Metadata for a single input parameter to a runtime API method / pallet view function.
922#[derive(Debug, Clone)]
923pub struct MethodParamMetadata {
924    /// Parameter name.
925    pub name: String,
926    /// Parameter type.
927    pub ty: u32,
928}
929
930/// Metadata of custom types with custom values, basically the same as `frame_metadata::v15::CustomMetadata<PortableForm>>`.
931#[derive(Debug, Clone)]
932pub struct CustomMetadata<'a> {
933    types: &'a PortableRegistry,
934    inner: &'a CustomMetadataInner,
935}
936
937impl<'a> CustomMetadata<'a> {
938    /// Get a certain [CustomValueMetadata] by its name.
939    pub fn get(&self, name: &str) -> Option<CustomValueMetadata<'a>> {
940        self.inner
941            .map
942            .get_key_value(name)
943            .map(|(name, e)| CustomValueMetadata {
944                types: self.types,
945                type_id: e.ty.id,
946                data: &e.value,
947                name,
948            })
949    }
950
951    /// Iterates over names (keys) and associated custom values
952    pub fn iter(&self) -> impl Iterator<Item = CustomValueMetadata<'a>> + use<'a> {
953        self.inner.map.iter().map(|(name, e)| CustomValueMetadata {
954            types: self.types,
955            type_id: e.ty.id,
956            data: &e.value,
957            name: name.as_ref(),
958        })
959    }
960
961    /// Access the underlying type registry.
962    pub fn types(&self) -> &PortableRegistry {
963        self.types
964    }
965}
966
967/// Basically the same as `frame_metadata::v15::CustomValueMetadata<PortableForm>>`, but borrowed.
968pub struct CustomValueMetadata<'a> {
969    types: &'a PortableRegistry,
970    type_id: u32,
971    data: &'a [u8],
972    name: &'a str,
973}
974
975impl<'a> CustomValueMetadata<'a> {
976    /// Access the underlying type registry.
977    pub fn types(&self) -> &PortableRegistry {
978        self.types
979    }
980
981    /// The scale encoded value
982    pub fn bytes(&self) -> &'a [u8] {
983        self.data
984    }
985
986    /// The type id in the TypeRegistry
987    pub fn type_id(&self) -> u32 {
988        self.type_id
989    }
990
991    /// The name under which the custom value is registered.
992    pub fn name(&self) -> &str {
993        self.name
994    }
995
996    /// Calculates the hash for the CustomValueMetadata.
997    pub fn hash(&self) -> [u8; HASH_LEN] {
998        get_custom_value_hash(self)
999    }
1000}
1001
1002// Support decoding metadata from the "wire" format directly into this.
1003// Errors may be lost in the case that the metadata content is somehow invalid.
1004impl codec::Decode for Metadata {
1005    fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
1006        let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(input)?;
1007        let metadata = match metadata.1 {
1008            frame_metadata::RuntimeMetadata::V14(md) => md.try_into(),
1009            frame_metadata::RuntimeMetadata::V15(md) => md.try_into(),
1010            frame_metadata::RuntimeMetadata::V16(md) => md.try_into(),
1011            _ => return Err("Cannot try_into() to Metadata: unsupported metadata version".into()),
1012        };
1013
1014        metadata.map_err(|_e| "Cannot try_into() to Metadata.".into())
1015    }
1016}