subxt_metadata/from/
v15.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
5use super::TryFromError;
6
7use crate::utils::variant_index::VariantIndex;
8use crate::{
9    ArcStr, ConstantMetadata, ExtrinsicMetadata, Metadata, MethodParamMetadata, OuterEnumsMetadata,
10    PalletMetadataInner, RuntimeApiMetadataInner, RuntimeApiMethodMetadataInner,
11    StorageEntryMetadata, StorageEntryModifier, StorageEntryType, StorageHasher, StorageMetadata,
12    TransactionExtensionMetadataInner, utils::ordered_map::OrderedMap,
13};
14use alloc::collections::BTreeMap;
15use alloc::vec;
16use alloc::vec::Vec;
17use frame_metadata::v15;
18use hashbrown::HashMap;
19use scale_info::form::PortableForm;
20
21impl TryFrom<v15::RuntimeMetadataV15> for Metadata {
22    type Error = TryFromError;
23    fn try_from(m: v15::RuntimeMetadataV15) -> Result<Self, TryFromError> {
24        let mut pallets = OrderedMap::new();
25        let mut pallets_by_index = HashMap::new();
26        for (pos, p) in m.pallets.into_iter().enumerate() {
27            let name: ArcStr = p.name.into();
28
29            let storage = p.storage.map(|s| StorageMetadata {
30                prefix: s.prefix,
31                entries: s
32                    .entries
33                    .into_iter()
34                    .map(|s| {
35                        let name: ArcStr = s.name.clone().into();
36                        (name.clone(), from_storage_entry_metadata(name, s))
37                    })
38                    .collect(),
39            });
40            let constants = p.constants.into_iter().map(|c| {
41                let name: ArcStr = c.name.clone().into();
42                (name.clone(), from_constant_metadata(name, c))
43            });
44
45            let call_variant_index =
46                VariantIndex::build(p.calls.as_ref().map(|c| c.ty.id), &m.types);
47            let error_variant_index =
48                VariantIndex::build(p.error.as_ref().map(|e| e.ty.id), &m.types);
49            let event_variant_index =
50                VariantIndex::build(p.event.as_ref().map(|e| e.ty.id), &m.types);
51
52            pallets_by_index.insert(p.index, pos);
53            pallets.push_insert(
54                name.clone(),
55                PalletMetadataInner {
56                    name,
57                    index: p.index,
58                    storage,
59                    call_ty: p.calls.map(|c| c.ty.id),
60                    call_variant_index,
61                    event_ty: p.event.map(|e| e.ty.id),
62                    event_variant_index,
63                    error_ty: p.error.map(|e| e.ty.id),
64                    error_variant_index,
65                    constants: constants.collect(),
66                    view_functions: Default::default(),
67                    associated_types: Default::default(),
68                    docs: p.docs,
69                },
70            );
71        }
72
73        let apis = m.apis.into_iter().map(|api| {
74            let name: ArcStr = api.name.clone().into();
75            (name.clone(), from_runtime_api_metadata(name, api))
76        });
77
78        let dispatch_error_ty = m
79            .types
80            .types
81            .iter()
82            .find(|ty| ty.ty.path.segments == ["sp_runtime", "DispatchError"])
83            .map(|ty| ty.id);
84
85        Ok(Metadata {
86            types: m.types,
87            pallets,
88            pallets_by_index,
89            extrinsic: from_extrinsic_metadata(m.extrinsic),
90            dispatch_error_ty,
91            apis: apis.collect(),
92            outer_enums: OuterEnumsMetadata {
93                call_enum_ty: m.outer_enums.call_enum_ty.id,
94                event_enum_ty: m.outer_enums.event_enum_ty.id,
95                error_enum_ty: m.outer_enums.error_enum_ty.id,
96            },
97            custom: m.custom,
98        })
99    }
100}
101
102fn from_signed_extension_metadata(
103    value: v15::SignedExtensionMetadata<PortableForm>,
104) -> TransactionExtensionMetadataInner {
105    TransactionExtensionMetadataInner {
106        identifier: value.identifier,
107        extra_ty: value.ty.id,
108        additional_ty: value.additional_signed.id,
109    }
110}
111
112fn from_extrinsic_metadata(value: v15::ExtrinsicMetadata<PortableForm>) -> ExtrinsicMetadata {
113    let transaction_extensions: Vec<_> = value
114        .signed_extensions
115        .into_iter()
116        .map(from_signed_extension_metadata)
117        .collect();
118
119    let transaction_extension_indexes = (0..transaction_extensions.len() as u32).collect();
120
121    ExtrinsicMetadata {
122        supported_versions: vec![value.version],
123        transaction_extensions,
124        address_ty: value.address_ty.id,
125        signature_ty: value.signature_ty.id,
126        transaction_extensions_by_version: BTreeMap::from_iter([(
127            0,
128            transaction_extension_indexes,
129        )]),
130    }
131}
132
133fn from_storage_hasher(value: v15::StorageHasher) -> StorageHasher {
134    match value {
135        v15::StorageHasher::Blake2_128 => StorageHasher::Blake2_128,
136        v15::StorageHasher::Blake2_256 => StorageHasher::Blake2_256,
137        v15::StorageHasher::Blake2_128Concat => StorageHasher::Blake2_128Concat,
138        v15::StorageHasher::Twox128 => StorageHasher::Twox128,
139        v15::StorageHasher::Twox256 => StorageHasher::Twox256,
140        v15::StorageHasher::Twox64Concat => StorageHasher::Twox64Concat,
141        v15::StorageHasher::Identity => StorageHasher::Identity,
142    }
143}
144
145fn from_storage_entry_type(value: v15::StorageEntryType<PortableForm>) -> StorageEntryType {
146    match value {
147        v15::StorageEntryType::Plain(ty) => StorageEntryType::Plain(ty.id),
148        v15::StorageEntryType::Map {
149            hashers,
150            key,
151            value,
152        } => StorageEntryType::Map {
153            hashers: hashers.into_iter().map(from_storage_hasher).collect(),
154            key_ty: key.id,
155            value_ty: value.id,
156        },
157    }
158}
159
160fn from_storage_entry_modifier(value: v15::StorageEntryModifier) -> StorageEntryModifier {
161    match value {
162        v15::StorageEntryModifier::Optional => StorageEntryModifier::Optional,
163        v15::StorageEntryModifier::Default => StorageEntryModifier::Default,
164    }
165}
166
167fn from_storage_entry_metadata(
168    name: ArcStr,
169    s: v15::StorageEntryMetadata<PortableForm>,
170) -> StorageEntryMetadata {
171    StorageEntryMetadata {
172        name,
173        modifier: from_storage_entry_modifier(s.modifier),
174        entry_type: from_storage_entry_type(s.ty),
175        default: s.default,
176        docs: s.docs,
177    }
178}
179
180fn from_constant_metadata(
181    name: ArcStr,
182    s: v15::PalletConstantMetadata<PortableForm>,
183) -> ConstantMetadata {
184    ConstantMetadata {
185        name,
186        ty: s.ty.id,
187        value: s.value,
188        docs: s.docs,
189    }
190}
191
192fn from_runtime_api_metadata(
193    name: ArcStr,
194    s: v15::RuntimeApiMetadata<PortableForm>,
195) -> RuntimeApiMetadataInner {
196    RuntimeApiMetadataInner {
197        name,
198        docs: s.docs,
199        methods: s
200            .methods
201            .into_iter()
202            .map(|m| {
203                let name: ArcStr = m.name.clone().into();
204                (name.clone(), from_runtime_api_method_metadata(name, m))
205            })
206            .collect(),
207    }
208}
209
210fn from_runtime_api_method_metadata(
211    name: ArcStr,
212    s: v15::RuntimeApiMethodMetadata<PortableForm>,
213) -> RuntimeApiMethodMetadataInner {
214    RuntimeApiMethodMetadataInner {
215        name,
216        inputs: s
217            .inputs
218            .into_iter()
219            .map(from_runtime_api_method_param_metadata)
220            .collect(),
221        output_ty: s.output.id,
222        docs: s.docs,
223    }
224}
225
226fn from_runtime_api_method_param_metadata(
227    s: v15::RuntimeApiMethodParamMetadata<PortableForm>,
228) -> MethodParamMetadata {
229    MethodParamMetadata {
230        name: s.name,
231        ty: s.ty.id,
232    }
233}