1#![cfg_attr(not(feature = "std"), no_std)]
18#![deny(missing_docs)]
19
20extern crate alloc;
21
22mod from;
23mod utils;
24
25use alloc::{
26 borrow::Cow,
27 collections::BTreeMap,
28 string::{String, ToString},
29 vec::Vec,
30};
31use frame_decode::{
32 constants::{ConstantEntry, ConstantInfo, ConstantInfoError},
33 custom_values::{CustomValue, CustomValueInfo, CustomValueInfoError},
34 extrinsics::{
35 ExtrinsicCallInfo, ExtrinsicExtensionInfo, ExtrinsicInfoArg, ExtrinsicInfoError,
36 ExtrinsicSignatureInfo,
37 },
38 runtime_apis::{RuntimeApiEntry, RuntimeApiInfo, RuntimeApiInfoError, RuntimeApiInput},
39 storage::{StorageEntry, StorageInfo, StorageInfoError, StorageKeyInfo},
40 view_functions::{
41 ViewFunctionEntry, ViewFunctionInfo, ViewFunctionInfoError, ViewFunctionInput,
42 },
43};
44
45use hashbrown::HashMap;
46use scale_info::{form::PortableForm, PortableRegistry, Variant};
47use utils::{
48 ordered_map::OrderedMap,
49 validation::{get_custom_value_hash, HASH_LEN},
50 variant_index::VariantIndex,
51};
52
53pub use frame_decode::storage::StorageHasher;
54pub use from::{TryFromError, SUPPORTED_METADATA_VERSIONS};
55pub use utils::validation::MetadataHasher;
56
57#[cfg(feature = "legacy")]
58pub use from::legacy::Error as LegacyFromError;
59
60type CustomMetadataInner = frame_metadata::v15::CustomMetadata<PortableForm>;
61
62#[derive(Debug, Clone)]
66pub struct Metadata {
67 types: PortableRegistry,
69 pallets: OrderedMap<String, PalletMetadataInner>,
71 pallets_by_call_index: HashMap<u8, usize>,
73 pallets_by_event_index: HashMap<u8, usize>,
78 pallets_by_error_index: HashMap<u8, usize>,
83 extrinsic: ExtrinsicMetadata,
85 outer_enums: OuterEnumsMetadata,
87 dispatch_error_ty: Option<u32>,
89 apis: OrderedMap<String, RuntimeApiMetadataInner>,
91 custom: CustomMetadataInner,
94}
95
96impl frame_decode::extrinsics::ExtrinsicTypeInfo for Metadata {
99 type TypeId = u32;
100
101 fn extrinsic_call_info(
102 &self,
103 pallet_index: u8,
104 call_index: u8,
105 ) -> Result<ExtrinsicCallInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
106 let pallet = self
107 .pallet_by_call_index(pallet_index)
108 .ok_or(ExtrinsicInfoError::PalletNotFound { index: pallet_index })?;
109
110 let call = pallet.call_variant_by_index(call_index).ok_or_else(|| {
111 ExtrinsicInfoError::CallNotFound {
112 index: call_index,
113 pallet_index,
114 pallet_name: Cow::Borrowed(pallet.name()),
115 }
116 })?;
117
118 Ok(ExtrinsicCallInfo {
119 pallet_name: Cow::Borrowed(pallet.name()),
120 call_name: Cow::Borrowed(&call.name),
121 args: call
122 .fields
123 .iter()
124 .map(|f| ExtrinsicInfoArg {
125 name: Cow::Borrowed(f.name.as_deref().unwrap_or("")),
126 id: f.ty.id,
127 })
128 .collect(),
129 })
130 }
131
132 fn extrinsic_signature_info(
133 &self,
134 ) -> Result<ExtrinsicSignatureInfo<Self::TypeId>, ExtrinsicInfoError<'_>> {
135 Ok(ExtrinsicSignatureInfo {
136 address_id: self.extrinsic().address_ty,
137 signature_id: self.extrinsic().signature_ty,
138 })
139 }
140
141 fn extrinsic_extension_info(
142 &self,
143 extension_version: Option<u8>,
144 ) -> Result<ExtrinsicExtensionInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
145 let extension_version = extension_version.unwrap_or_else(|| {
146 self.extrinsic().transaction_extension_version_to_use_for_decoding()
150 });
151
152 let extension_ids = self
153 .extrinsic()
154 .transaction_extensions_by_version(extension_version)
155 .ok_or(ExtrinsicInfoError::ExtrinsicExtensionVersionNotFound { extension_version })?
156 .map(|f| ExtrinsicInfoArg { name: Cow::Borrowed(f.identifier()), id: f.extra_ty() })
157 .collect();
158
159 Ok(ExtrinsicExtensionInfo { extension_ids })
160 }
161}
162impl frame_decode::storage::StorageTypeInfo for Metadata {
163 type TypeId = u32;
164
165 fn storage_info(
166 &self,
167 pallet_name: &str,
168 storage_entry: &str,
169 ) -> Result<StorageInfo<'_, Self::TypeId>, StorageInfoError<'_>> {
170 let pallet =
171 self.pallet_by_name(pallet_name)
172 .ok_or_else(|| StorageInfoError::PalletNotFound {
173 pallet_name: pallet_name.to_string(),
174 })?;
175 let entry = pallet
176 .storage()
177 .and_then(|storage| storage.entry_by_name(storage_entry))
178 .ok_or_else(|| StorageInfoError::StorageNotFound {
179 name: storage_entry.to_string(),
180 pallet_name: Cow::Borrowed(pallet.name()),
181 })?;
182
183 let info = StorageInfo {
184 keys: Cow::Borrowed(&*entry.info.keys),
185 value_id: entry.info.value_id,
186 default_value: entry.info.default_value.as_ref().map(|def| Cow::Borrowed(&**def)),
187 };
188
189 Ok(info)
190 }
191}
192impl frame_decode::storage::StorageEntryInfo for Metadata {
193 fn storage_entries(&self) -> impl Iterator<Item = StorageEntry<'_>> {
194 self.pallets().flat_map(|pallet| {
195 let pallet_name = pallet.name();
196 let pallet_iter = core::iter::once(StorageEntry::In(pallet_name.into()));
197 let entries_iter = pallet.storage().into_iter().flat_map(|storage| {
198 storage.entries().iter().map(|entry| StorageEntry::Name(entry.name().into()))
199 });
200
201 pallet_iter.chain(entries_iter)
202 })
203 }
204}
205impl frame_decode::runtime_apis::RuntimeApiTypeInfo for Metadata {
206 type TypeId = u32;
207
208 fn runtime_api_info(
209 &self,
210 trait_name: &str,
211 method_name: &str,
212 ) -> Result<RuntimeApiInfo<'_, Self::TypeId>, RuntimeApiInfoError<'_>> {
213 let api_trait =
214 self.apis
215 .get_by_key(trait_name)
216 .ok_or_else(|| RuntimeApiInfoError::TraitNotFound {
217 trait_name: trait_name.to_string(),
218 })?;
219 let api_method = api_trait.methods.get_by_key(method_name).ok_or_else(|| {
220 RuntimeApiInfoError::MethodNotFound {
221 trait_name: Cow::Borrowed(&api_trait.name),
222 method_name: method_name.to_string(),
223 }
224 })?;
225
226 let info = RuntimeApiInfo {
227 inputs: Cow::Borrowed(&api_method.info.inputs),
228 output_id: api_method.info.output_id,
229 };
230
231 Ok(info)
232 }
233}
234impl frame_decode::runtime_apis::RuntimeApiEntryInfo for Metadata {
235 fn runtime_api_entries(&self) -> impl Iterator<Item = RuntimeApiEntry<'_>> {
236 self.runtime_api_traits().flat_map(|api_trait| {
237 let trait_name = api_trait.name();
238 let trait_iter = core::iter::once(RuntimeApiEntry::In(trait_name.into()));
239 let method_iter =
240 api_trait.methods().map(|method| RuntimeApiEntry::Name(method.name().into()));
241
242 trait_iter.chain(method_iter)
243 })
244 }
245}
246impl frame_decode::view_functions::ViewFunctionTypeInfo for Metadata {
247 type TypeId = u32;
248
249 fn view_function_info(
250 &self,
251 pallet_name: &str,
252 function_name: &str,
253 ) -> Result<ViewFunctionInfo<'_, Self::TypeId>, ViewFunctionInfoError<'_>> {
254 let pallet = self.pallet_by_name(pallet_name).ok_or_else(|| {
255 ViewFunctionInfoError::PalletNotFound { pallet_name: pallet_name.to_string() }
256 })?;
257 let function = pallet.view_function_by_name(function_name).ok_or_else(|| {
258 ViewFunctionInfoError::FunctionNotFound {
259 pallet_name: Cow::Borrowed(pallet.name()),
260 function_name: function_name.to_string(),
261 }
262 })?;
263
264 let info = ViewFunctionInfo {
265 inputs: Cow::Borrowed(&function.inner.info.inputs),
266 output_id: function.inner.info.output_id,
267 query_id: *function.query_id(),
268 };
269
270 Ok(info)
271 }
272}
273impl frame_decode::view_functions::ViewFunctionEntryInfo for Metadata {
274 fn view_function_entries(&self) -> impl Iterator<Item = ViewFunctionEntry<'_>> {
275 self.pallets().flat_map(|pallet| {
276 let pallet_name = pallet.name();
277 let pallet_iter = core::iter::once(ViewFunctionEntry::In(pallet_name.into()));
278 let fn_iter = pallet
279 .view_functions()
280 .map(|function| ViewFunctionEntry::Name(function.name().into()));
281
282 pallet_iter.chain(fn_iter)
283 })
284 }
285}
286impl frame_decode::constants::ConstantTypeInfo for Metadata {
287 type TypeId = u32;
288
289 fn constant_info(
290 &self,
291 pallet_name: &str,
292 constant_name: &str,
293 ) -> Result<ConstantInfo<'_, Self::TypeId>, ConstantInfoError<'_>> {
294 let pallet =
295 self.pallet_by_name(pallet_name)
296 .ok_or_else(|| ConstantInfoError::PalletNotFound {
297 pallet_name: pallet_name.to_string(),
298 })?;
299 let constant = pallet.constant_by_name(constant_name).ok_or_else(|| {
300 ConstantInfoError::ConstantNotFound {
301 pallet_name: Cow::Borrowed(pallet.name()),
302 constant_name: constant_name.to_string(),
303 }
304 })?;
305
306 let info = ConstantInfo { bytes: &constant.value, type_id: constant.ty };
307
308 Ok(info)
309 }
310}
311impl frame_decode::constants::ConstantEntryInfo for Metadata {
312 fn constant_entries(&self) -> impl Iterator<Item = ConstantEntry<'_>> {
313 self.pallets().flat_map(|pallet| {
314 let pallet_name = pallet.name();
315 let pallet_iter = core::iter::once(ConstantEntry::In(pallet_name.into()));
316 let constant_iter =
317 pallet.constants().map(|constant| ConstantEntry::Name(constant.name().into()));
318
319 pallet_iter.chain(constant_iter)
320 })
321 }
322}
323impl frame_decode::custom_values::CustomValueTypeInfo for Metadata {
324 type TypeId = u32;
325
326 fn custom_value_info(
327 &self,
328 name: &str,
329 ) -> Result<CustomValueInfo<'_, Self::TypeId>, CustomValueInfoError> {
330 let custom_value = self
331 .custom()
332 .get(name)
333 .ok_or_else(|| CustomValueInfoError { not_found: name.to_string() })?;
334
335 let info = CustomValueInfo { bytes: custom_value.data, type_id: custom_value.type_id };
336
337 Ok(info)
338 }
339}
340impl frame_decode::custom_values::CustomValueEntryInfo for Metadata {
341 fn custom_values(&self) -> impl Iterator<Item = CustomValue<'_>> {
342 self.custom.map.keys().map(|name| CustomValue { name: Cow::Borrowed(name) })
343 }
344}
345
346impl Metadata {
347 pub fn decode_from(mut bytes: &[u8]) -> Result<Self, codec::Error> {
349 <Self as codec::Decode>::decode(&mut bytes)
350 }
351
352 pub fn from_v16(
354 metadata: frame_metadata::v16::RuntimeMetadataV16,
355 ) -> Result<Self, TryFromError> {
356 metadata.try_into()
357 }
358
359 pub fn from_v15(
361 metadata: frame_metadata::v15::RuntimeMetadataV15,
362 ) -> Result<Self, TryFromError> {
363 metadata.try_into()
364 }
365
366 pub fn from_v14(
368 metadata: frame_metadata::v14::RuntimeMetadataV14,
369 ) -> Result<Self, TryFromError> {
370 metadata.try_into()
371 }
372
373 #[cfg(feature = "legacy")]
375 pub fn from_v13(
376 metadata: &frame_metadata::v13::RuntimeMetadataV13,
377 types: &scale_info_legacy::TypeRegistrySet<'_>,
378 ) -> Result<Self, LegacyFromError> {
379 from::legacy::from_v13(metadata, types, from::legacy::Opts::compat())
380 }
381
382 #[cfg(feature = "legacy")]
384 pub fn from_v12(
385 metadata: &frame_metadata::v12::RuntimeMetadataV12,
386 types: &scale_info_legacy::TypeRegistrySet<'_>,
387 ) -> Result<Self, LegacyFromError> {
388 from::legacy::from_v12(metadata, types, from::legacy::Opts::compat())
389 }
390
391 #[cfg(feature = "legacy")]
393 pub fn from_v11(
394 metadata: &frame_metadata::v11::RuntimeMetadataV11,
395 types: &scale_info_legacy::TypeRegistrySet<'_>,
396 ) -> Result<Self, LegacyFromError> {
397 from::legacy::from_v11(metadata, types, from::legacy::Opts::compat())
398 }
399
400 #[cfg(feature = "legacy")]
402 pub fn from_v10(
403 metadata: &frame_metadata::v10::RuntimeMetadataV10,
404 types: &scale_info_legacy::TypeRegistrySet<'_>,
405 ) -> Result<Self, LegacyFromError> {
406 from::legacy::from_v10(metadata, types, from::legacy::Opts::compat())
407 }
408
409 #[cfg(feature = "legacy")]
411 pub fn from_v9(
412 metadata: &frame_metadata::v9::RuntimeMetadataV9,
413 types: &scale_info_legacy::TypeRegistrySet<'_>,
414 ) -> Result<Self, LegacyFromError> {
415 from::legacy::from_v9(metadata, types, from::legacy::Opts::compat())
416 }
417
418 #[cfg(feature = "legacy")]
420 pub fn from_v8(
421 metadata: &frame_metadata::v8::RuntimeMetadataV8,
422 types: &scale_info_legacy::TypeRegistrySet<'_>,
423 ) -> Result<Self, LegacyFromError> {
424 from::legacy::from_v8(metadata, types, from::legacy::Opts::compat())
425 }
426
427 pub fn types(&self) -> &PortableRegistry {
429 &self.types
430 }
431
432 pub fn types_mut(&mut self) -> &mut PortableRegistry {
434 &mut self.types
435 }
436
437 pub fn dispatch_error_ty(&self) -> Option<u32> {
439 self.dispatch_error_ty
440 }
441
442 pub fn extrinsic(&self) -> &ExtrinsicMetadata {
444 &self.extrinsic
445 }
446
447 pub fn outer_enums(&self) -> OuterEnumsMetadata {
449 self.outer_enums
450 }
451
452 pub fn pallets(&self) -> impl ExactSizeIterator<Item = PalletMetadata<'_>> {
454 self.pallets
455 .values()
456 .iter()
457 .map(|inner| PalletMetadata { inner, types: self.types() })
458 }
459
460 pub fn pallet_by_call_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
462 let inner = self
463 .pallets_by_call_index
464 .get(&variant_index)
465 .and_then(|i| self.pallets.get_by_index(*i))?;
466
467 Some(PalletMetadata { inner, types: self.types() })
468 }
469
470 pub fn pallet_by_event_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
472 let inner = self
473 .pallets_by_event_index
474 .get(&variant_index)
475 .and_then(|i| self.pallets.get_by_index(*i))?;
476
477 Some(PalletMetadata { inner, types: self.types() })
478 }
479
480 pub fn pallet_by_error_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
482 let inner = self
483 .pallets_by_error_index
484 .get(&variant_index)
485 .and_then(|i| self.pallets.get_by_index(*i))?;
486
487 Some(PalletMetadata { inner, types: self.types() })
488 }
489
490 pub fn pallet_by_name(&self, pallet_name: &str) -> Option<PalletMetadata<'_>> {
492 let inner = self.pallets.get_by_key(pallet_name)?;
493
494 Some(PalletMetadata { inner, types: self.types() })
495 }
496
497 pub fn runtime_api_traits(&self) -> impl ExactSizeIterator<Item = RuntimeApiMetadata<'_>> {
499 self.apis
500 .values()
501 .iter()
502 .map(|inner| RuntimeApiMetadata { inner, types: self.types() })
503 }
504
505 pub fn runtime_api_trait_by_name(&'_ self, name: &str) -> Option<RuntimeApiMetadata<'_>> {
507 let inner = self.apis.get_by_key(name)?;
508 Some(RuntimeApiMetadata { inner, types: self.types() })
509 }
510
511 pub fn custom(&self) -> CustomMetadata<'_> {
513 CustomMetadata { types: self.types(), inner: &self.custom }
514 }
515
516 pub fn hasher(&self) -> MetadataHasher<'_> {
518 MetadataHasher::new(self)
519 }
520
521 pub fn type_hash(&self, id: u32) -> Option<[u8; HASH_LEN]> {
523 self.types.resolve(id)?;
524 Some(crate::utils::validation::get_type_hash(&self.types, id))
525 }
526}
527
528#[derive(Debug, Clone, Copy)]
530pub struct PalletMetadata<'a> {
531 inner: &'a PalletMetadataInner,
532 types: &'a PortableRegistry,
533}
534
535impl<'a> PalletMetadata<'a> {
536 pub fn name(&self) -> &'a str {
538 &self.inner.name
539 }
540
541 pub fn call_index(&self) -> u8 {
543 self.inner.call_index
544 }
545
546 pub fn event_index(&self) -> u8 {
548 self.inner.event_index
549 }
550
551 pub fn error_index(&self) -> u8 {
553 self.inner.error_index
554 }
555
556 pub fn docs(&self) -> &'a [String] {
558 &self.inner.docs
559 }
560
561 pub fn call_ty_id(&self) -> Option<u32> {
563 self.inner.call_ty
564 }
565
566 pub fn event_ty_id(&self) -> Option<u32> {
568 self.inner.event_ty
569 }
570
571 pub fn error_ty_id(&self) -> Option<u32> {
573 self.inner.error_ty
574 }
575
576 pub fn storage(&self) -> Option<&'a StorageMetadata> {
578 self.inner.storage.as_ref()
579 }
580
581 pub fn event_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
583 VariantIndex::get(self.inner.event_ty, self.types)
584 }
585
586 pub fn event_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
588 self.inner.event_variant_index.lookup_by_index(
589 variant_index,
590 self.inner.event_ty,
591 self.types,
592 )
593 }
594
595 pub fn has_view_functions(&self) -> bool {
597 !self.inner.view_functions.is_empty()
598 }
599
600 pub fn view_functions(
602 &self,
603 ) -> impl ExactSizeIterator<Item = ViewFunctionMetadata<'a>> + use<'a> {
604 self.inner
605 .view_functions
606 .values()
607 .iter()
608 .map(|vf: &'a _| ViewFunctionMetadata { inner: vf, types: self.types })
609 }
610
611 pub fn view_function_by_name(&self, name: &str) -> Option<ViewFunctionMetadata<'a>> {
613 self.inner
614 .view_functions
615 .get_by_key(name)
616 .map(|vf: &'a _| ViewFunctionMetadata { inner: vf, types: self.types })
617 }
618
619 pub fn associated_types(&self) -> impl ExactSizeIterator<Item = (&'a str, u32)> + use<'a> {
622 self.inner.associated_types.iter().map(|(name, ty)| (&**name, *ty))
623 }
624
625 pub fn associated_type_id(&self, name: &str) -> Option<u32> {
627 self.inner.associated_types.get(name).copied()
628 }
629
630 pub fn call_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
632 VariantIndex::get(self.inner.call_ty, self.types)
633 }
634
635 pub fn call_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
637 self.inner
638 .call_variant_index
639 .lookup_by_index(variant_index, self.inner.call_ty, self.types)
640 }
641
642 pub fn call_variant_by_name(&self, call_name: &str) -> Option<&'a Variant<PortableForm>> {
644 self.inner
645 .call_variant_index
646 .lookup_by_name(call_name, self.inner.call_ty, self.types)
647 }
648
649 pub fn error_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
651 VariantIndex::get(self.inner.error_ty, self.types)
652 }
653
654 pub fn error_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
656 self.inner.error_variant_index.lookup_by_index(
657 variant_index,
658 self.inner.error_ty,
659 self.types,
660 )
661 }
662
663 pub fn constant_by_name(&self, name: &str) -> Option<&'a ConstantMetadata> {
665 self.inner.constants.get_by_key(name)
666 }
667
668 pub fn constants(&self) -> impl ExactSizeIterator<Item = &'a ConstantMetadata> + use<'a> {
670 self.inner.constants.values().iter()
671 }
672
673 pub fn storage_hash(&self, entry_name: &str) -> Option<[u8; HASH_LEN]> {
675 crate::utils::validation::get_storage_hash(self, entry_name)
676 }
677
678 pub fn constant_hash(&self, constant_name: &str) -> Option<[u8; HASH_LEN]> {
680 crate::utils::validation::get_constant_hash(self, constant_name)
681 }
682
683 pub fn call_hash(&self, call_name: &str) -> Option<[u8; HASH_LEN]> {
685 crate::utils::validation::get_call_hash(self, call_name)
686 }
687
688 pub fn hash(&self) -> [u8; HASH_LEN] {
690 crate::utils::validation::get_pallet_hash(*self)
691 }
692}
693
694#[derive(Debug, Clone)]
695struct PalletMetadataInner {
696 name: String,
698 call_index: u8,
700 event_index: u8,
705 error_index: u8,
710 storage: Option<StorageMetadata>,
712 call_ty: Option<u32>,
714 call_variant_index: VariantIndex,
716 event_ty: Option<u32>,
718 event_variant_index: VariantIndex,
720 error_ty: Option<u32>,
722 error_variant_index: VariantIndex,
724 constants: OrderedMap<String, ConstantMetadata>,
726 view_functions: OrderedMap<String, ViewFunctionMetadataInner>,
728 associated_types: BTreeMap<String, u32>,
730 docs: Vec<String>,
732}
733
734#[derive(Debug, Clone)]
736pub struct StorageMetadata {
737 prefix: String,
739 entries: OrderedMap<String, StorageEntryMetadata>,
741}
742
743impl StorageMetadata {
744 pub fn prefix(&self) -> &str {
746 &self.prefix
747 }
748
749 pub fn entries(&self) -> &[StorageEntryMetadata] {
751 self.entries.values()
752 }
753
754 pub fn entry_by_name(&self, name: &str) -> Option<&StorageEntryMetadata> {
756 self.entries.get_by_key(name)
757 }
758}
759
760#[derive(Debug, Clone)]
762pub struct StorageEntryMetadata {
763 name: String,
765 info: StorageInfo<'static, u32>,
767 docs: Vec<String>,
769}
770
771impl StorageEntryMetadata {
772 pub fn name(&self) -> &str {
774 &self.name
775 }
776 pub fn keys(&self) -> impl ExactSizeIterator<Item = &StorageKeyInfo<u32>> {
778 let keys = &*self.info.keys;
779 keys.iter()
780 }
781 pub fn value_ty(&self) -> u32 {
783 self.info.value_id
784 }
785 pub fn default_value(&self) -> Option<&[u8]> {
787 self.info.default_value.as_deref()
788 }
789 pub fn docs(&self) -> &[String] {
791 &self.docs
792 }
793}
794
795#[derive(Debug, Clone)]
797pub struct ConstantMetadata {
798 name: String,
800 ty: u32,
802 value: Vec<u8>,
804 docs: Vec<String>,
806}
807
808impl ConstantMetadata {
809 pub fn name(&self) -> &str {
811 &self.name
812 }
813 pub fn ty(&self) -> u32 {
815 self.ty
816 }
817 pub fn value(&self) -> &[u8] {
819 &self.value
820 }
821 pub fn docs(&self) -> &[String] {
823 &self.docs
824 }
825}
826
827#[derive(Debug, Clone)]
829pub struct ExtrinsicMetadata {
830 address_ty: u32,
833 signature_ty: u32,
836 supported_versions: Vec<u8>,
838 transaction_extensions: Vec<TransactionExtensionMetadataInner>,
840 transaction_extensions_by_version: BTreeMap<u8, Vec<u32>>,
844}
845
846impl ExtrinsicMetadata {
847 pub fn supported_versions(&self) -> &[u8] {
849 &self.supported_versions
850 }
851
852 pub fn transaction_extensions_by_version(
854 &self,
855 version: u8,
856 ) -> Option<impl Iterator<Item = TransactionExtensionMetadata<'_>>> {
857 let extension_indexes = self.transaction_extensions_by_version.get(&version)?;
858 let iter = extension_indexes.iter().map(|index| {
859 let tx_metadata = self.transaction_extensions.get(*index as usize).expect(
860 "transaction extension should exist if index is in transaction_extensions_by_version",
861 );
862
863 TransactionExtensionMetadata {
864 identifier: &tx_metadata.identifier,
865 extra_ty: tx_metadata.extra_ty,
866 additional_ty: tx_metadata.additional_ty,
867 }
868 });
869
870 Some(iter)
871 }
872
873 pub fn transaction_extension_version_to_use_for_encoding(&self) -> u8 {
875 *self
876 .transaction_extensions_by_version
877 .keys()
878 .max()
879 .expect("At least one version of transaction extensions is expected")
880 }
881
882 pub fn transaction_extensions_to_use_for_encoding(
886 &self,
887 ) -> impl Iterator<Item = TransactionExtensionMetadata<'_>> {
888 let encoding_version = self.transaction_extension_version_to_use_for_encoding();
889 self.transaction_extensions_by_version(encoding_version).unwrap()
890 }
891
892 pub fn transaction_extension_version_to_use_for_decoding(&self) -> u8 {
894 *self
895 .transaction_extensions_by_version
896 .keys()
897 .max()
898 .expect("At least one version of transaction extensions is expected")
899 }
900}
901
902#[derive(Debug, Clone)]
904pub struct TransactionExtensionMetadata<'a> {
905 identifier: &'a str,
907 extra_ty: u32,
909 additional_ty: u32,
911}
912
913#[derive(Debug, Clone)]
914struct TransactionExtensionMetadataInner {
915 identifier: String,
916 extra_ty: u32,
917 additional_ty: u32,
918}
919
920impl<'a> TransactionExtensionMetadata<'a> {
921 pub fn identifier(&self) -> &'a str {
923 self.identifier
924 }
925 pub fn extra_ty(&self) -> u32 {
927 self.extra_ty
928 }
929 pub fn additional_ty(&self) -> u32 {
931 self.additional_ty
932 }
933}
934
935#[derive(Debug, Clone, Copy)]
937pub struct OuterEnumsMetadata {
938 call_enum_ty: u32,
940 event_enum_ty: u32,
942 error_enum_ty: u32,
944}
945
946impl OuterEnumsMetadata {
947 pub fn call_enum_ty(&self) -> u32 {
949 self.call_enum_ty
950 }
951
952 pub fn event_enum_ty(&self) -> u32 {
954 self.event_enum_ty
955 }
956
957 pub fn error_enum_ty(&self) -> u32 {
959 self.error_enum_ty
960 }
961}
962
963#[derive(Debug, Clone, Copy)]
965pub struct RuntimeApiMetadata<'a> {
966 inner: &'a RuntimeApiMetadataInner,
967 types: &'a PortableRegistry,
968}
969
970impl<'a> RuntimeApiMetadata<'a> {
971 pub fn name(&self) -> &'a str {
973 &self.inner.name
974 }
975 pub fn docs(&self) -> &[String] {
977 &self.inner.docs
978 }
979 pub fn methods(&self) -> impl ExactSizeIterator<Item = RuntimeApiMethodMetadata<'a>> + use<'a> {
981 self.inner.methods.values().iter().map(|item| RuntimeApiMethodMetadata {
982 trait_name: &self.inner.name,
983 inner: item,
984 types: self.types,
985 })
986 }
987 pub fn method_by_name(&self, name: &str) -> Option<RuntimeApiMethodMetadata<'a>> {
989 self.inner.methods.get_by_key(name).map(|item| RuntimeApiMethodMetadata {
990 trait_name: &self.inner.name,
991 inner: item,
992 types: self.types,
993 })
994 }
995 pub fn hash(&self) -> [u8; HASH_LEN] {
997 crate::utils::validation::get_runtime_apis_hash(*self)
998 }
999}
1000
1001#[derive(Debug, Clone)]
1002struct RuntimeApiMetadataInner {
1003 name: String,
1005 methods: OrderedMap<String, RuntimeApiMethodMetadataInner>,
1007 docs: Vec<String>,
1009}
1010
1011#[derive(Debug, Clone)]
1013pub struct RuntimeApiMethodMetadata<'a> {
1014 trait_name: &'a str,
1015 inner: &'a RuntimeApiMethodMetadataInner,
1016 types: &'a PortableRegistry,
1017}
1018
1019impl<'a> RuntimeApiMethodMetadata<'a> {
1020 pub fn name(&self) -> &'a str {
1022 &self.inner.name
1023 }
1024 pub fn docs(&self) -> &[String] {
1026 &self.inner.docs
1027 }
1028 pub fn inputs(
1030 &self,
1031 ) -> impl ExactSizeIterator<Item = &'a RuntimeApiInput<'static, u32>> + use<'a> {
1032 let inputs = &*self.inner.info.inputs;
1033 inputs.iter()
1034 }
1035 pub fn output_ty(&self) -> u32 {
1037 self.inner.info.output_id
1038 }
1039 pub fn hash(&self) -> [u8; HASH_LEN] {
1041 crate::utils::validation::get_runtime_api_hash(self)
1042 }
1043}
1044
1045#[derive(Debug, Clone)]
1046struct RuntimeApiMethodMetadataInner {
1047 name: String,
1049 info: RuntimeApiInfo<'static, u32>,
1051 docs: Vec<String>,
1053}
1054
1055#[derive(Debug, Clone, Copy)]
1058pub struct ViewFunctionMetadata<'a> {
1059 inner: &'a ViewFunctionMetadataInner,
1060 types: &'a PortableRegistry,
1061}
1062
1063impl<'a> ViewFunctionMetadata<'a> {
1064 pub fn name(&self) -> &'a str {
1066 &self.inner.name
1067 }
1068 pub fn query_id(&self) -> &'a [u8; 32] {
1071 &self.inner.info.query_id
1072 }
1073 pub fn docs(&self) -> &'a [String] {
1075 &self.inner.docs
1076 }
1077 pub fn inputs(
1079 &self,
1080 ) -> impl ExactSizeIterator<Item = &'a ViewFunctionInput<'static, u32>> + use<'a> {
1081 let inputs = &*self.inner.info.inputs;
1082 inputs.iter()
1083 }
1084 pub fn output_ty(&self) -> u32 {
1086 self.inner.info.output_id
1087 }
1088 pub fn hash(&self) -> [u8; HASH_LEN] {
1092 crate::utils::validation::get_view_function_hash(self)
1093 }
1094}
1095
1096#[derive(Debug, Clone)]
1097struct ViewFunctionMetadataInner {
1098 name: String,
1100 info: ViewFunctionInfo<'static, u32>,
1102 docs: Vec<String>,
1104}
1105
1106#[derive(Debug, Clone)]
1108pub struct MethodParamMetadata {
1109 pub name: String,
1111 pub ty: u32,
1113}
1114
1115#[derive(Debug, Clone)]
1118pub struct CustomMetadata<'a> {
1119 types: &'a PortableRegistry,
1120 inner: &'a CustomMetadataInner,
1121}
1122
1123impl<'a> CustomMetadata<'a> {
1124 pub fn get(&self, name: &str) -> Option<CustomValueMetadata<'a>> {
1126 self.inner.map.get_key_value(name).map(|(name, e)| CustomValueMetadata {
1127 types: self.types,
1128 type_id: e.ty.id,
1129 data: &e.value,
1130 name,
1131 })
1132 }
1133
1134 pub fn iter(&self) -> impl Iterator<Item = CustomValueMetadata<'a>> + use<'a> {
1136 self.inner.map.iter().map(|(name, e)| CustomValueMetadata {
1137 types: self.types,
1138 type_id: e.ty.id,
1139 data: &e.value,
1140 name: name.as_ref(),
1141 })
1142 }
1143
1144 pub fn types(&self) -> &PortableRegistry {
1146 self.types
1147 }
1148}
1149
1150pub struct CustomValueMetadata<'a> {
1152 types: &'a PortableRegistry,
1153 type_id: u32,
1154 data: &'a [u8],
1155 name: &'a str,
1156}
1157
1158impl<'a> CustomValueMetadata<'a> {
1159 pub fn types(&self) -> &PortableRegistry {
1161 self.types
1162 }
1163
1164 pub fn bytes(&self) -> &'a [u8] {
1166 self.data
1167 }
1168
1169 pub fn type_id(&self) -> u32 {
1171 self.type_id
1172 }
1173
1174 pub fn name(&self) -> &str {
1176 self.name
1177 }
1178
1179 pub fn hash(&self) -> [u8; HASH_LEN] {
1181 get_custom_value_hash(self)
1182 }
1183}
1184
1185pub fn decode_runtime_metadata(
1193 input: &[u8],
1194) -> Result<frame_metadata::RuntimeMetadata, codec::Error> {
1195 use codec::Decode;
1196
1197 let err = match frame_metadata::RuntimeMetadataPrefixed::decode(&mut &*input) {
1198 Ok(md) => return Ok(md.1),
1199 Err(e) => e,
1200 };
1201
1202 if let Ok(md) = frame_metadata::RuntimeMetadata::decode(&mut &*input) {
1203 return Ok(md);
1204 }
1205
1206 if let Ok(len) = codec::Compact::<u64>::decode(&mut &*input) {
1210 if input.len() == len.0 as usize {
1211 return decode_runtime_metadata(input);
1212 }
1213 }
1214
1215 Err(err)
1216}
1217
1218impl codec::Decode for Metadata {
1221 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
1222 let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(input)?;
1223 let metadata = match metadata.1 {
1224 frame_metadata::RuntimeMetadata::V14(md) => md.try_into(),
1225 frame_metadata::RuntimeMetadata::V15(md) => md.try_into(),
1226 frame_metadata::RuntimeMetadata::V16(md) => md.try_into(),
1227 _ => {
1228 return Err("Metadata::decode failed: Cannot try_into() to Metadata: unsupported metadata version".into())
1229 },
1230 };
1231
1232 metadata.map_err(|_| "Metadata::decode failed: Cannot try_into() to Metadata".into())
1233 }
1234}