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