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, ToString};
28use alloc::sync::Arc;
29use alloc::vec::Vec;
30use frame_decode::constants::{ConstantEntry, ConstantInfo, ConstantInfoError};
31use frame_decode::custom_values::{CustomValue, CustomValueInfo, CustomValueInfoError};
32use frame_decode::extrinsics::{
33    ExtrinsicCallInfo, ExtrinsicExtensionInfo, ExtrinsicInfoArg, ExtrinsicInfoError,
34    ExtrinsicSignatureInfo,
35};
36use frame_decode::runtime_apis::{
37    RuntimeApiEntry, RuntimeApiInfo, RuntimeApiInfoError, RuntimeApiInput,
38};
39use frame_decode::storage::{StorageEntry, StorageInfo, StorageInfoError, StorageKeyInfo};
40use frame_decode::view_functions::{
41    ViewFunctionEntry, ViewFunctionInfo, ViewFunctionInfoError, ViewFunctionInput,
42};
43use hashbrown::HashMap;
44use scale_info::{PortableRegistry, Variant, form::PortableForm};
45use utils::{
46    ordered_map::OrderedMap,
47    validation::{HASH_LEN, get_custom_value_hash},
48    variant_index::VariantIndex,
49};
50
51pub use frame_decode::storage::StorageHasher;
52pub use from::SUPPORTED_METADATA_VERSIONS;
53pub use from::TryFromError;
54pub use utils::validation::MetadataHasher;
55
56#[cfg(feature = "legacy")]
57pub use from::legacy::Error as LegacyFromError;
58
59type CustomMetadataInner = frame_metadata::v15::CustomMetadata<PortableForm>;
60
61/// Metadata is often passed around wrapped in an [`Arc`] so that it can be cloned.
62pub type ArcMetadata = Arc<Metadata>;
63
64/// Node metadata. This can be constructed by providing some compatible [`frame_metadata`]
65/// which is then decoded into this. We aim to preserve all of the existing information in
66/// the incoming metadata while optimizing the format a little for Subxt's use cases.
67#[derive(Debug)]
68pub struct Metadata {
69    /// Type registry containing all types used in the metadata.
70    types: PortableRegistry,
71    /// Metadata of all the pallets.
72    pallets: OrderedMap<String, PalletMetadataInner>,
73    /// Find the pallet for a given call index.
74    pallets_by_call_index: HashMap<u8, usize>,
75    /// Find the pallet for a given event index.
76    ///
77    /// for modern metadatas, this is the same as pallets_by_call_index,
78    /// but for old metadatas this can vary.
79    pallets_by_event_index: HashMap<u8, usize>,
80    /// Find the pallet for a given error index.
81    ///
82    /// for modern metadatas, this is the same as pallets_by_call_index,
83    /// but for old metadatas this can vary.
84    pallets_by_error_index: HashMap<u8, usize>,
85    /// Metadata of the extrinsic.
86    extrinsic: ExtrinsicMetadata,
87    /// The types of the outer enums.
88    outer_enums: OuterEnumsMetadata,
89    /// The type Id of the `DispatchError` type, which Subxt makes use of.
90    dispatch_error_ty: Option<u32>,
91    /// Details about each of the runtime API traits.
92    apis: OrderedMap<String, RuntimeApiMetadataInner>,
93    /// Allows users to add custom types to the metadata. A map that associates a string key to a `CustomValueMetadata`.
94    custom: CustomMetadataInner,
95}
96
97// Since we've abstracted away from frame-metadatas, we impl this on our custom Metadata
98// so that it can be used by `frame-decode` to obtain the relevant extrinsic info.
99impl frame_decode::extrinsics::ExtrinsicTypeInfo for Metadata {
100    type TypeId = u32;
101
102    fn extrinsic_call_info(
103        &self,
104        pallet_index: u8,
105        call_index: u8,
106    ) -> Result<ExtrinsicCallInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
107        let pallet = self.pallet_by_call_index(pallet_index).ok_or({
108            ExtrinsicInfoError::PalletNotFound {
109                index: pallet_index,
110            }
111        })?;
112
113        let call = pallet.call_variant_by_index(call_index).ok_or_else(|| {
114            ExtrinsicInfoError::CallNotFound {
115                index: call_index,
116                pallet_index,
117                pallet_name: Cow::Borrowed(pallet.name()),
118            }
119        })?;
120
121        Ok(ExtrinsicCallInfo {
122            pallet_name: Cow::Borrowed(pallet.name()),
123            call_name: Cow::Borrowed(&call.name),
124            args: call
125                .fields
126                .iter()
127                .map(|f| ExtrinsicInfoArg {
128                    name: Cow::Borrowed(f.name.as_deref().unwrap_or("")),
129                    id: f.ty.id,
130                })
131                .collect(),
132        })
133    }
134
135    fn extrinsic_signature_info(
136        &self,
137    ) -> Result<ExtrinsicSignatureInfo<Self::TypeId>, ExtrinsicInfoError<'_>> {
138        Ok(ExtrinsicSignatureInfo {
139            address_id: self.extrinsic().address_ty,
140            signature_id: self.extrinsic().signature_ty,
141        })
142    }
143
144    fn extrinsic_extension_info(
145        &self,
146        extension_version: Option<u8>,
147    ) -> Result<ExtrinsicExtensionInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
148        let extension_version = extension_version.unwrap_or_else(|| {
149            // We have some transaction, probably a V4 one with no extension version,
150            // but our metadata may support multiple versions. Use the metadata to decide
151            // what version to assume we'll decode it as.
152            self.extrinsic()
153                .transaction_extension_version_to_use_for_decoding()
154        });
155
156        let extension_ids = self
157            .extrinsic()
158            .transaction_extensions_by_version(extension_version)
159            .ok_or(ExtrinsicInfoError::ExtrinsicExtensionVersionNotFound { extension_version })?
160            .map(|f| ExtrinsicInfoArg {
161                name: Cow::Borrowed(f.identifier()),
162                id: f.extra_ty(),
163            })
164            .collect();
165
166        Ok(ExtrinsicExtensionInfo { extension_ids })
167    }
168}
169impl frame_decode::storage::StorageTypeInfo for Metadata {
170    type TypeId = u32;
171
172    fn storage_info(
173        &self,
174        pallet_name: &str,
175        storage_entry: &str,
176    ) -> Result<StorageInfo<'_, Self::TypeId>, StorageInfoError<'_>> {
177        let pallet =
178            self.pallet_by_name(pallet_name)
179                .ok_or_else(|| StorageInfoError::PalletNotFound {
180                    pallet_name: pallet_name.to_string(),
181                })?;
182        let entry = pallet
183            .storage()
184            .and_then(|storage| storage.entry_by_name(storage_entry))
185            .ok_or_else(|| StorageInfoError::StorageNotFound {
186                name: storage_entry.to_string(),
187                pallet_name: Cow::Borrowed(pallet.name()),
188            })?;
189
190        let info = StorageInfo {
191            keys: Cow::Borrowed(&*entry.info.keys),
192            value_id: entry.info.value_id,
193            default_value: entry
194                .info
195                .default_value
196                .as_ref()
197                .map(|def| Cow::Borrowed(&**def)),
198            use_old_v9_storage_hashers: false,
199        };
200
201        Ok(info)
202    }
203}
204impl frame_decode::storage::StorageEntryInfo for Metadata {
205    fn storage_entries(&self) -> impl Iterator<Item = StorageEntry<'_>> {
206        self.pallets().flat_map(|pallet| {
207            let pallet_name = pallet.name();
208            let pallet_iter = core::iter::once(StorageEntry::In(pallet_name.into()));
209            let entries_iter = pallet.storage().into_iter().flat_map(|storage| {
210                storage
211                    .entries()
212                    .iter()
213                    .map(|entry| StorageEntry::Name(entry.name().into()))
214            });
215
216            pallet_iter.chain(entries_iter)
217        })
218    }
219}
220impl frame_decode::runtime_apis::RuntimeApiTypeInfo for Metadata {
221    type TypeId = u32;
222
223    fn runtime_api_info(
224        &self,
225        trait_name: &str,
226        method_name: &str,
227    ) -> Result<RuntimeApiInfo<'_, Self::TypeId>, RuntimeApiInfoError<'_>> {
228        let api_trait =
229            self.apis
230                .get_by_key(trait_name)
231                .ok_or_else(|| RuntimeApiInfoError::TraitNotFound {
232                    trait_name: trait_name.to_string(),
233                })?;
234        let api_method = api_trait.methods.get_by_key(method_name).ok_or_else(|| {
235            RuntimeApiInfoError::MethodNotFound {
236                trait_name: Cow::Borrowed(&api_trait.name),
237                method_name: method_name.to_string(),
238            }
239        })?;
240
241        let info = RuntimeApiInfo {
242            inputs: Cow::Borrowed(&api_method.info.inputs),
243            output_id: api_method.info.output_id,
244        };
245
246        Ok(info)
247    }
248}
249impl frame_decode::runtime_apis::RuntimeApiEntryInfo for Metadata {
250    fn runtime_api_entries(&self) -> impl Iterator<Item = RuntimeApiEntry<'_>> {
251        self.runtime_api_traits().flat_map(|api_trait| {
252            let trait_name = api_trait.name();
253            let trait_iter = core::iter::once(RuntimeApiEntry::In(trait_name.into()));
254            let method_iter = api_trait
255                .methods()
256                .map(|method| RuntimeApiEntry::Name(method.name().into()));
257
258            trait_iter.chain(method_iter)
259        })
260    }
261}
262impl frame_decode::view_functions::ViewFunctionTypeInfo for Metadata {
263    type TypeId = u32;
264
265    fn view_function_info(
266        &self,
267        pallet_name: &str,
268        function_name: &str,
269    ) -> Result<ViewFunctionInfo<'_, Self::TypeId>, ViewFunctionInfoError<'_>> {
270        let pallet = self.pallet_by_name(pallet_name).ok_or_else(|| {
271            ViewFunctionInfoError::PalletNotFound {
272                pallet_name: pallet_name.to_string(),
273            }
274        })?;
275        let function = pallet.view_function_by_name(function_name).ok_or_else(|| {
276            ViewFunctionInfoError::FunctionNotFound {
277                pallet_name: Cow::Borrowed(pallet.name()),
278                function_name: function_name.to_string(),
279            }
280        })?;
281
282        let info = ViewFunctionInfo {
283            inputs: Cow::Borrowed(&function.inner.info.inputs),
284            output_id: function.inner.info.output_id,
285            query_id: *function.query_id(),
286        };
287
288        Ok(info)
289    }
290}
291impl frame_decode::view_functions::ViewFunctionEntryInfo for Metadata {
292    fn view_function_entries(&self) -> impl Iterator<Item = ViewFunctionEntry<'_>> {
293        self.pallets().flat_map(|pallet| {
294            let pallet_name = pallet.name();
295            let pallet_iter = core::iter::once(ViewFunctionEntry::In(pallet_name.into()));
296            let fn_iter = pallet
297                .view_functions()
298                .map(|function| ViewFunctionEntry::Name(function.name().into()));
299
300            pallet_iter.chain(fn_iter)
301        })
302    }
303}
304impl frame_decode::constants::ConstantTypeInfo for Metadata {
305    type TypeId = u32;
306
307    fn constant_info(
308        &self,
309        pallet_name: &str,
310        constant_name: &str,
311    ) -> Result<ConstantInfo<'_, Self::TypeId>, ConstantInfoError<'_>> {
312        let pallet =
313            self.pallet_by_name(pallet_name)
314                .ok_or_else(|| ConstantInfoError::PalletNotFound {
315                    pallet_name: pallet_name.to_string(),
316                })?;
317        let constant = pallet.constant_by_name(constant_name).ok_or_else(|| {
318            ConstantInfoError::ConstantNotFound {
319                pallet_name: Cow::Borrowed(pallet.name()),
320                constant_name: constant_name.to_string(),
321            }
322        })?;
323
324        let info = ConstantInfo {
325            bytes: &constant.value,
326            type_id: constant.ty,
327        };
328
329        Ok(info)
330    }
331}
332impl frame_decode::constants::ConstantEntryInfo for Metadata {
333    fn constant_entries(&self) -> impl Iterator<Item = ConstantEntry<'_>> {
334        self.pallets().flat_map(|pallet| {
335            let pallet_name = pallet.name();
336            let pallet_iter = core::iter::once(ConstantEntry::In(pallet_name.into()));
337            let constant_iter = pallet
338                .constants()
339                .map(|constant| ConstantEntry::Name(constant.name().into()));
340
341            pallet_iter.chain(constant_iter)
342        })
343    }
344}
345impl frame_decode::custom_values::CustomValueTypeInfo for Metadata {
346    type TypeId = u32;
347
348    fn custom_value_info(
349        &self,
350        name: &str,
351    ) -> Result<CustomValueInfo<'_, Self::TypeId>, CustomValueInfoError> {
352        let custom_value = self
353            .custom()
354            .get(name)
355            .ok_or_else(|| CustomValueInfoError {
356                not_found: name.to_string(),
357            })?;
358
359        let info = CustomValueInfo {
360            bytes: custom_value.data,
361            type_id: custom_value.type_id,
362        };
363
364        Ok(info)
365    }
366}
367impl frame_decode::custom_values::CustomValueEntryInfo for Metadata {
368    fn custom_values(&self) -> impl Iterator<Item = CustomValue<'_>> {
369        self.custom.map.keys().map(|name| CustomValue {
370            name: Cow::Borrowed(name),
371        })
372    }
373}
374
375impl Metadata {
376    /// Metadata tends to be passed around wrapped in an [`Arc`] so that it can be
377    /// cheaply cloned. This is a shorthand to return that.
378    pub fn arc(self) -> ArcMetadata {
379        Arc::new(self)
380    }
381
382    /// This is similar to`<Metadata as codec::Decode>::decode(&mut bytes)`, except it
383    /// is able to attempt to decode from several types.
384    ///
385    /// - The default assumption is that metadata is encoded as [`frame_metadata::RuntimeMetadataPrefixed`]. This is the
386    ///   expected format that metadata is encoded into, and what the [`codec::Decode`] impl tries.
387    /// - if this fails, we also try to decode as [`frame_metadata::RuntimeMetadata`].
388    /// - If this all fails, we finally will try to decode as [`frame_metadata::OpaqueMetadata`].
389    pub fn decode_from(bytes: &[u8]) -> Result<Self, codec::Error> {
390        let metadata = decode_runtime_metadata(bytes)?;
391        from_runtime_metadata(metadata)
392    }
393
394    /// Convert V16 metadata into [`Metadata`].
395    pub fn from_v16(
396        metadata: frame_metadata::v16::RuntimeMetadataV16,
397    ) -> Result<Self, TryFromError> {
398        metadata.try_into()
399    }
400
401    /// Convert V15 metadata into [`Metadata`].
402    pub fn from_v15(
403        metadata: frame_metadata::v15::RuntimeMetadataV15,
404    ) -> Result<Self, TryFromError> {
405        metadata.try_into()
406    }
407
408    /// Convert V14 metadata into [`Metadata`].
409    pub fn from_v14(
410        metadata: frame_metadata::v14::RuntimeMetadataV14,
411    ) -> Result<Self, TryFromError> {
412        metadata.try_into()
413    }
414
415    /// Convert V13 metadata into [`Metadata`], given the necessary extra type information.
416    #[cfg(feature = "legacy")]
417    pub fn from_v13(
418        metadata: &frame_metadata::v13::RuntimeMetadataV13,
419        types: &scale_info_legacy::TypeRegistrySet<'_>,
420    ) -> Result<Self, LegacyFromError> {
421        from::legacy::from_v13(metadata, types, from::legacy::Opts::compat())
422    }
423
424    /// Convert V12 metadata into [`Metadata`], given the necessary extra type information.
425    #[cfg(feature = "legacy")]
426    pub fn from_v12(
427        metadata: &frame_metadata::v12::RuntimeMetadataV12,
428        types: &scale_info_legacy::TypeRegistrySet<'_>,
429    ) -> Result<Self, LegacyFromError> {
430        from::legacy::from_v12(metadata, types, from::legacy::Opts::compat())
431    }
432
433    /// Convert V13 metadata into [`Metadata`], given the necessary extra type information.
434    #[cfg(feature = "legacy")]
435    pub fn from_v11(
436        metadata: &frame_metadata::v11::RuntimeMetadataV11,
437        types: &scale_info_legacy::TypeRegistrySet<'_>,
438    ) -> Result<Self, LegacyFromError> {
439        from::legacy::from_v11(metadata, types, from::legacy::Opts::compat())
440    }
441
442    /// Convert V13 metadata into [`Metadata`], given the necessary extra type information.
443    #[cfg(feature = "legacy")]
444    pub fn from_v10(
445        metadata: &frame_metadata::v10::RuntimeMetadataV10,
446        types: &scale_info_legacy::TypeRegistrySet<'_>,
447    ) -> Result<Self, LegacyFromError> {
448        from::legacy::from_v10(metadata, types, from::legacy::Opts::compat())
449    }
450
451    /// Convert V9 metadata into [`Metadata`], given the necessary extra type information.
452    #[cfg(feature = "legacy")]
453    pub fn from_v9(
454        metadata: &frame_metadata::v9::RuntimeMetadataV9,
455        types: &scale_info_legacy::TypeRegistrySet<'_>,
456    ) -> Result<Self, LegacyFromError> {
457        from::legacy::from_v9(metadata, types, from::legacy::Opts::compat())
458    }
459
460    /// Convert V8 metadata into [`Metadata`], given the necessary extra type information.
461    #[cfg(feature = "legacy")]
462    pub fn from_v8(
463        metadata: &frame_metadata::v8::RuntimeMetadataV8,
464        types: &scale_info_legacy::TypeRegistrySet<'_>,
465    ) -> Result<Self, LegacyFromError> {
466        from::legacy::from_v8(metadata, types, from::legacy::Opts::compat())
467    }
468
469    /// Access the underlying type registry.
470    pub fn types(&self) -> &PortableRegistry {
471        &self.types
472    }
473
474    /// Mutable access to the underlying type registry.
475    pub fn types_mut(&mut self) -> &mut PortableRegistry {
476        &mut self.types
477    }
478
479    /// The type ID of the `DispatchError` type, if it exists.
480    pub fn dispatch_error_ty(&self) -> Option<u32> {
481        self.dispatch_error_ty
482    }
483
484    /// Return details about the extrinsic format.
485    pub fn extrinsic(&self) -> &ExtrinsicMetadata {
486        &self.extrinsic
487    }
488
489    /// Return details about the outer enums.
490    pub fn outer_enums(&self) -> OuterEnumsMetadata {
491        self.outer_enums
492    }
493
494    /// An iterator over all of the available pallets.
495    pub fn pallets(&self) -> impl ExactSizeIterator<Item = PalletMetadata<'_>> {
496        self.pallets.values().iter().map(|inner| PalletMetadata {
497            inner,
498            types: self.types(),
499        })
500    }
501
502    /// Access a pallet given some call/extrinsic pallet index byte
503    pub fn pallet_by_call_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
504        let inner = self
505            .pallets_by_call_index
506            .get(&variant_index)
507            .and_then(|i| self.pallets.get_by_index(*i))?;
508
509        Some(PalletMetadata {
510            inner,
511            types: self.types(),
512        })
513    }
514
515    /// Access a pallet given some event pallet index byte
516    pub fn pallet_by_event_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
517        let inner = self
518            .pallets_by_event_index
519            .get(&variant_index)
520            .and_then(|i| self.pallets.get_by_index(*i))?;
521
522        Some(PalletMetadata {
523            inner,
524            types: self.types(),
525        })
526    }
527
528    /// Access a pallet given some error pallet index byte
529    pub fn pallet_by_error_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
530        let inner = self
531            .pallets_by_error_index
532            .get(&variant_index)
533            .and_then(|i| self.pallets.get_by_index(*i))?;
534
535        Some(PalletMetadata {
536            inner,
537            types: self.types(),
538        })
539    }
540
541    /// Access a pallet given its name.
542    pub fn pallet_by_name(&self, pallet_name: &str) -> Option<PalletMetadata<'_>> {
543        let inner = self.pallets.get_by_key(pallet_name)?;
544
545        Some(PalletMetadata {
546            inner,
547            types: self.types(),
548        })
549    }
550
551    /// An iterator over all of the runtime APIs.
552    pub fn runtime_api_traits(&self) -> impl ExactSizeIterator<Item = RuntimeApiMetadata<'_>> {
553        self.apis.values().iter().map(|inner| RuntimeApiMetadata {
554            inner,
555            types: self.types(),
556        })
557    }
558
559    /// Access a runtime API trait given its name.
560    pub fn runtime_api_trait_by_name(&'_ self, name: &str) -> Option<RuntimeApiMetadata<'_>> {
561        let inner = self.apis.get_by_key(name)?;
562        Some(RuntimeApiMetadata {
563            inner,
564            types: self.types(),
565        })
566    }
567
568    /// Returns custom user defined types
569    pub fn custom(&self) -> CustomMetadata<'_> {
570        CustomMetadata {
571            types: self.types(),
572            inner: &self.custom,
573        }
574    }
575
576    /// Obtain a unique hash representing this metadata or specific parts of it.
577    pub fn hasher(&self) -> MetadataHasher<'_> {
578        MetadataHasher::new(self)
579    }
580
581    /// Get type hash for a type in the registry
582    pub fn type_hash(&self, id: u32) -> Option<[u8; HASH_LEN]> {
583        self.types.resolve(id)?;
584        Some(crate::utils::validation::get_type_hash(&self.types, id))
585    }
586}
587
588/// Metadata for a specific pallet.
589#[derive(Debug, Clone, Copy)]
590pub struct PalletMetadata<'a> {
591    inner: &'a PalletMetadataInner,
592    types: &'a PortableRegistry,
593}
594
595impl<'a> PalletMetadata<'a> {
596    /// The pallet name.
597    pub fn name(&self) -> &'a str {
598        &self.inner.name
599    }
600
601    /// The index to use for calls in this pallet.
602    pub fn call_index(&self) -> u8 {
603        self.inner.call_index
604    }
605
606    /// The index to use for events in this pallet.
607    pub fn event_index(&self) -> u8 {
608        self.inner.event_index
609    }
610
611    /// The index to use for errors in this pallet.
612    pub fn error_index(&self) -> u8 {
613        self.inner.error_index
614    }
615
616    /// The pallet docs.
617    pub fn docs(&self) -> &'a [String] {
618        &self.inner.docs
619    }
620
621    /// Type ID for the pallet's Call type, if it exists.
622    pub fn call_ty_id(&self) -> Option<u32> {
623        self.inner.call_ty
624    }
625
626    /// Type ID for the pallet's Event type, if it exists.
627    pub fn event_ty_id(&self) -> Option<u32> {
628        self.inner.event_ty
629    }
630
631    /// Type ID for the pallet's Error type, if it exists.
632    pub fn error_ty_id(&self) -> Option<u32> {
633        self.inner.error_ty
634    }
635
636    /// Return metadata about the pallet's storage entries.
637    pub fn storage(&self) -> Option<&'a StorageMetadata> {
638        self.inner.storage.as_ref()
639    }
640
641    /// Return all of the event variants, if an event type exists.
642    pub fn event_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
643        VariantIndex::get(self.inner.event_ty, self.types)
644    }
645
646    /// Return an event variant given it's encoded variant index.
647    pub fn event_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
648        self.inner.event_variant_index.lookup_by_index(
649            variant_index,
650            self.inner.event_ty,
651            self.types,
652        )
653    }
654
655    /// Does this pallet have any view functions?
656    pub fn has_view_functions(&self) -> bool {
657        !self.inner.view_functions.is_empty()
658    }
659
660    /// Return an iterator over the View Functions in this pallet, if any.
661    pub fn view_functions(
662        &self,
663    ) -> impl ExactSizeIterator<Item = ViewFunctionMetadata<'a>> + use<'a> {
664        self.inner
665            .view_functions
666            .values()
667            .iter()
668            .map(|vf: &'a _| ViewFunctionMetadata {
669                inner: vf,
670                types: self.types,
671            })
672    }
673
674    /// Return the view function with a given name, if any
675    pub fn view_function_by_name(&self, name: &str) -> Option<ViewFunctionMetadata<'a>> {
676        self.inner
677            .view_functions
678            .get_by_key(name)
679            .map(|vf: &'a _| ViewFunctionMetadata {
680                inner: vf,
681                types: self.types,
682            })
683    }
684
685    /// Iterate (in no particular order) over the associated type names and type IDs for this pallet.
686    pub fn associated_types(&self) -> impl ExactSizeIterator<Item = (&'a str, u32)> + use<'a> {
687        self.inner
688            .associated_types
689            .iter()
690            .map(|(name, ty)| (&**name, *ty))
691    }
692
693    /// Fetch an associated type ID given the associated type name.
694    pub fn associated_type_id(&self, name: &str) -> Option<u32> {
695        self.inner.associated_types.get(name).copied()
696    }
697
698    /// Return all of the call variants, if a call type exists.
699    pub fn call_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
700        VariantIndex::get(self.inner.call_ty, self.types)
701    }
702
703    /// Return a call variant given it's encoded variant index.
704    pub fn call_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
705        self.inner
706            .call_variant_index
707            .lookup_by_index(variant_index, self.inner.call_ty, self.types)
708    }
709
710    /// Return a call variant given it's name.
711    pub fn call_variant_by_name(&self, call_name: &str) -> Option<&'a Variant<PortableForm>> {
712        self.inner
713            .call_variant_index
714            .lookup_by_name(call_name, self.inner.call_ty, self.types)
715    }
716
717    /// Return all of the error variants, if an error type exists.
718    pub fn error_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
719        VariantIndex::get(self.inner.error_ty, self.types)
720    }
721
722    /// Return an error variant given it's encoded variant index.
723    pub fn error_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
724        self.inner.error_variant_index.lookup_by_index(
725            variant_index,
726            self.inner.error_ty,
727            self.types,
728        )
729    }
730
731    /// Return constant details given the constant name.
732    pub fn constant_by_name(&self, name: &str) -> Option<&'a ConstantMetadata> {
733        self.inner.constants.get_by_key(name)
734    }
735
736    /// An iterator over the constants in this pallet.
737    pub fn constants(&self) -> impl ExactSizeIterator<Item = &'a ConstantMetadata> + use<'a> {
738        self.inner.constants.values().iter()
739    }
740
741    /// Return a hash for the storage entry, or None if it was not found.
742    pub fn storage_hash(&self, entry_name: &str) -> Option<[u8; HASH_LEN]> {
743        crate::utils::validation::get_storage_hash(self, entry_name)
744    }
745
746    /// Return a hash for the constant, or None if it was not found.
747    pub fn constant_hash(&self, constant_name: &str) -> Option<[u8; HASH_LEN]> {
748        crate::utils::validation::get_constant_hash(self, constant_name)
749    }
750
751    /// Return a hash for the call, or None if it was not found.
752    pub fn call_hash(&self, call_name: &str) -> Option<[u8; HASH_LEN]> {
753        crate::utils::validation::get_call_hash(self, call_name)
754    }
755
756    /// Return a hash for the entire pallet.
757    pub fn hash(&self) -> [u8; HASH_LEN] {
758        crate::utils::validation::get_pallet_hash(*self)
759    }
760}
761
762#[derive(Debug, Clone)]
763struct PalletMetadataInner {
764    /// Pallet name.
765    name: String,
766    /// The index for calls in the pallet.
767    call_index: u8,
768    /// The index for events in the pallet.
769    ///
770    /// This is the same as `call_index` for modern metadatas,
771    /// but can be different for older metadatas (pre-V12).
772    event_index: u8,
773    /// The index for errors in the pallet.
774    ///
775    /// This is the same as `call_index` for modern metadatas,
776    /// but can be different for older metadatas (pre-V12).
777    error_index: u8,
778    /// Pallet storage metadata.
779    storage: Option<StorageMetadata>,
780    /// Type ID for the pallet Call enum.
781    call_ty: Option<u32>,
782    /// Call variants by name/u8.
783    call_variant_index: VariantIndex,
784    /// Type ID for the pallet Event enum.
785    event_ty: Option<u32>,
786    /// Event variants by name/u8.
787    event_variant_index: VariantIndex,
788    /// Type ID for the pallet Error enum.
789    error_ty: Option<u32>,
790    /// Error variants by name/u8.
791    error_variant_index: VariantIndex,
792    /// Map from constant name to constant details.
793    constants: OrderedMap<String, ConstantMetadata>,
794    /// Details about each of the pallet view functions.
795    view_functions: OrderedMap<String, ViewFunctionMetadataInner>,
796    /// Mapping from associated type to type ID describing its shape.
797    associated_types: BTreeMap<String, u32>,
798    /// Pallet documentation.
799    docs: Vec<String>,
800}
801
802/// Metadata for the storage entries in a pallet.
803#[derive(Debug, Clone)]
804pub struct StorageMetadata {
805    /// The common prefix used by all storage entries.
806    prefix: String,
807    /// Map from storage entry name to details.
808    entries: OrderedMap<String, StorageEntryMetadata>,
809}
810
811impl StorageMetadata {
812    /// The common prefix used by all storage entries.
813    pub fn prefix(&self) -> &str {
814        &self.prefix
815    }
816
817    /// An iterator over the storage entries.
818    pub fn entries(&self) -> &[StorageEntryMetadata] {
819        self.entries.values()
820    }
821
822    /// Return a specific storage entry given its name.
823    pub fn entry_by_name(&self, name: &str) -> Option<&StorageEntryMetadata> {
824        self.entries.get_by_key(name)
825    }
826}
827
828/// Metadata for a single storage entry.
829#[derive(Debug, Clone)]
830pub struct StorageEntryMetadata {
831    /// Variable name of the storage entry.
832    name: String,
833    /// Information about the storage entry.
834    info: StorageInfo<'static, u32>,
835    /// Storage entry documentation.
836    docs: Vec<String>,
837}
838
839impl StorageEntryMetadata {
840    /// Name of this entry.
841    pub fn name(&self) -> &str {
842        &self.name
843    }
844    /// Keys in this storage entry.
845    pub fn keys(&self) -> impl ExactSizeIterator<Item = &StorageKeyInfo<u32>> {
846        let keys = &*self.info.keys;
847        keys.iter()
848    }
849    /// Value type for this storage entry.
850    pub fn value_ty(&self) -> u32 {
851        self.info.value_id
852    }
853    /// The default value, if one exists, for this entry.
854    pub fn default_value(&self) -> Option<&[u8]> {
855        self.info.default_value.as_deref()
856    }
857    /// Storage entry documentation.
858    pub fn docs(&self) -> &[String] {
859        &self.docs
860    }
861}
862
863/// Metadata for a single constant.
864#[derive(Debug, Clone)]
865pub struct ConstantMetadata {
866    /// Name of the pallet constant.
867    name: String,
868    /// Type of the pallet constant.
869    ty: u32,
870    /// Value stored in the constant (SCALE encoded).
871    value: Vec<u8>,
872    /// Constant documentation.
873    docs: Vec<String>,
874}
875
876impl ConstantMetadata {
877    /// Name of the pallet constant.
878    pub fn name(&self) -> &str {
879        &self.name
880    }
881    /// Type of the pallet constant.
882    pub fn ty(&self) -> u32 {
883        self.ty
884    }
885    /// Value stored in the constant (SCALE encoded).
886    pub fn value(&self) -> &[u8] {
887        &self.value
888    }
889    /// Constant documentation.
890    pub fn docs(&self) -> &[String] {
891        &self.docs
892    }
893}
894
895/// Metadata for the extrinsic type.
896#[derive(Debug, Clone)]
897pub struct ExtrinsicMetadata {
898    /// The type of the address that signs the extrinsic.
899    /// Used to help decode tx signatures.
900    address_ty: u32,
901    /// The type of the extrinsic's signature.
902    /// Used to help decode tx signatures.
903    signature_ty: u32,
904    /// Which extrinsic versions are supported by this chain.
905    supported_versions: Vec<u8>,
906    /// The signed extensions in the order they appear in the extrinsic.
907    transaction_extensions: Vec<TransactionExtensionMetadataInner>,
908    /// Different versions of transaction extensions can exist. Each version
909    /// is a u8 which corresponds to the indexes of the transaction extensions
910    /// seen in the above Vec, in order, that exist at that version.
911    transaction_extensions_by_version: BTreeMap<u8, Vec<u32>>,
912}
913
914impl ExtrinsicMetadata {
915    /// Which extrinsic versions are supported.
916    pub fn supported_versions(&self) -> &[u8] {
917        &self.supported_versions
918    }
919
920    /// The extra/additional information associated with the extrinsic.
921    pub fn transaction_extensions_by_version(
922        &self,
923        version: u8,
924    ) -> Option<impl Iterator<Item = TransactionExtensionMetadata<'_>>> {
925        let extension_indexes = self.transaction_extensions_by_version.get(&version)?;
926        let iter = extension_indexes.iter().map(|index| {
927            let tx_metadata = self
928                .transaction_extensions
929                .get(*index as usize)
930                .expect("transaction extension should exist if index is in transaction_extensions_by_version");
931
932            TransactionExtensionMetadata {
933                identifier: &tx_metadata.identifier,
934                extra_ty: tx_metadata.extra_ty,
935                additional_ty: tx_metadata.additional_ty,
936            }
937        });
938
939        Some(iter)
940    }
941
942    /// When constructing a v5 extrinsic, use this transaction extensions version.
943    pub fn transaction_extension_version_to_use_for_encoding(&self) -> u8 {
944        *self
945            .transaction_extensions_by_version
946            .keys()
947            .max()
948            .expect("At least one version of transaction extensions is expected")
949    }
950
951    /// An iterator of the transaction extensions to use when encoding a transaction. Basically equivalent to
952    /// `self.transaction_extensions_by_version(self.transaction_extension_version_to_use_for_encoding()).unwrap()`
953    pub fn transaction_extensions_to_use_for_encoding(
954        &self,
955    ) -> impl Iterator<Item = TransactionExtensionMetadata<'_>> {
956        let encoding_version = self.transaction_extension_version_to_use_for_encoding();
957        self.transaction_extensions_by_version(encoding_version)
958            .unwrap()
959    }
960
961    /// When presented with a v4 extrinsic that has no version, treat it as being this version.
962    pub fn transaction_extension_version_to_use_for_decoding(&self) -> u8 {
963        *self
964            .transaction_extensions_by_version
965            .keys()
966            .max()
967            .expect("At least one version of transaction extensions is expected")
968    }
969}
970
971/// Metadata for the signed extensions used by extrinsics.
972#[derive(Debug, Clone)]
973pub struct TransactionExtensionMetadata<'a> {
974    /// The unique transaction extension identifier, which may be different from the type name.
975    identifier: &'a str,
976    /// The type of the transaction extension, with the data to be included in the extrinsic.
977    extra_ty: u32,
978    /// The type of the additional signed data, with the data to be included in the signed payload.
979    additional_ty: u32,
980}
981
982#[derive(Debug, Clone)]
983struct TransactionExtensionMetadataInner {
984    identifier: String,
985    extra_ty: u32,
986    additional_ty: u32,
987}
988
989impl<'a> TransactionExtensionMetadata<'a> {
990    /// The unique signed extension identifier, which may be different from the type name.
991    pub fn identifier(&self) -> &'a str {
992        self.identifier
993    }
994    /// The type of the signed extension, with the data to be included in the extrinsic.
995    pub fn extra_ty(&self) -> u32 {
996        self.extra_ty
997    }
998    /// The type of the additional signed data, with the data to be included in the signed payload
999    pub fn additional_ty(&self) -> u32 {
1000        self.additional_ty
1001    }
1002}
1003
1004/// Metadata for the outer enums.
1005#[derive(Debug, Clone, Copy)]
1006pub struct OuterEnumsMetadata {
1007    /// The type of the outer call enum.
1008    call_enum_ty: u32,
1009    /// The type of the outer event enum.
1010    event_enum_ty: u32,
1011    /// The type of the outer error enum.
1012    error_enum_ty: u32,
1013}
1014
1015impl OuterEnumsMetadata {
1016    /// The type of the outer call enum.
1017    pub fn call_enum_ty(&self) -> u32 {
1018        self.call_enum_ty
1019    }
1020
1021    /// The type of the outer event enum.
1022    pub fn event_enum_ty(&self) -> u32 {
1023        self.event_enum_ty
1024    }
1025
1026    /// The type of the outer error enum.
1027    pub fn error_enum_ty(&self) -> u32 {
1028        self.error_enum_ty
1029    }
1030}
1031
1032/// Metadata for the available runtime APIs.
1033#[derive(Debug, Clone, Copy)]
1034pub struct RuntimeApiMetadata<'a> {
1035    inner: &'a RuntimeApiMetadataInner,
1036    types: &'a PortableRegistry,
1037}
1038
1039impl<'a> RuntimeApiMetadata<'a> {
1040    /// Trait name.
1041    pub fn name(&self) -> &'a str {
1042        &self.inner.name
1043    }
1044    /// Trait documentation.
1045    pub fn docs(&self) -> &[String] {
1046        &self.inner.docs
1047    }
1048    /// An iterator over the trait methods.
1049    pub fn methods(&self) -> impl ExactSizeIterator<Item = RuntimeApiMethodMetadata<'a>> + use<'a> {
1050        self.inner
1051            .methods
1052            .values()
1053            .iter()
1054            .map(|item| RuntimeApiMethodMetadata {
1055                trait_name: &self.inner.name,
1056                inner: item,
1057                types: self.types,
1058            })
1059    }
1060    /// Get a specific trait method given its name.
1061    pub fn method_by_name(&self, name: &str) -> Option<RuntimeApiMethodMetadata<'a>> {
1062        self.inner
1063            .methods
1064            .get_by_key(name)
1065            .map(|item| RuntimeApiMethodMetadata {
1066                trait_name: &self.inner.name,
1067                inner: item,
1068                types: self.types,
1069            })
1070    }
1071    /// Return a hash for the runtime API trait.
1072    pub fn hash(&self) -> [u8; HASH_LEN] {
1073        crate::utils::validation::get_runtime_apis_hash(*self)
1074    }
1075}
1076
1077#[derive(Debug, Clone)]
1078struct RuntimeApiMetadataInner {
1079    /// Trait name.
1080    name: String,
1081    /// Trait methods.
1082    methods: OrderedMap<String, RuntimeApiMethodMetadataInner>,
1083    /// Trait documentation.
1084    docs: Vec<String>,
1085}
1086
1087/// Metadata for a single runtime API method.
1088#[derive(Debug, Clone)]
1089pub struct RuntimeApiMethodMetadata<'a> {
1090    trait_name: &'a str,
1091    inner: &'a RuntimeApiMethodMetadataInner,
1092    types: &'a PortableRegistry,
1093}
1094
1095impl<'a> RuntimeApiMethodMetadata<'a> {
1096    /// Method name.
1097    pub fn name(&self) -> &'a str {
1098        &self.inner.name
1099    }
1100    /// Method documentation.
1101    pub fn docs(&self) -> &[String] {
1102        &self.inner.docs
1103    }
1104    /// Method inputs.
1105    pub fn inputs(
1106        &self,
1107    ) -> impl ExactSizeIterator<Item = &'a RuntimeApiInput<'static, u32>> + use<'a> {
1108        let inputs = &*self.inner.info.inputs;
1109        inputs.iter()
1110    }
1111    /// Method return type.
1112    pub fn output_ty(&self) -> u32 {
1113        self.inner.info.output_id
1114    }
1115    /// Return a hash for the method.
1116    pub fn hash(&self) -> [u8; HASH_LEN] {
1117        crate::utils::validation::get_runtime_api_hash(self)
1118    }
1119}
1120
1121#[derive(Debug, Clone)]
1122struct RuntimeApiMethodMetadataInner {
1123    /// Method name.
1124    name: String,
1125    /// Info.
1126    info: RuntimeApiInfo<'static, u32>,
1127    /// Method documentation.
1128    docs: Vec<String>,
1129}
1130
1131/// Metadata for the available View Functions. Currently these exist only
1132/// at the pallet level, but eventually they could exist at the runtime level too.
1133#[derive(Debug, Clone, Copy)]
1134pub struct ViewFunctionMetadata<'a> {
1135    inner: &'a ViewFunctionMetadataInner,
1136    types: &'a PortableRegistry,
1137}
1138
1139impl<'a> ViewFunctionMetadata<'a> {
1140    /// Method name.
1141    pub fn name(&self) -> &'a str {
1142        &self.inner.name
1143    }
1144    /// Query ID. This is used to query the function. Roughly, it is constructed by doing
1145    /// `twox_128(pallet_name) ++ twox_128("fn_name(fnarg_types) -> return_ty")` .
1146    pub fn query_id(&self) -> &'a [u8; 32] {
1147        &self.inner.info.query_id
1148    }
1149    /// Method documentation.
1150    pub fn docs(&self) -> &'a [String] {
1151        &self.inner.docs
1152    }
1153    /// Method inputs.
1154    pub fn inputs(
1155        &self,
1156    ) -> impl ExactSizeIterator<Item = &'a ViewFunctionInput<'static, u32>> + use<'a> {
1157        let inputs = &*self.inner.info.inputs;
1158        inputs.iter()
1159    }
1160    /// Method return type.
1161    pub fn output_ty(&self) -> u32 {
1162        self.inner.info.output_id
1163    }
1164    /// Return a hash for the method. The query ID of a view function validates it to some
1165    /// degree, but only takes type _names_ into account. This hash takes into account the
1166    /// actual _shape_ of each argument and the return type.
1167    pub fn hash(&self) -> [u8; HASH_LEN] {
1168        crate::utils::validation::get_view_function_hash(self)
1169    }
1170}
1171
1172#[derive(Debug, Clone)]
1173struct ViewFunctionMetadataInner {
1174    /// View function name.
1175    name: String,
1176    /// Info.
1177    info: ViewFunctionInfo<'static, u32>,
1178    /// Documentation.
1179    docs: Vec<String>,
1180}
1181
1182/// Metadata for a single input parameter to a runtime API method / pallet view function.
1183#[derive(Debug, Clone)]
1184pub struct MethodParamMetadata {
1185    /// Parameter name.
1186    pub name: String,
1187    /// Parameter type.
1188    pub ty: u32,
1189}
1190
1191/// Metadata of custom types with custom values, basically the same as `frame_metadata::v15::CustomMetadata<PortableForm>>`.
1192#[derive(Debug, Clone)]
1193pub struct CustomMetadata<'a> {
1194    types: &'a PortableRegistry,
1195    inner: &'a CustomMetadataInner,
1196}
1197
1198impl<'a> CustomMetadata<'a> {
1199    /// Get a certain [CustomValueMetadata] by its name.
1200    pub fn get(&self, name: &str) -> Option<CustomValueMetadata<'a>> {
1201        self.inner
1202            .map
1203            .get_key_value(name)
1204            .map(|(name, e)| CustomValueMetadata {
1205                types: self.types,
1206                type_id: e.ty.id,
1207                data: &e.value,
1208                name,
1209            })
1210    }
1211
1212    /// Iterates over names (keys) and associated custom values
1213    pub fn iter(&self) -> impl Iterator<Item = CustomValueMetadata<'a>> + use<'a> {
1214        self.inner.map.iter().map(|(name, e)| CustomValueMetadata {
1215            types: self.types,
1216            type_id: e.ty.id,
1217            data: &e.value,
1218            name: name.as_ref(),
1219        })
1220    }
1221
1222    /// Access the underlying type registry.
1223    pub fn types(&self) -> &PortableRegistry {
1224        self.types
1225    }
1226}
1227
1228/// Basically the same as `frame_metadata::v15::CustomValueMetadata<PortableForm>>`, but borrowed.
1229pub struct CustomValueMetadata<'a> {
1230    types: &'a PortableRegistry,
1231    type_id: u32,
1232    data: &'a [u8],
1233    name: &'a str,
1234}
1235
1236impl<'a> CustomValueMetadata<'a> {
1237    /// Access the underlying type registry.
1238    pub fn types(&self) -> &PortableRegistry {
1239        self.types
1240    }
1241
1242    /// The scale encoded value
1243    pub fn bytes(&self) -> &'a [u8] {
1244        self.data
1245    }
1246
1247    /// The type id in the TypeRegistry
1248    pub fn type_id(&self) -> u32 {
1249        self.type_id
1250    }
1251
1252    /// The name under which the custom value is registered.
1253    pub fn name(&self) -> &str {
1254        self.name
1255    }
1256
1257    /// Calculates the hash for the CustomValueMetadata.
1258    pub fn hash(&self) -> [u8; HASH_LEN] {
1259        get_custom_value_hash(self)
1260    }
1261}
1262
1263// Support decoding metadata from the "wire" format directly into this.
1264impl codec::Decode for Metadata {
1265    fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
1266        let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(input)?;
1267        from_runtime_metadata(metadata.1)
1268    }
1269}
1270
1271/// A utility function to decode SCALE encoded metadata. This is much like [`Metadata::decode_from`] but doesn't
1272/// do the final step of converting the decoded metadata into [`Metadata`].
1273///
1274/// - The default assumption is that metadata is encoded as [`frame_metadata::RuntimeMetadataPrefixed`]. This is the
1275///   expected format that metadata is encoded into.
1276/// - if this fails, we also try to decode as [`frame_metadata::RuntimeMetadata`].
1277/// - If this all fails, we also try to decode as [`frame_metadata::OpaqueMetadata`].
1278pub fn decode_runtime_metadata(
1279    input: &[u8],
1280) -> Result<frame_metadata::RuntimeMetadata, codec::Error> {
1281    use codec::Decode;
1282
1283    let err = match frame_metadata::RuntimeMetadataPrefixed::decode(&mut &*input) {
1284        Ok(md) => return Ok(md.1),
1285        Err(e) => e,
1286    };
1287
1288    if let Ok(md) = frame_metadata::RuntimeMetadata::decode(&mut &*input) {
1289        return Ok(md);
1290    }
1291
1292    // frame_metadata::OpaqueMetadata is a vec of bytes. If we can decode the length, AND
1293    // the length definitely corresponds to the number of remaining bytes, then we try to
1294    // decode the inner bytes.
1295    if let Ok(len) = codec::Compact::<u64>::decode(&mut &*input) {
1296        if input.len() == len.0 as usize {
1297            return decode_runtime_metadata(input);
1298        }
1299    }
1300
1301    Err(err)
1302}
1303
1304/// Convert RuntimeMetadata into Metadata if possible.
1305fn from_runtime_metadata(
1306    metadata: frame_metadata::RuntimeMetadata,
1307) -> Result<Metadata, codec::Error> {
1308    let metadata = match metadata {
1309        frame_metadata::RuntimeMetadata::V14(md) => md.try_into(),
1310        frame_metadata::RuntimeMetadata::V15(md) => md.try_into(),
1311        frame_metadata::RuntimeMetadata::V16(md) => md.try_into(),
1312        _ => {
1313            let reason = alloc::format!(
1314                "RuntimeMetadata version {} cannot be decoded from",
1315                metadata.version()
1316            );
1317            let e: codec::Error = "Metadata::decode failed: Cannot try_into() to Metadata: unsupported metadata version".into();
1318            return Err(e.chain(reason));
1319        }
1320    };
1321
1322    metadata.map_err(|reason: TryFromError| {
1323        let e: codec::Error = "Metadata::decode failed: Cannot try_into() to Metadata".into();
1324        e.chain(reason.to_string())
1325    })
1326}