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