frame_metadata/
v15.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// SPDX-License-Identifier: Apache-2.0
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// 	http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#[cfg(feature = "decode")]
17use codec::Decode;
18#[cfg(feature = "serde_full")]
19use serde::Serialize;
20
21use super::{RuntimeMetadataPrefixed, META_RESERVED};
22use codec::Encode;
23use scale_info::{
24	form::{Form, MetaForm, PortableForm},
25	prelude::{collections::BTreeMap, vec::Vec},
26	IntoPortable, MetaType, PortableRegistry, Registry,
27};
28
29pub use super::v14::{
30	PalletCallMetadata, PalletConstantMetadata, PalletErrorMetadata, PalletEventMetadata,
31	PalletStorageMetadata, StorageEntryMetadata, StorageEntryModifier, StorageEntryType,
32	StorageHasher,
33};
34
35/// Latest runtime metadata
36pub type RuntimeMetadataLastVersion = RuntimeMetadataV15;
37
38impl From<RuntimeMetadataLastVersion> for super::RuntimeMetadataPrefixed {
39	fn from(metadata: RuntimeMetadataLastVersion) -> RuntimeMetadataPrefixed {
40		RuntimeMetadataPrefixed(META_RESERVED, super::RuntimeMetadata::V15(metadata))
41	}
42}
43
44/// The metadata of a runtime.
45#[derive(Clone, PartialEq, Eq, Encode, Debug)]
46#[cfg_attr(feature = "decode", derive(Decode))]
47#[cfg_attr(feature = "serde_full", derive(Serialize))]
48pub struct RuntimeMetadataV15 {
49	/// Type registry containing all types used in the metadata.
50	pub types: PortableRegistry,
51	/// Metadata of all the pallets.
52	pub pallets: Vec<PalletMetadata<PortableForm>>,
53	/// Metadata of the extrinsic.
54	pub extrinsic: ExtrinsicMetadata<PortableForm>,
55	/// The type of the `Runtime`.
56	pub ty: <PortableForm as Form>::Type,
57	/// Metadata of the Runtime API.
58	pub apis: Vec<RuntimeApiMetadata<PortableForm>>,
59	/// The outer enums types as found in the runtime.
60	pub outer_enums: OuterEnums<PortableForm>,
61	/// Allows users to add custom types to the metadata.
62	pub custom: CustomMetadata<PortableForm>,
63}
64
65impl RuntimeMetadataV15 {
66	/// Create a new instance of [`RuntimeMetadataV15`].
67	pub fn new(
68		pallets: Vec<PalletMetadata>,
69		extrinsic: ExtrinsicMetadata,
70		runtime_type: MetaType,
71		apis: Vec<RuntimeApiMetadata>,
72		outer_enums: OuterEnums,
73		custom: CustomMetadata,
74	) -> Self {
75		let mut registry = Registry::new();
76		// extrinsic types need to be collected first to ensure CheckMetadataHash hash
77		// is stable across different metadata versions
78		let extrinsic = extrinsic.into_portable(&mut registry);
79		let pallets = registry.map_into_portable(pallets);
80		let ty = registry.register_type(&runtime_type);
81		let apis = registry.map_into_portable(apis);
82		let outer_enums = outer_enums.into_portable(&mut registry);
83		let custom = custom.into_portable(&mut registry);
84
85		Self {
86			types: registry.into(),
87			pallets,
88			extrinsic,
89			ty,
90			apis,
91			outer_enums,
92			custom,
93		}
94	}
95}
96
97/// Metadata of a runtime trait.
98#[derive(Clone, PartialEq, Eq, Encode, Debug)]
99#[cfg_attr(feature = "decode", derive(Decode))]
100#[cfg_attr(feature = "serde_full", derive(Serialize))]
101#[cfg_attr(
102	feature = "serde_full",
103	serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
104)]
105pub struct RuntimeApiMetadata<T: Form = MetaForm> {
106	/// Trait name.
107	pub name: T::String,
108	/// Trait methods.
109	pub methods: Vec<RuntimeApiMethodMetadata<T>>,
110	/// Trait documentation.
111	pub docs: Vec<T::String>,
112}
113
114impl IntoPortable for RuntimeApiMetadata {
115	type Output = RuntimeApiMetadata<PortableForm>;
116
117	fn into_portable(self, registry: &mut Registry) -> Self::Output {
118		RuntimeApiMetadata {
119			name: self.name.into_portable(registry),
120			methods: registry.map_into_portable(self.methods),
121			docs: registry.map_into_portable(self.docs),
122		}
123	}
124}
125
126/// Metadata of a runtime method.
127#[derive(Clone, PartialEq, Eq, Encode, Debug)]
128#[cfg_attr(feature = "decode", derive(Decode))]
129#[cfg_attr(feature = "serde_full", derive(Serialize))]
130#[cfg_attr(
131	feature = "serde_full",
132	serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
133)]
134pub struct RuntimeApiMethodMetadata<T: Form = MetaForm> {
135	/// Method name.
136	pub name: T::String,
137	/// Method parameters.
138	pub inputs: Vec<RuntimeApiMethodParamMetadata<T>>,
139	/// Method output.
140	pub output: T::Type,
141	/// Method documentation.
142	pub docs: Vec<T::String>,
143}
144
145impl IntoPortable for RuntimeApiMethodMetadata {
146	type Output = RuntimeApiMethodMetadata<PortableForm>;
147
148	fn into_portable(self, registry: &mut Registry) -> Self::Output {
149		RuntimeApiMethodMetadata {
150			name: self.name.into_portable(registry),
151			inputs: registry.map_into_portable(self.inputs),
152			output: registry.register_type(&self.output),
153			docs: registry.map_into_portable(self.docs),
154		}
155	}
156}
157
158/// Metadata of a runtime method parameter.
159#[derive(Clone, PartialEq, Eq, Encode, Debug)]
160#[cfg_attr(feature = "decode", derive(Decode))]
161#[cfg_attr(feature = "serde_full", derive(Serialize))]
162#[cfg_attr(
163	feature = "serde_full",
164	serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
165)]
166pub struct RuntimeApiMethodParamMetadata<T: Form = MetaForm> {
167	/// Parameter name.
168	pub name: T::String,
169	/// Parameter type.
170	pub ty: T::Type,
171}
172
173impl IntoPortable for RuntimeApiMethodParamMetadata {
174	type Output = RuntimeApiMethodParamMetadata<PortableForm>;
175
176	fn into_portable(self, registry: &mut Registry) -> Self::Output {
177		RuntimeApiMethodParamMetadata {
178			name: self.name.into_portable(registry),
179			ty: registry.register_type(&self.ty),
180		}
181	}
182}
183
184/// Metadata of the extrinsic used by the runtime.
185#[derive(Clone, PartialEq, Eq, Encode, Debug)]
186#[cfg_attr(feature = "decode", derive(Decode))]
187#[cfg_attr(feature = "serde_full", derive(Serialize))]
188#[cfg_attr(
189	feature = "serde_full",
190	serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
191)]
192pub struct ExtrinsicMetadata<T: Form = MetaForm> {
193	/// Extrinsic version.
194	pub version: u8,
195	/// The type of the address that signes the extrinsic
196	pub address_ty: T::Type,
197	/// The type of the outermost Call enum.
198	pub call_ty: T::Type,
199	/// The type of the extrinsic's signature.
200	pub signature_ty: T::Type,
201	/// The type of the outermost Extra enum.
202	pub extra_ty: T::Type,
203	/// The signed extensions in the order they appear in the extrinsic.
204	pub signed_extensions: Vec<SignedExtensionMetadata<T>>,
205}
206
207impl IntoPortable for ExtrinsicMetadata {
208	type Output = ExtrinsicMetadata<PortableForm>;
209
210	fn into_portable(self, registry: &mut Registry) -> Self::Output {
211		// the collection order needs to be stable across different metadata versions
212		// to ensure CheckMetadataHash hash is invariant
213		ExtrinsicMetadata {
214			version: self.version,
215			address_ty: registry.register_type(&self.address_ty),
216			call_ty: registry.register_type(&self.call_ty),
217			signature_ty: registry.register_type(&self.signature_ty),
218			signed_extensions: registry.map_into_portable(self.signed_extensions),
219			extra_ty: registry.register_type(&self.extra_ty),
220		}
221	}
222}
223
224/// Metadata of an extrinsic's signed extension.
225#[derive(Clone, PartialEq, Eq, Encode, Debug)]
226#[cfg_attr(feature = "decode", derive(Decode))]
227#[cfg_attr(feature = "serde_full", derive(Serialize))]
228#[cfg_attr(
229	feature = "serde_full",
230	serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
231)]
232pub struct SignedExtensionMetadata<T: Form = MetaForm> {
233	/// The unique signed extension identifier, which may be different from the type name.
234	pub identifier: T::String,
235	/// The type of the signed extension, with the data to be included in the extrinsic.
236	pub ty: T::Type,
237	/// The type of the additional signed data, with the data to be included in the signed payload
238	pub additional_signed: T::Type,
239}
240
241impl IntoPortable for SignedExtensionMetadata {
242	type Output = SignedExtensionMetadata<PortableForm>;
243
244	fn into_portable(self, registry: &mut Registry) -> Self::Output {
245		SignedExtensionMetadata {
246			identifier: self.identifier.into_portable(registry),
247			ty: registry.register_type(&self.ty),
248			additional_signed: registry.register_type(&self.additional_signed),
249		}
250	}
251}
252
253/// All metadata about an runtime pallet.
254#[derive(Clone, PartialEq, Eq, Encode, Debug)]
255#[cfg_attr(feature = "decode", derive(Decode))]
256#[cfg_attr(feature = "serde_full", derive(Serialize))]
257#[cfg_attr(
258	feature = "serde_full",
259	serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
260)]
261pub struct PalletMetadata<T: Form = MetaForm> {
262	/// Pallet name.
263	pub name: T::String,
264	/// Pallet storage metadata.
265	pub storage: Option<PalletStorageMetadata<T>>,
266	/// Pallet calls metadata.
267	pub calls: Option<PalletCallMetadata<T>>,
268	/// Pallet event metadata.
269	pub event: Option<PalletEventMetadata<T>>,
270	/// Pallet constants metadata.
271	pub constants: Vec<PalletConstantMetadata<T>>,
272	/// Pallet error metadata.
273	pub error: Option<PalletErrorMetadata<T>>,
274	/// Define the index of the pallet, this index will be used for the encoding of pallet event,
275	/// call and origin variants.
276	pub index: u8,
277	/// Pallet documentation.
278	pub docs: Vec<T::String>,
279}
280
281impl IntoPortable for PalletMetadata {
282	type Output = PalletMetadata<PortableForm>;
283
284	fn into_portable(self, registry: &mut Registry) -> Self::Output {
285		PalletMetadata {
286			name: self.name.into_portable(registry),
287			storage: self.storage.map(|storage| storage.into_portable(registry)),
288			calls: self.calls.map(|calls| calls.into_portable(registry)),
289			event: self.event.map(|event| event.into_portable(registry)),
290			constants: registry.map_into_portable(self.constants),
291			error: self.error.map(|error| error.into_portable(registry)),
292			index: self.index,
293			docs: registry.map_into_portable(self.docs),
294		}
295	}
296}
297
298/// Metadata for custom types.
299///
300/// This map associates a string key to a `CustomValueMetadata`.
301#[derive(Clone, PartialEq, Eq, Encode, Debug)]
302#[cfg_attr(feature = "decode", derive(Decode))]
303#[cfg_attr(feature = "serde_full", derive(Serialize))]
304#[cfg_attr(
305	feature = "serde_full",
306	serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
307)]
308pub struct CustomMetadata<T: Form = MetaForm> {
309	/// The custom map.
310	pub map: BTreeMap<T::String, CustomValueMetadata<T>>,
311}
312
313impl IntoPortable for CustomMetadata {
314	type Output = CustomMetadata<PortableForm>;
315
316	fn into_portable(self, registry: &mut Registry) -> Self::Output {
317		let map = self
318			.map
319			.into_iter()
320			.map(|(key, value)| (key.into_portable(registry), value.into_portable(registry)))
321			.collect();
322
323		CustomMetadata { map }
324	}
325}
326
327/// The associated value of a custom metadata type.
328#[derive(Clone, PartialEq, Eq, Encode, Debug)]
329#[cfg_attr(feature = "decode", derive(Decode))]
330#[cfg_attr(feature = "serde_full", derive(Serialize))]
331#[cfg_attr(
332	feature = "serde_full",
333	serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
334)]
335pub struct CustomValueMetadata<T: Form = MetaForm> {
336	/// The custom type.
337	pub ty: T::Type,
338	/// The custom value of this type.
339	pub value: Vec<u8>,
340}
341
342impl IntoPortable for CustomValueMetadata {
343	type Output = CustomValueMetadata<PortableForm>;
344
345	fn into_portable(self, registry: &mut Registry) -> Self::Output {
346		CustomValueMetadata {
347			ty: registry.register_type(&self.ty),
348			value: self.value,
349		}
350	}
351}
352
353/// The type of the outer enums.
354#[derive(Clone, PartialEq, Eq, Encode, Debug)]
355#[cfg_attr(feature = "decode", derive(Decode))]
356#[cfg_attr(feature = "serde_full", derive(Serialize))]
357#[cfg_attr(
358	feature = "serde_full",
359	serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
360)]
361pub struct OuterEnums<T: Form = MetaForm> {
362	/// The type of the outer `RuntimeCall` enum.
363	pub call_enum_ty: T::Type,
364	/// The type of the outer `RuntimeEvent` enum.
365	pub event_enum_ty: T::Type,
366	/// The module error type of the
367	/// [`DispatchError::Module`](https://docs.rs/sp-runtime/24.0.0/sp_runtime/enum.DispatchError.html#variant.Module) variant.
368	///
369	/// The `Module` variant will be 5 scale encoded bytes which are normally decoded into
370	/// an `{ index: u8, error: [u8; 4] }` struct. This type ID points to an enum type which instead
371	/// interprets the first `index` byte as a pallet variant, and the remaining `error` bytes as the
372	/// appropriate `pallet::Error` type. It is an equally valid way to decode the error bytes, and
373	/// can be more informative.
374	///
375	/// # Note
376	///
377	/// - This type cannot be used directly to decode `sp_runtime::DispatchError` from the
378	///   chain. It provides just the information needed to decode `sp_runtime::DispatchError::Module`.
379	/// - Decoding the 5 error bytes into this type will not always lead to all of the bytes being consumed;
380	///   many error types do not require all of the bytes to represent them fully.
381	pub error_enum_ty: T::Type,
382}
383
384impl IntoPortable for OuterEnums {
385	type Output = OuterEnums<PortableForm>;
386
387	fn into_portable(self, registry: &mut Registry) -> Self::Output {
388		OuterEnums {
389			call_enum_ty: registry.register_type(&self.call_enum_ty),
390			event_enum_ty: registry.register_type(&self.event_enum_ty),
391			error_enum_ty: registry.register_type(&self.error_enum_ty),
392		}
393	}
394}