1use 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}