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