Skip to main content

subxt_metadata/
lib.rs

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