1use super::TryFromError;
6
7use crate::utils::variant_index::VariantIndex;
8use crate::{
9 ConstantMetadata, ExtrinsicMetadata, Metadata, OuterEnumsMetadata, PalletMetadataInner,
10 RuntimeApiMetadataInner, RuntimeApiMethodMetadataInner, StorageEntryMetadata, StorageMetadata,
11 TransactionExtensionMetadataInner, utils::ordered_map::OrderedMap,
12};
13use alloc::collections::BTreeMap;
14use alloc::vec;
15use alloc::vec::Vec;
16use frame_decode::runtime_apis::RuntimeApiTypeInfo;
17use frame_decode::storage::StorageTypeInfo;
18use frame_metadata::v15;
19use hashbrown::HashMap;
20use scale_info::form::PortableForm;
21
22impl TryFrom<v15::RuntimeMetadataV15> for Metadata {
23 type Error = TryFromError;
24 fn try_from(m: v15::RuntimeMetadataV15) -> Result<Self, TryFromError> {
25 let mut pallets = OrderedMap::new();
26 let mut pallets_by_index = HashMap::new();
27 for (pos, p) in m.pallets.iter().enumerate() {
28 let name = p.name.clone();
29
30 let storage = match &p.storage {
31 None => None,
32 Some(s) => Some(StorageMetadata {
33 prefix: s.prefix.clone(),
34 entries: s
35 .entries
36 .iter()
37 .map(|s| {
38 let entry_name = s.name.clone();
39 let storage_info = m
40 .storage_info(&name, &entry_name)
41 .map_err(|e| e.into_owned())?
42 .into_owned();
43 let storage_entry = StorageEntryMetadata {
44 name: entry_name.clone(),
45 info: storage_info,
46 docs: s.docs.clone(),
47 };
48
49 Ok::<_, TryFromError>((entry_name, storage_entry))
50 })
51 .collect::<Result<_, TryFromError>>()?,
52 }),
53 };
54
55 let constants = p.constants.iter().map(|c| {
56 let name = c.name.clone();
57 (name, from_constant_metadata(c.clone()))
58 });
59
60 let call_variant_index =
61 VariantIndex::build(p.calls.as_ref().map(|c| c.ty.id), &m.types);
62 let error_variant_index =
63 VariantIndex::build(p.error.as_ref().map(|e| e.ty.id), &m.types);
64 let event_variant_index =
65 VariantIndex::build(p.event.as_ref().map(|e| e.ty.id), &m.types);
66
67 pallets_by_index.insert(p.index, pos);
68 pallets.push_insert(
69 name.clone(),
70 PalletMetadataInner {
71 name,
72 call_index: p.index,
73 event_index: p.index,
74 error_index: p.index,
75 storage,
76 call_ty: p.calls.as_ref().map(|c| c.ty.id),
77 call_variant_index,
78 event_ty: p.event.as_ref().map(|e| e.ty.id),
79 event_variant_index,
80 error_ty: p.error.as_ref().map(|e| e.ty.id),
81 error_variant_index,
82 constants: constants.collect(),
83 view_functions: Default::default(),
84 associated_types: Default::default(),
85 docs: p.docs.clone(),
86 },
87 );
88 }
89
90 let apis = m
91 .apis
92 .iter()
93 .map(|api| {
94 let trait_name = api.name.clone();
95 let methods = api
96 .methods
97 .iter()
98 .map(|method| {
99 let method_name = method.name.clone();
100 let method_info = RuntimeApiMethodMetadataInner {
101 info: m
102 .runtime_api_info(&trait_name, &method.name)
103 .map_err(|e| e.into_owned())?
104 .into_owned(),
105 name: method.name.clone(),
106 docs: method.docs.clone(),
107 };
108 Ok((method_name, method_info))
109 })
110 .collect::<Result<_, TryFromError>>()?;
111
112 let runtime_api_metadata = RuntimeApiMetadataInner {
113 name: trait_name.clone(),
114 methods,
115 docs: api.docs.clone(),
116 };
117 Ok((trait_name, runtime_api_metadata))
118 })
119 .collect::<Result<_, TryFromError>>()?;
120
121 let dispatch_error_ty = m
122 .types
123 .types
124 .iter()
125 .find(|ty| ty.ty.path.segments == ["sp_runtime", "DispatchError"])
126 .map(|ty| ty.id);
127
128 Ok(Metadata {
129 types: m.types,
130 pallets,
131 pallets_by_call_index: pallets_by_index.clone(),
132 pallets_by_error_index: pallets_by_index.clone(),
133 pallets_by_event_index: pallets_by_index,
134 extrinsic: from_extrinsic_metadata(m.extrinsic),
135 dispatch_error_ty,
136 apis,
137 outer_enums: OuterEnumsMetadata {
138 call_enum_ty: m.outer_enums.call_enum_ty.id,
139 event_enum_ty: m.outer_enums.event_enum_ty.id,
140 error_enum_ty: m.outer_enums.error_enum_ty.id,
141 },
142 custom: m.custom,
143 })
144 }
145}
146
147fn from_signed_extension_metadata(
148 value: v15::SignedExtensionMetadata<PortableForm>,
149) -> TransactionExtensionMetadataInner {
150 TransactionExtensionMetadataInner {
151 identifier: value.identifier,
152 extra_ty: value.ty.id,
153 additional_ty: value.additional_signed.id,
154 }
155}
156
157fn from_extrinsic_metadata(value: v15::ExtrinsicMetadata<PortableForm>) -> ExtrinsicMetadata {
158 let transaction_extensions: Vec<_> = value
159 .signed_extensions
160 .into_iter()
161 .map(from_signed_extension_metadata)
162 .collect();
163
164 let transaction_extension_indexes = (0..transaction_extensions.len() as u32).collect();
165
166 ExtrinsicMetadata {
167 supported_versions: vec![value.version],
168 transaction_extensions,
169 address_ty: value.address_ty.id,
170 signature_ty: value.signature_ty.id,
171 transaction_extensions_by_version: BTreeMap::from_iter([(
172 0,
173 transaction_extension_indexes,
174 )]),
175 }
176}
177
178fn from_constant_metadata(s: v15::PalletConstantMetadata<PortableForm>) -> ConstantMetadata {
179 ConstantMetadata {
180 name: s.name,
181 ty: s.ty.id,
182 value: s.value,
183 docs: s.docs,
184 }
185}