// Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #[cfg(feature = "decode")] use codec::Decode; #[cfg(feature = "serde_full")] use serde::Serialize; use super::{RuntimeMetadataPrefixed, META_RESERVED}; use codec::{Compact, Encode}; use scale_info::{ form::{Form, MetaForm, PortableForm}, prelude::{collections::BTreeMap, vec::Vec}, IntoPortable, PortableRegistry, Registry, }; // These types have not changed, so we re-export from our v14/v15 definitions: pub use super::v14::{StorageEntryMetadata, StorageEntryModifier, StorageEntryType, StorageHasher}; pub use super::v15::{CustomMetadata, CustomValueMetadata, OuterEnums}; /// The metadata for a method or function parameter. This is identical to /// [`crate::v15::RuntimeApiMethodParamMetadata`]. pub type FunctionParamMetadata = super::v15::RuntimeApiMethodParamMetadata; /// Latest runtime metadata. pub type RuntimeMetadataLastVersion = RuntimeMetadataV16; impl From for super::RuntimeMetadataPrefixed { fn from(metadata: RuntimeMetadataLastVersion) -> RuntimeMetadataPrefixed { RuntimeMetadataPrefixed(META_RESERVED, super::RuntimeMetadata::V16(metadata)) } } /// The metadata of a runtime. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] pub struct RuntimeMetadataV16 { /// Type registry containing all types used in the metadata. pub types: PortableRegistry, /// Metadata of all the pallets. pub pezpallets: Vec>, /// Metadata of the extrinsic. pub extrinsic: ExtrinsicMetadata, /// Metadata of the Runtime API. pub apis: Vec>, /// The outer enums types as found in the runtime. pub outer_enums: OuterEnums, /// Allows users to add custom types to the metadata. pub custom: CustomMetadata, } impl RuntimeMetadataV16 { /// Create a new instance of [`RuntimeMetadataV16`]. pub fn new( pezpallets: Vec, extrinsic: ExtrinsicMetadata, apis: Vec, outer_enums: OuterEnums, custom: CustomMetadata, ) -> Self { let mut registry = Registry::new(); // extrinsic types need to be collected first to ensure CheckMetadataHash hash // is stable across different metadata versions let extrinsic = extrinsic.into_portable(&mut registry); let pezpallets = registry.map_into_portable(pezpallets); let apis = registry.map_into_portable(apis); let outer_enums = outer_enums.into_portable(&mut registry); let custom = custom.into_portable(&mut registry); Self { types: registry.into(), pezpallets, extrinsic, apis, outer_enums, custom } } } /// Metadata of a runtime trait. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct RuntimeApiMetadata { /// Trait name. pub name: T::String, /// Trait methods. pub methods: Vec>, /// Trait documentation. pub docs: Vec, /// Runtime API version. pub version: Compact, /// Deprecation info. pub deprecation_info: ItemDeprecationInfo, } impl IntoPortable for RuntimeApiMetadata { type Output = RuntimeApiMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { RuntimeApiMetadata { name: self.name.into_portable(registry), methods: registry.map_into_portable(self.methods), docs: registry.map_into_portable(self.docs), version: self.version, deprecation_info: self.deprecation_info.into_portable(registry), } } } /// Metadata of a runtime method. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct RuntimeApiMethodMetadata { /// Method name. pub name: T::String, /// Method parameters. pub inputs: Vec>, /// Method output. pub output: T::Type, /// Method documentation. pub docs: Vec, /// Deprecation info pub deprecation_info: ItemDeprecationInfo, } impl IntoPortable for RuntimeApiMethodMetadata { type Output = RuntimeApiMethodMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { RuntimeApiMethodMetadata { name: self.name.into_portable(registry), inputs: registry.map_into_portable(self.inputs), output: registry.register_type(&self.output), docs: registry.map_into_portable(self.docs), deprecation_info: self.deprecation_info.into_portable(registry), } } } /// Metadata of the extrinsic used by the runtime. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct ExtrinsicMetadata { /// Extrinsic versions supported by the runtime. pub versions: Vec, /// The type of the address that signs the extrinsic pub address_ty: T::Type, /// The type of the outermost Call enum. // Dev note: this is also exposed in outer_enums, but we duplicate // it here so that ExtrinsicMetadata, on its own, provides everything // needed to decode an extrinsic. pub call_ty: T::Type, /// The type of the extrinsic's signature. pub signature_ty: T::Type, /// A mapping of supported transaction extrinsic versions to their respective transaction extension indexes. /// /// For each supported version number, list the indexes, in order, of the extensions used. pub transaction_extensions_by_version: BTreeMap>>, /// The transaction extensions in the order they appear in the extrinsic. pub transaction_extensions: Vec>, } impl IntoPortable for ExtrinsicMetadata { type Output = ExtrinsicMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { // the collection order needs to be stable across different metadata versions // to ensure CheckMetadataHash hash is invariant ExtrinsicMetadata { versions: self.versions, address_ty: registry.register_type(&self.address_ty), call_ty: registry.register_type(&self.call_ty), signature_ty: registry.register_type(&self.signature_ty), transaction_extensions_by_version: self.transaction_extensions_by_version, transaction_extensions: registry.map_into_portable(self.transaction_extensions), } } } /// Metadata of an extrinsic's transaction extension. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct TransactionExtensionMetadata { /// The unique transaction extension identifier, which may be different from the type name. pub identifier: T::String, /// The type of the transaction extension, with the data to be included in the extrinsic. pub ty: T::Type, /// The type of the implicit data, with the data to be included in the signed payload. pub implicit: T::Type, } impl IntoPortable for TransactionExtensionMetadata { type Output = TransactionExtensionMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { TransactionExtensionMetadata { identifier: self.identifier.into_portable(registry), ty: registry.register_type(&self.ty), implicit: registry.register_type(&self.implicit), } } } /// All metadata about an runtime pezpallet. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct PezpalletMetadata { /// Pezpallet name. pub name: T::String, /// Pezpallet storage metadata. pub storage: Option>, /// Pezpallet calls metadata. pub calls: Option>, /// Pezpallet event metadata. pub event: Option>, /// Pezpallet constants metadata. pub constants: Vec>, /// Pezpallet error metadata. pub error: Option>, /// Config's trait associated types. pub associated_types: Vec>, /// Pezpallet view functions metadata. pub view_functions: Vec>, /// Define the index of the pezpallet, this index will be used for the encoding of pezpallet event, /// call and origin variants. pub index: u8, /// Pezpallet documentation. pub docs: Vec, /// Deprecation info pub deprecation_info: ItemDeprecationInfo, } impl IntoPortable for PezpalletMetadata { type Output = PezpalletMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { PezpalletMetadata { name: self.name.into_portable(registry), storage: self.storage.map(|storage| storage.into_portable(registry)), calls: self.calls.map(|calls| calls.into_portable(registry)), event: self.event.map(|event| event.into_portable(registry)), constants: registry.map_into_portable(self.constants), error: self.error.map(|error| error.into_portable(registry)), associated_types: registry.map_into_portable(self.associated_types), view_functions: registry.map_into_portable(self.view_functions), index: self.index, docs: registry.map_into_portable(self.docs), deprecation_info: self.deprecation_info.into_portable(registry), } } } /// Metadata for all calls in a pezpallet. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct PezpalletCallMetadata { /// The corresponding enum type for the pezpallet call. pub ty: T::Type, /// Deprecation status of the pezpallet call pub deprecation_info: EnumDeprecationInfo, } impl IntoPortable for PezpalletCallMetadata { type Output = PezpalletCallMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { PezpalletCallMetadata { ty: registry.register_type(&self.ty), deprecation_info: self.deprecation_info.into_portable(registry), } } } /// All metadata of the pezpallet's storage. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct PezpalletStorageMetadata { /// The common prefix used by all storage entries. pub prefix: T::String, /// Metadata for all storage entries. pub entries: Vec>, } impl IntoPortable for PezpalletStorageMetadata { type Output = PezpalletStorageMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { PezpalletStorageMetadata { prefix: self.prefix.into_portable(registry), entries: registry.map_into_portable(self.entries), } } } /// Metadata about the pezpallet Event type. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct PezpalletEventMetadata { /// The Event type. pub ty: T::Type, /// Deprecation info pub deprecation_info: EnumDeprecationInfo, } impl IntoPortable for PezpalletEventMetadata { type Output = PezpalletEventMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { PezpalletEventMetadata { ty: registry.register_type(&self.ty), deprecation_info: self.deprecation_info.into_portable(registry), } } } /// Metadata about one pezpallet constant. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct PezpalletConstantMetadata { /// Name of the pezpallet constant. pub name: T::String, /// Type of the pezpallet constant. pub ty: T::Type, /// Value stored in the constant (SCALE encoded). pub value: Vec, /// Documentation of the constant. pub docs: Vec, /// Deprecation info pub deprecation_info: ItemDeprecationInfo, } impl IntoPortable for PezpalletConstantMetadata { type Output = PezpalletConstantMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { PezpalletConstantMetadata { name: self.name.into_portable(registry), ty: registry.register_type(&self.ty), value: self.value, docs: registry.map_into_portable(self.docs), deprecation_info: self.deprecation_info.into_portable(registry), } } } /// Metadata about a pezpallet error. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct PezpalletErrorMetadata { /// The error type information. pub ty: T::Type, /// Deprecation info pub deprecation_info: EnumDeprecationInfo, } impl IntoPortable for PezpalletErrorMetadata { type Output = PezpalletErrorMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { PezpalletErrorMetadata { ty: registry.register_type(&self.ty), deprecation_info: self.deprecation_info.into_portable(registry), } } } /// Metadata of a pezpallet's associated type. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct PezpalletAssociatedTypeMetadata { /// The name of the associated type. pub name: T::String, /// The type of the associated type. pub ty: T::Type, /// The documentation of the associated type. pub docs: Vec, } impl IntoPortable for PezpalletAssociatedTypeMetadata { type Output = PezpalletAssociatedTypeMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { PezpalletAssociatedTypeMetadata { name: self.name.into_portable(registry), ty: registry.register_type(&self.ty), docs: registry.map_into_portable(self.docs), } } } /// Metadata about a pezpallet view function. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct PezpalletViewFunctionMetadata { /// Method id. pub id: [u8; 32], /// Method name. pub name: T::String, /// Method parameters. pub inputs: Vec>, /// Method output. pub output: T::Type, /// Method documentation. pub docs: Vec, /// Deprecation info pub deprecation_info: ItemDeprecationInfo, } impl IntoPortable for PezpalletViewFunctionMetadata { type Output = PezpalletViewFunctionMetadata; fn into_portable(self, registry: &mut Registry) -> Self::Output { PezpalletViewFunctionMetadata { id: self.id, name: self.name.into_portable(registry), inputs: registry.map_into_portable(self.inputs), output: registry.register_type(&self.output), docs: registry.map_into_portable(self.docs), deprecation_info: self.deprecation_info.into_portable(registry), } } } /// Deprecation information for generic items. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub enum ItemDeprecationInfo { /// Item is not deprecated. NotDeprecated, /// Item is fully deprecated without a note. DeprecatedWithoutNote, /// Item is fully deprecated with a note and an optional `since` field. Deprecated { /// Note explaining the deprecation note: T::String, /// Optional value for noting the version when the deprecation occurred. since: Option, }, } impl IntoPortable for ItemDeprecationInfo { type Output = ItemDeprecationInfo; fn into_portable(self, registry: &mut Registry) -> Self::Output { match self { Self::NotDeprecated => ItemDeprecationInfo::NotDeprecated, Self::DeprecatedWithoutNote => ItemDeprecationInfo::DeprecatedWithoutNote, Self::Deprecated { note, since } => { let note = note.into_portable(registry); let since = since.map(|x| x.into_portable(registry)); ItemDeprecationInfo::Deprecated { note, since } }, } } } /// Deprecation information for enums in which specific variants can be deprecated. /// If the map is empty, then nothing is deprecated. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub struct EnumDeprecationInfo(pub BTreeMap>); impl EnumDeprecationInfo { /// Construct an instance in which nothing is marked for deprecation. pub fn nothing_deprecated() -> Self { Self(BTreeMap::new()) } /// Are any variants deprecated? pub fn has_deprecated_variants(&self) -> bool { !self.0.is_empty() } /// Is a specific variant deprecated? pub fn is_variant_deprecated(&self, variant_index: u8) -> bool { self.0.contains_key(&variant_index) } } impl IntoPortable for EnumDeprecationInfo { type Output = EnumDeprecationInfo; fn into_portable(self, registry: &mut Registry) -> Self::Output { let entries = self.0.into_iter().map(|(k, entry)| (k, entry.into_portable(registry))); EnumDeprecationInfo(entries.collect()) } } /// Deprecation information for an item or variant in the metadata. // Dev note: we use #[codec(index)] here to align the indexes with those // of ItemDeprecationInfo, allowing both can decode into this asa convenience. #[derive(Clone, PartialEq, Eq, Encode, Debug)] #[cfg_attr(feature = "decode", derive(Decode))] #[cfg_attr(feature = "serde_full", derive(Serialize))] #[cfg_attr( feature = "serde_full", serde(bound(serialize = "T::Type: Serialize, T::String: Serialize")) )] pub enum VariantDeprecationInfo { /// Variant is deprecated without a note. #[codec(index = 1)] DeprecatedWithoutNote, /// Variant is deprecated with a note and an optional `since` field. #[codec(index = 2)] Deprecated { /// Note explaining the deprecation note: T::String, /// Optional value for noting the version when the deprecation occurred. since: Option, }, } impl IntoPortable for VariantDeprecationInfo { type Output = VariantDeprecationInfo; fn into_portable(self, registry: &mut Registry) -> Self::Output { match self { Self::Deprecated { note, since } => { let note = note.into_portable(registry); let since = since.map(|x| x.into_portable(registry)); VariantDeprecationInfo::Deprecated { note, since } }, Self::DeprecatedWithoutNote => VariantDeprecationInfo::DeprecatedWithoutNote, } } }