1#![cfg_attr(not(feature = "std"), no_std)]
18#![deny(missing_docs)]
19
20extern crate alloc;
21
22mod from;
23mod utils;
24
25use alloc::borrow::Cow;
26use alloc::collections::BTreeMap;
27use alloc::string::{String, ToString};
28use alloc::sync::Arc;
29use alloc::vec::Vec;
30use frame_decode::constants::{ConstantEntry, ConstantInfo, ConstantInfoError};
31use frame_decode::custom_values::{CustomValue, CustomValueInfo, CustomValueInfoError};
32use frame_decode::extrinsics::{
33 ExtrinsicCallInfo, ExtrinsicExtensionInfo, ExtrinsicInfoArg, ExtrinsicInfoError,
34 ExtrinsicSignatureInfo,
35};
36use frame_decode::runtime_apis::{
37 RuntimeApiEntry, RuntimeApiInfo, RuntimeApiInfoError, RuntimeApiInput,
38};
39use frame_decode::storage::{StorageEntry, StorageInfo, StorageInfoError, StorageKeyInfo};
40use frame_decode::view_functions::{
41 ViewFunctionEntry, ViewFunctionInfo, ViewFunctionInfoError, ViewFunctionInput,
42};
43
44use hashbrown::HashMap;
45use scale_info::{PortableRegistry, Variant, form::PortableForm};
46use utils::{
47 ordered_map::OrderedMap,
48 validation::{HASH_LEN, get_custom_value_hash},
49 variant_index::VariantIndex,
50};
51
52pub use frame_decode::storage::StorageHasher;
53pub use from::SUPPORTED_METADATA_VERSIONS;
54pub use from::TryFromError;
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
62pub type ArcMetadata = Arc<Metadata>;
64
65#[derive(Debug)]
69pub struct Metadata {
70 types: PortableRegistry,
72 pallets: OrderedMap<String, PalletMetadataInner>,
74 pallets_by_call_index: HashMap<u8, usize>,
76 pallets_by_event_index: HashMap<u8, usize>,
81 pallets_by_error_index: HashMap<u8, usize>,
86 extrinsic: ExtrinsicMetadata,
88 outer_enums: OuterEnumsMetadata,
90 dispatch_error_ty: Option<u32>,
92 apis: OrderedMap<String, RuntimeApiMetadataInner>,
94 custom: CustomMetadataInner,
96}
97
98impl frame_decode::extrinsics::ExtrinsicTypeInfo for Metadata {
101 type TypeId = u32;
102
103 fn extrinsic_call_info(
104 &self,
105 pallet_index: u8,
106 call_index: u8,
107 ) -> Result<ExtrinsicCallInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
108 let pallet = self.pallet_by_call_index(pallet_index).ok_or({
109 ExtrinsicInfoError::PalletNotFound {
110 index: pallet_index,
111 }
112 })?;
113
114 let call = pallet.call_variant_by_index(call_index).ok_or_else(|| {
115 ExtrinsicInfoError::CallNotFound {
116 index: call_index,
117 pallet_index,
118 pallet_name: Cow::Borrowed(pallet.name()),
119 }
120 })?;
121
122 Ok(ExtrinsicCallInfo {
123 pallet_name: Cow::Borrowed(pallet.name()),
124 call_name: Cow::Borrowed(&call.name),
125 args: call
126 .fields
127 .iter()
128 .map(|f| ExtrinsicInfoArg {
129 name: Cow::Borrowed(f.name.as_deref().unwrap_or("")),
130 id: f.ty.id,
131 })
132 .collect(),
133 })
134 }
135
136 fn extrinsic_signature_info(
137 &self,
138 ) -> Result<ExtrinsicSignatureInfo<Self::TypeId>, ExtrinsicInfoError<'_>> {
139 Ok(ExtrinsicSignatureInfo {
140 address_id: self.extrinsic().address_ty,
141 signature_id: self.extrinsic().signature_ty,
142 })
143 }
144
145 fn extrinsic_extension_info(
146 &self,
147 extension_version: Option<u8>,
148 ) -> Result<ExtrinsicExtensionInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
149 let extension_version = extension_version.unwrap_or_else(|| {
150 self.extrinsic()
154 .transaction_extension_version_to_use_for_decoding()
155 });
156
157 let extension_ids = self
158 .extrinsic()
159 .transaction_extensions_by_version(extension_version)
160 .ok_or(ExtrinsicInfoError::ExtrinsicExtensionVersionNotFound { extension_version })?
161 .map(|f| ExtrinsicInfoArg {
162 name: Cow::Borrowed(f.identifier()),
163 id: f.extra_ty(),
164 })
165 .collect();
166
167 Ok(ExtrinsicExtensionInfo { extension_ids })
168 }
169}
170impl frame_decode::storage::StorageTypeInfo for Metadata {
171 type TypeId = u32;
172
173 fn storage_info(
174 &self,
175 pallet_name: &str,
176 storage_entry: &str,
177 ) -> Result<StorageInfo<'_, Self::TypeId>, StorageInfoError<'_>> {
178 let pallet =
179 self.pallet_by_name(pallet_name)
180 .ok_or_else(|| StorageInfoError::PalletNotFound {
181 pallet_name: pallet_name.to_string(),
182 })?;
183 let entry = pallet
184 .storage()
185 .and_then(|storage| storage.entry_by_name(storage_entry))
186 .ok_or_else(|| StorageInfoError::StorageNotFound {
187 name: storage_entry.to_string(),
188 pallet_name: Cow::Borrowed(pallet.name()),
189 })?;
190
191 let info = StorageInfo {
192 keys: Cow::Borrowed(&*entry.info.keys),
193 value_id: entry.info.value_id,
194 default_value: entry
195 .info
196 .default_value
197 .as_ref()
198 .map(|def| Cow::Borrowed(&**def)),
199 use_old_v9_storage_hashers: false,
200 };
201
202 Ok(info)
203 }
204}
205impl frame_decode::storage::StorageEntryInfo for Metadata {
206 fn storage_entries(&self) -> impl Iterator<Item = StorageEntry<'_>> {
207 self.pallets().flat_map(|pallet| {
208 let pallet_name = pallet.name();
209 let pallet_iter = core::iter::once(StorageEntry::In(pallet_name.into()));
210 let entries_iter = pallet.storage().into_iter().flat_map(|storage| {
211 storage
212 .entries()
213 .iter()
214 .map(|entry| StorageEntry::Name(entry.name().into()))
215 });
216
217 pallet_iter.chain(entries_iter)
218 })
219 }
220}
221impl frame_decode::runtime_apis::RuntimeApiTypeInfo for Metadata {
222 type TypeId = u32;
223
224 fn runtime_api_info(
225 &self,
226 trait_name: &str,
227 method_name: &str,
228 ) -> Result<RuntimeApiInfo<'_, Self::TypeId>, RuntimeApiInfoError<'_>> {
229 let api_trait =
230 self.apis
231 .get_by_key(trait_name)
232 .ok_or_else(|| RuntimeApiInfoError::TraitNotFound {
233 trait_name: trait_name.to_string(),
234 })?;
235 let api_method = api_trait.methods.get_by_key(method_name).ok_or_else(|| {
236 RuntimeApiInfoError::MethodNotFound {
237 trait_name: Cow::Borrowed(&api_trait.name),
238 method_name: method_name.to_string(),
239 }
240 })?;
241
242 let info = RuntimeApiInfo {
243 inputs: Cow::Borrowed(&api_method.info.inputs),
244 output_id: api_method.info.output_id,
245 };
246
247 Ok(info)
248 }
249}
250impl frame_decode::runtime_apis::RuntimeApiEntryInfo for Metadata {
251 fn runtime_api_entries(&self) -> impl Iterator<Item = RuntimeApiEntry<'_>> {
252 self.runtime_api_traits().flat_map(|api_trait| {
253 let trait_name = api_trait.name();
254 let trait_iter = core::iter::once(RuntimeApiEntry::In(trait_name.into()));
255 let method_iter = api_trait
256 .methods()
257 .map(|method| RuntimeApiEntry::Name(method.name().into()));
258
259 trait_iter.chain(method_iter)
260 })
261 }
262}
263impl frame_decode::view_functions::ViewFunctionTypeInfo for Metadata {
264 type TypeId = u32;
265
266 fn view_function_info(
267 &self,
268 pallet_name: &str,
269 function_name: &str,
270 ) -> Result<ViewFunctionInfo<'_, Self::TypeId>, ViewFunctionInfoError<'_>> {
271 let pallet = self.pallet_by_name(pallet_name).ok_or_else(|| {
272 ViewFunctionInfoError::PalletNotFound {
273 pallet_name: pallet_name.to_string(),
274 }
275 })?;
276 let function = pallet.view_function_by_name(function_name).ok_or_else(|| {
277 ViewFunctionInfoError::FunctionNotFound {
278 pallet_name: Cow::Borrowed(pallet.name()),
279 function_name: function_name.to_string(),
280 }
281 })?;
282
283 let info = ViewFunctionInfo {
284 inputs: Cow::Borrowed(&function.inner.info.inputs),
285 output_id: function.inner.info.output_id,
286 query_id: *function.query_id(),
287 };
288
289 Ok(info)
290 }
291}
292impl frame_decode::view_functions::ViewFunctionEntryInfo for Metadata {
293 fn view_function_entries(&self) -> impl Iterator<Item = ViewFunctionEntry<'_>> {
294 self.pallets().flat_map(|pallet| {
295 let pallet_name = pallet.name();
296 let pallet_iter = core::iter::once(ViewFunctionEntry::In(pallet_name.into()));
297 let fn_iter = pallet
298 .view_functions()
299 .map(|function| ViewFunctionEntry::Name(function.name().into()));
300
301 pallet_iter.chain(fn_iter)
302 })
303 }
304}
305impl frame_decode::constants::ConstantTypeInfo for Metadata {
306 type TypeId = u32;
307
308 fn constant_info(
309 &self,
310 pallet_name: &str,
311 constant_name: &str,
312 ) -> Result<ConstantInfo<'_, Self::TypeId>, ConstantInfoError<'_>> {
313 let pallet =
314 self.pallet_by_name(pallet_name)
315 .ok_or_else(|| ConstantInfoError::PalletNotFound {
316 pallet_name: pallet_name.to_string(),
317 })?;
318 let constant = pallet.constant_by_name(constant_name).ok_or_else(|| {
319 ConstantInfoError::ConstantNotFound {
320 pallet_name: Cow::Borrowed(pallet.name()),
321 constant_name: constant_name.to_string(),
322 }
323 })?;
324
325 let info = ConstantInfo {
326 bytes: &constant.value,
327 type_id: constant.ty,
328 };
329
330 Ok(info)
331 }
332}
333impl frame_decode::constants::ConstantEntryInfo for Metadata {
334 fn constant_entries(&self) -> impl Iterator<Item = ConstantEntry<'_>> {
335 self.pallets().flat_map(|pallet| {
336 let pallet_name = pallet.name();
337 let pallet_iter = core::iter::once(ConstantEntry::In(pallet_name.into()));
338 let constant_iter = pallet
339 .constants()
340 .map(|constant| ConstantEntry::Name(constant.name().into()));
341
342 pallet_iter.chain(constant_iter)
343 })
344 }
345}
346impl frame_decode::custom_values::CustomValueTypeInfo for Metadata {
347 type TypeId = u32;
348
349 fn custom_value_info(
350 &self,
351 name: &str,
352 ) -> Result<CustomValueInfo<'_, Self::TypeId>, CustomValueInfoError> {
353 let custom_value = self
354 .custom()
355 .get(name)
356 .ok_or_else(|| CustomValueInfoError {
357 not_found: name.to_string(),
358 })?;
359
360 let info = CustomValueInfo {
361 bytes: custom_value.data,
362 type_id: custom_value.type_id,
363 };
364
365 Ok(info)
366 }
367}
368impl frame_decode::custom_values::CustomValueEntryInfo for Metadata {
369 fn custom_values(&self) -> impl Iterator<Item = CustomValue<'_>> {
370 self.custom.map.keys().map(|name| CustomValue {
371 name: Cow::Borrowed(name),
372 })
373 }
374}
375
376impl Metadata {
377 pub fn arc(self) -> ArcMetadata {
380 Arc::new(self)
381 }
382
383 pub fn decode_from(mut bytes: &[u8]) -> Result<Self, codec::Error> {
385 <Self as codec::Decode>::decode(&mut bytes)
386 }
387
388 pub fn from_v16(
390 metadata: frame_metadata::v16::RuntimeMetadataV16,
391 ) -> Result<Self, TryFromError> {
392 metadata.try_into()
393 }
394
395 pub fn from_v15(
397 metadata: frame_metadata::v15::RuntimeMetadataV15,
398 ) -> Result<Self, TryFromError> {
399 metadata.try_into()
400 }
401
402 pub fn from_v14(
404 metadata: frame_metadata::v14::RuntimeMetadataV14,
405 ) -> Result<Self, TryFromError> {
406 metadata.try_into()
407 }
408
409 #[cfg(feature = "legacy")]
411 pub fn from_v13(
412 metadata: &frame_metadata::v13::RuntimeMetadataV13,
413 types: &scale_info_legacy::TypeRegistrySet<'_>,
414 ) -> Result<Self, LegacyFromError> {
415 from::legacy::from_v13(metadata, types, from::legacy::Opts::compat())
416 }
417
418 #[cfg(feature = "legacy")]
420 pub fn from_v12(
421 metadata: &frame_metadata::v12::RuntimeMetadataV12,
422 types: &scale_info_legacy::TypeRegistrySet<'_>,
423 ) -> Result<Self, LegacyFromError> {
424 from::legacy::from_v12(metadata, types, from::legacy::Opts::compat())
425 }
426
427 #[cfg(feature = "legacy")]
429 pub fn from_v11(
430 metadata: &frame_metadata::v11::RuntimeMetadataV11,
431 types: &scale_info_legacy::TypeRegistrySet<'_>,
432 ) -> Result<Self, LegacyFromError> {
433 from::legacy::from_v11(metadata, types, from::legacy::Opts::compat())
434 }
435
436 #[cfg(feature = "legacy")]
438 pub fn from_v10(
439 metadata: &frame_metadata::v10::RuntimeMetadataV10,
440 types: &scale_info_legacy::TypeRegistrySet<'_>,
441 ) -> Result<Self, LegacyFromError> {
442 from::legacy::from_v10(metadata, types, from::legacy::Opts::compat())
443 }
444
445 #[cfg(feature = "legacy")]
447 pub fn from_v9(
448 metadata: &frame_metadata::v9::RuntimeMetadataV9,
449 types: &scale_info_legacy::TypeRegistrySet<'_>,
450 ) -> Result<Self, LegacyFromError> {
451 from::legacy::from_v9(metadata, types, from::legacy::Opts::compat())
452 }
453
454 #[cfg(feature = "legacy")]
456 pub fn from_v8(
457 metadata: &frame_metadata::v8::RuntimeMetadataV8,
458 types: &scale_info_legacy::TypeRegistrySet<'_>,
459 ) -> Result<Self, LegacyFromError> {
460 from::legacy::from_v8(metadata, types, from::legacy::Opts::compat())
461 }
462
463 pub fn types(&self) -> &PortableRegistry {
465 &self.types
466 }
467
468 pub fn types_mut(&mut self) -> &mut PortableRegistry {
470 &mut self.types
471 }
472
473 pub fn dispatch_error_ty(&self) -> Option<u32> {
475 self.dispatch_error_ty
476 }
477
478 pub fn extrinsic(&self) -> &ExtrinsicMetadata {
480 &self.extrinsic
481 }
482
483 pub fn outer_enums(&self) -> OuterEnumsMetadata {
485 self.outer_enums
486 }
487
488 pub fn pallets(&self) -> impl ExactSizeIterator<Item = PalletMetadata<'_>> {
490 self.pallets.values().iter().map(|inner| PalletMetadata {
491 inner,
492 types: self.types(),
493 })
494 }
495
496 pub fn pallet_by_call_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
498 let inner = self
499 .pallets_by_call_index
500 .get(&variant_index)
501 .and_then(|i| self.pallets.get_by_index(*i))?;
502
503 Some(PalletMetadata {
504 inner,
505 types: self.types(),
506 })
507 }
508
509 pub fn pallet_by_event_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
511 let inner = self
512 .pallets_by_event_index
513 .get(&variant_index)
514 .and_then(|i| self.pallets.get_by_index(*i))?;
515
516 Some(PalletMetadata {
517 inner,
518 types: self.types(),
519 })
520 }
521
522 pub fn pallet_by_error_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
524 let inner = self
525 .pallets_by_error_index
526 .get(&variant_index)
527 .and_then(|i| self.pallets.get_by_index(*i))?;
528
529 Some(PalletMetadata {
530 inner,
531 types: self.types(),
532 })
533 }
534
535 pub fn pallet_by_name(&self, pallet_name: &str) -> Option<PalletMetadata<'_>> {
537 let inner = self.pallets.get_by_key(pallet_name)?;
538
539 Some(PalletMetadata {
540 inner,
541 types: self.types(),
542 })
543 }
544
545 pub fn runtime_api_traits(&self) -> impl ExactSizeIterator<Item = RuntimeApiMetadata<'_>> {
547 self.apis.values().iter().map(|inner| RuntimeApiMetadata {
548 inner,
549 types: self.types(),
550 })
551 }
552
553 pub fn runtime_api_trait_by_name(&'_ self, name: &str) -> Option<RuntimeApiMetadata<'_>> {
555 let inner = self.apis.get_by_key(name)?;
556 Some(RuntimeApiMetadata {
557 inner,
558 types: self.types(),
559 })
560 }
561
562 pub fn custom(&self) -> CustomMetadata<'_> {
564 CustomMetadata {
565 types: self.types(),
566 inner: &self.custom,
567 }
568 }
569
570 pub fn hasher(&self) -> MetadataHasher<'_> {
572 MetadataHasher::new(self)
573 }
574
575 pub fn type_hash(&self, id: u32) -> Option<[u8; HASH_LEN]> {
577 self.types.resolve(id)?;
578 Some(crate::utils::validation::get_type_hash(&self.types, id))
579 }
580}
581
582#[derive(Debug, Clone, Copy)]
584pub struct PalletMetadata<'a> {
585 inner: &'a PalletMetadataInner,
586 types: &'a PortableRegistry,
587}
588
589impl<'a> PalletMetadata<'a> {
590 pub fn name(&self) -> &'a str {
592 &self.inner.name
593 }
594
595 pub fn call_index(&self) -> u8 {
597 self.inner.call_index
598 }
599
600 pub fn event_index(&self) -> u8 {
602 self.inner.event_index
603 }
604
605 pub fn error_index(&self) -> u8 {
607 self.inner.error_index
608 }
609
610 pub fn docs(&self) -> &'a [String] {
612 &self.inner.docs
613 }
614
615 pub fn call_ty_id(&self) -> Option<u32> {
617 self.inner.call_ty
618 }
619
620 pub fn event_ty_id(&self) -> Option<u32> {
622 self.inner.event_ty
623 }
624
625 pub fn error_ty_id(&self) -> Option<u32> {
627 self.inner.error_ty
628 }
629
630 pub fn storage(&self) -> Option<&'a StorageMetadata> {
632 self.inner.storage.as_ref()
633 }
634
635 pub fn event_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
637 VariantIndex::get(self.inner.event_ty, self.types)
638 }
639
640 pub fn event_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
642 self.inner.event_variant_index.lookup_by_index(
643 variant_index,
644 self.inner.event_ty,
645 self.types,
646 )
647 }
648
649 pub fn has_view_functions(&self) -> bool {
651 !self.inner.view_functions.is_empty()
652 }
653
654 pub fn view_functions(
656 &self,
657 ) -> impl ExactSizeIterator<Item = ViewFunctionMetadata<'a>> + use<'a> {
658 self.inner
659 .view_functions
660 .values()
661 .iter()
662 .map(|vf: &'a _| ViewFunctionMetadata {
663 inner: vf,
664 types: self.types,
665 })
666 }
667
668 pub fn view_function_by_name(&self, name: &str) -> Option<ViewFunctionMetadata<'a>> {
670 self.inner
671 .view_functions
672 .get_by_key(name)
673 .map(|vf: &'a _| ViewFunctionMetadata {
674 inner: vf,
675 types: self.types,
676 })
677 }
678
679 pub fn associated_types(&self) -> impl ExactSizeIterator<Item = (&'a str, u32)> + use<'a> {
681 self.inner
682 .associated_types
683 .iter()
684 .map(|(name, ty)| (&**name, *ty))
685 }
686
687 pub fn associated_type_id(&self, name: &str) -> Option<u32> {
689 self.inner.associated_types.get(name).copied()
690 }
691
692 pub fn call_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
694 VariantIndex::get(self.inner.call_ty, self.types)
695 }
696
697 pub fn call_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
699 self.inner
700 .call_variant_index
701 .lookup_by_index(variant_index, self.inner.call_ty, self.types)
702 }
703
704 pub fn call_variant_by_name(&self, call_name: &str) -> Option<&'a Variant<PortableForm>> {
706 self.inner
707 .call_variant_index
708 .lookup_by_name(call_name, self.inner.call_ty, self.types)
709 }
710
711 pub fn error_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
713 VariantIndex::get(self.inner.error_ty, self.types)
714 }
715
716 pub fn error_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
718 self.inner.error_variant_index.lookup_by_index(
719 variant_index,
720 self.inner.error_ty,
721 self.types,
722 )
723 }
724
725 pub fn constant_by_name(&self, name: &str) -> Option<&'a ConstantMetadata> {
727 self.inner.constants.get_by_key(name)
728 }
729
730 pub fn constants(&self) -> impl ExactSizeIterator<Item = &'a ConstantMetadata> + use<'a> {
732 self.inner.constants.values().iter()
733 }
734
735 pub fn storage_hash(&self, entry_name: &str) -> Option<[u8; HASH_LEN]> {
737 crate::utils::validation::get_storage_hash(self, entry_name)
738 }
739
740 pub fn constant_hash(&self, constant_name: &str) -> Option<[u8; HASH_LEN]> {
742 crate::utils::validation::get_constant_hash(self, constant_name)
743 }
744
745 pub fn call_hash(&self, call_name: &str) -> Option<[u8; HASH_LEN]> {
747 crate::utils::validation::get_call_hash(self, call_name)
748 }
749
750 pub fn hash(&self) -> [u8; HASH_LEN] {
752 crate::utils::validation::get_pallet_hash(*self)
753 }
754}
755
756#[derive(Debug, Clone)]
757struct PalletMetadataInner {
758 name: String,
760 call_index: u8,
762 event_index: u8,
767 error_index: u8,
772 storage: Option<StorageMetadata>,
774 call_ty: Option<u32>,
776 call_variant_index: VariantIndex,
778 event_ty: Option<u32>,
780 event_variant_index: VariantIndex,
782 error_ty: Option<u32>,
784 error_variant_index: VariantIndex,
786 constants: OrderedMap<String, ConstantMetadata>,
788 view_functions: OrderedMap<String, ViewFunctionMetadataInner>,
790 associated_types: BTreeMap<String, u32>,
792 docs: Vec<String>,
794}
795
796#[derive(Debug, Clone)]
798pub struct StorageMetadata {
799 prefix: String,
801 entries: OrderedMap<String, StorageEntryMetadata>,
803}
804
805impl StorageMetadata {
806 pub fn prefix(&self) -> &str {
808 &self.prefix
809 }
810
811 pub fn entries(&self) -> &[StorageEntryMetadata] {
813 self.entries.values()
814 }
815
816 pub fn entry_by_name(&self, name: &str) -> Option<&StorageEntryMetadata> {
818 self.entries.get_by_key(name)
819 }
820}
821
822#[derive(Debug, Clone)]
824pub struct StorageEntryMetadata {
825 name: String,
827 info: StorageInfo<'static, u32>,
829 docs: Vec<String>,
831}
832
833impl StorageEntryMetadata {
834 pub fn name(&self) -> &str {
836 &self.name
837 }
838 pub fn keys(&self) -> impl ExactSizeIterator<Item = &StorageKeyInfo<u32>> {
840 let keys = &*self.info.keys;
841 keys.iter()
842 }
843 pub fn value_ty(&self) -> u32 {
845 self.info.value_id
846 }
847 pub fn default_value(&self) -> Option<&[u8]> {
849 self.info.default_value.as_deref()
850 }
851 pub fn docs(&self) -> &[String] {
853 &self.docs
854 }
855}
856
857#[derive(Debug, Clone)]
859pub struct ConstantMetadata {
860 name: String,
862 ty: u32,
864 value: Vec<u8>,
866 docs: Vec<String>,
868}
869
870impl ConstantMetadata {
871 pub fn name(&self) -> &str {
873 &self.name
874 }
875 pub fn ty(&self) -> u32 {
877 self.ty
878 }
879 pub fn value(&self) -> &[u8] {
881 &self.value
882 }
883 pub fn docs(&self) -> &[String] {
885 &self.docs
886 }
887}
888
889#[derive(Debug, Clone)]
891pub struct ExtrinsicMetadata {
892 address_ty: u32,
895 signature_ty: u32,
898 supported_versions: Vec<u8>,
900 transaction_extensions: Vec<TransactionExtensionMetadataInner>,
902 transaction_extensions_by_version: BTreeMap<u8, Vec<u32>>,
906}
907
908impl ExtrinsicMetadata {
909 pub fn supported_versions(&self) -> &[u8] {
911 &self.supported_versions
912 }
913
914 pub fn transaction_extensions_by_version(
916 &self,
917 version: u8,
918 ) -> Option<impl Iterator<Item = TransactionExtensionMetadata<'_>>> {
919 let extension_indexes = self.transaction_extensions_by_version.get(&version)?;
920 let iter = extension_indexes.iter().map(|index| {
921 let tx_metadata = self
922 .transaction_extensions
923 .get(*index as usize)
924 .expect("transaction extension should exist if index is in transaction_extensions_by_version");
925
926 TransactionExtensionMetadata {
927 identifier: &tx_metadata.identifier,
928 extra_ty: tx_metadata.extra_ty,
929 additional_ty: tx_metadata.additional_ty,
930 }
931 });
932
933 Some(iter)
934 }
935
936 pub fn transaction_extension_version_to_use_for_encoding(&self) -> u8 {
938 *self
939 .transaction_extensions_by_version
940 .keys()
941 .max()
942 .expect("At least one version of transaction extensions is expected")
943 }
944
945 pub fn transaction_extensions_to_use_for_encoding(
948 &self,
949 ) -> impl Iterator<Item = TransactionExtensionMetadata<'_>> {
950 let encoding_version = self.transaction_extension_version_to_use_for_encoding();
951 self.transaction_extensions_by_version(encoding_version)
952 .unwrap()
953 }
954
955 pub fn transaction_extension_version_to_use_for_decoding(&self) -> u8 {
957 *self
958 .transaction_extensions_by_version
959 .keys()
960 .max()
961 .expect("At least one version of transaction extensions is expected")
962 }
963}
964
965#[derive(Debug, Clone)]
967pub struct TransactionExtensionMetadata<'a> {
968 identifier: &'a str,
970 extra_ty: u32,
972 additional_ty: u32,
974}
975
976#[derive(Debug, Clone)]
977struct TransactionExtensionMetadataInner {
978 identifier: String,
979 extra_ty: u32,
980 additional_ty: u32,
981}
982
983impl<'a> TransactionExtensionMetadata<'a> {
984 pub fn identifier(&self) -> &'a str {
986 self.identifier
987 }
988 pub fn extra_ty(&self) -> u32 {
990 self.extra_ty
991 }
992 pub fn additional_ty(&self) -> u32 {
994 self.additional_ty
995 }
996}
997
998#[derive(Debug, Clone, Copy)]
1000pub struct OuterEnumsMetadata {
1001 call_enum_ty: u32,
1003 event_enum_ty: u32,
1005 error_enum_ty: u32,
1007}
1008
1009impl OuterEnumsMetadata {
1010 pub fn call_enum_ty(&self) -> u32 {
1012 self.call_enum_ty
1013 }
1014
1015 pub fn event_enum_ty(&self) -> u32 {
1017 self.event_enum_ty
1018 }
1019
1020 pub fn error_enum_ty(&self) -> u32 {
1022 self.error_enum_ty
1023 }
1024}
1025
1026#[derive(Debug, Clone, Copy)]
1028pub struct RuntimeApiMetadata<'a> {
1029 inner: &'a RuntimeApiMetadataInner,
1030 types: &'a PortableRegistry,
1031}
1032
1033impl<'a> RuntimeApiMetadata<'a> {
1034 pub fn name(&self) -> &'a str {
1036 &self.inner.name
1037 }
1038 pub fn docs(&self) -> &[String] {
1040 &self.inner.docs
1041 }
1042 pub fn methods(&self) -> impl ExactSizeIterator<Item = RuntimeApiMethodMetadata<'a>> + use<'a> {
1044 self.inner
1045 .methods
1046 .values()
1047 .iter()
1048 .map(|item| RuntimeApiMethodMetadata {
1049 trait_name: &self.inner.name,
1050 inner: item,
1051 types: self.types,
1052 })
1053 }
1054 pub fn method_by_name(&self, name: &str) -> Option<RuntimeApiMethodMetadata<'a>> {
1056 self.inner
1057 .methods
1058 .get_by_key(name)
1059 .map(|item| RuntimeApiMethodMetadata {
1060 trait_name: &self.inner.name,
1061 inner: item,
1062 types: self.types,
1063 })
1064 }
1065 pub fn hash(&self) -> [u8; HASH_LEN] {
1067 crate::utils::validation::get_runtime_apis_hash(*self)
1068 }
1069}
1070
1071#[derive(Debug, Clone)]
1072struct RuntimeApiMetadataInner {
1073 name: String,
1075 methods: OrderedMap<String, RuntimeApiMethodMetadataInner>,
1077 docs: Vec<String>,
1079}
1080
1081#[derive(Debug, Clone)]
1083pub struct RuntimeApiMethodMetadata<'a> {
1084 trait_name: &'a str,
1085 inner: &'a RuntimeApiMethodMetadataInner,
1086 types: &'a PortableRegistry,
1087}
1088
1089impl<'a> RuntimeApiMethodMetadata<'a> {
1090 pub fn name(&self) -> &'a str {
1092 &self.inner.name
1093 }
1094 pub fn docs(&self) -> &[String] {
1096 &self.inner.docs
1097 }
1098 pub fn inputs(
1100 &self,
1101 ) -> impl ExactSizeIterator<Item = &'a RuntimeApiInput<'static, u32>> + use<'a> {
1102 let inputs = &*self.inner.info.inputs;
1103 inputs.iter()
1104 }
1105 pub fn output_ty(&self) -> u32 {
1107 self.inner.info.output_id
1108 }
1109 pub fn hash(&self) -> [u8; HASH_LEN] {
1111 crate::utils::validation::get_runtime_api_hash(self)
1112 }
1113}
1114
1115#[derive(Debug, Clone)]
1116struct RuntimeApiMethodMetadataInner {
1117 name: String,
1119 info: RuntimeApiInfo<'static, u32>,
1121 docs: Vec<String>,
1123}
1124
1125#[derive(Debug, Clone, Copy)]
1128pub struct ViewFunctionMetadata<'a> {
1129 inner: &'a ViewFunctionMetadataInner,
1130 types: &'a PortableRegistry,
1131}
1132
1133impl<'a> ViewFunctionMetadata<'a> {
1134 pub fn name(&self) -> &'a str {
1136 &self.inner.name
1137 }
1138 pub fn query_id(&self) -> &'a [u8; 32] {
1141 &self.inner.info.query_id
1142 }
1143 pub fn docs(&self) -> &'a [String] {
1145 &self.inner.docs
1146 }
1147 pub fn inputs(
1149 &self,
1150 ) -> impl ExactSizeIterator<Item = &'a ViewFunctionInput<'static, u32>> + use<'a> {
1151 let inputs = &*self.inner.info.inputs;
1152 inputs.iter()
1153 }
1154 pub fn output_ty(&self) -> u32 {
1156 self.inner.info.output_id
1157 }
1158 pub fn hash(&self) -> [u8; HASH_LEN] {
1162 crate::utils::validation::get_view_function_hash(self)
1163 }
1164}
1165
1166#[derive(Debug, Clone)]
1167struct ViewFunctionMetadataInner {
1168 name: String,
1170 info: ViewFunctionInfo<'static, u32>,
1172 docs: Vec<String>,
1174}
1175
1176#[derive(Debug, Clone)]
1178pub struct MethodParamMetadata {
1179 pub name: String,
1181 pub ty: u32,
1183}
1184
1185#[derive(Debug, Clone)]
1187pub struct CustomMetadata<'a> {
1188 types: &'a PortableRegistry,
1189 inner: &'a CustomMetadataInner,
1190}
1191
1192impl<'a> CustomMetadata<'a> {
1193 pub fn get(&self, name: &str) -> Option<CustomValueMetadata<'a>> {
1195 self.inner
1196 .map
1197 .get_key_value(name)
1198 .map(|(name, e)| CustomValueMetadata {
1199 types: self.types,
1200 type_id: e.ty.id,
1201 data: &e.value,
1202 name,
1203 })
1204 }
1205
1206 pub fn iter(&self) -> impl Iterator<Item = CustomValueMetadata<'a>> + use<'a> {
1208 self.inner.map.iter().map(|(name, e)| CustomValueMetadata {
1209 types: self.types,
1210 type_id: e.ty.id,
1211 data: &e.value,
1212 name: name.as_ref(),
1213 })
1214 }
1215
1216 pub fn types(&self) -> &PortableRegistry {
1218 self.types
1219 }
1220}
1221
1222pub struct CustomValueMetadata<'a> {
1224 types: &'a PortableRegistry,
1225 type_id: u32,
1226 data: &'a [u8],
1227 name: &'a str,
1228}
1229
1230impl<'a> CustomValueMetadata<'a> {
1231 pub fn types(&self) -> &PortableRegistry {
1233 self.types
1234 }
1235
1236 pub fn bytes(&self) -> &'a [u8] {
1238 self.data
1239 }
1240
1241 pub fn type_id(&self) -> u32 {
1243 self.type_id
1244 }
1245
1246 pub fn name(&self) -> &str {
1248 self.name
1249 }
1250
1251 pub fn hash(&self) -> [u8; HASH_LEN] {
1253 get_custom_value_hash(self)
1254 }
1255}
1256
1257pub fn decode_runtime_metadata(
1264 input: &[u8],
1265) -> Result<frame_metadata::RuntimeMetadata, codec::Error> {
1266 use codec::Decode;
1267
1268 let err = match frame_metadata::RuntimeMetadataPrefixed::decode(&mut &*input) {
1269 Ok(md) => return Ok(md.1),
1270 Err(e) => e,
1271 };
1272
1273 if let Ok(md) = frame_metadata::RuntimeMetadata::decode(&mut &*input) {
1274 return Ok(md);
1275 }
1276
1277 if let Ok(len) = codec::Compact::<u64>::decode(&mut &*input) {
1281 if input.len() == len.0 as usize {
1282 return decode_runtime_metadata(input);
1283 }
1284 }
1285
1286 Err(err)
1287}
1288
1289impl codec::Decode for Metadata {
1292 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
1293 let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(input)?;
1294 let metadata = match metadata.1 {
1295 frame_metadata::RuntimeMetadata::V14(md) => md.try_into(),
1296 frame_metadata::RuntimeMetadata::V15(md) => md.try_into(),
1297 frame_metadata::RuntimeMetadata::V16(md) => md.try_into(),
1298 _ => {
1299 return Err("Metadata::decode failed: Cannot try_into() to Metadata: unsupported metadata version".into())
1300 },
1301 };
1302
1303 metadata.map_err(|_| "Metadata::decode failed: Cannot try_into() to Metadata".into())
1304 }
1305}