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};
43use hashbrown::HashMap;
44use scale_info::{PortableRegistry, Variant, form::PortableForm};
45use utils::{
46 ordered_map::OrderedMap,
47 validation::{HASH_LEN, get_custom_value_hash},
48 variant_index::VariantIndex,
49};
50
51pub use frame_decode::storage::StorageHasher;
52pub use from::SUPPORTED_METADATA_VERSIONS;
53pub use from::TryFromError;
54pub use utils::validation::MetadataHasher;
55
56#[cfg(feature = "legacy")]
57pub use from::legacy::Error as LegacyFromError;
58
59type CustomMetadataInner = frame_metadata::v15::CustomMetadata<PortableForm>;
60
61pub type ArcMetadata = Arc<Metadata>;
63
64#[derive(Debug)]
68pub struct Metadata {
69 types: PortableRegistry,
71 pallets: OrderedMap<String, PalletMetadataInner>,
73 pallets_by_call_index: HashMap<u8, usize>,
75 pallets_by_event_index: HashMap<u8, usize>,
80 pallets_by_error_index: HashMap<u8, usize>,
85 extrinsic: ExtrinsicMetadata,
87 outer_enums: OuterEnumsMetadata,
89 dispatch_error_ty: Option<u32>,
91 apis: OrderedMap<String, RuntimeApiMetadataInner>,
93 custom: CustomMetadataInner,
95}
96
97impl frame_decode::extrinsics::ExtrinsicTypeInfo for Metadata {
100 type TypeId = u32;
101
102 fn extrinsic_call_info(
103 &self,
104 pallet_index: u8,
105 call_index: u8,
106 ) -> Result<ExtrinsicCallInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
107 let pallet = self.pallet_by_call_index(pallet_index).ok_or({
108 ExtrinsicInfoError::PalletNotFound {
109 index: pallet_index,
110 }
111 })?;
112
113 let call = pallet.call_variant_by_index(call_index).ok_or_else(|| {
114 ExtrinsicInfoError::CallNotFound {
115 index: call_index,
116 pallet_index,
117 pallet_name: Cow::Borrowed(pallet.name()),
118 }
119 })?;
120
121 Ok(ExtrinsicCallInfo {
122 pallet_name: Cow::Borrowed(pallet.name()),
123 call_name: Cow::Borrowed(&call.name),
124 args: call
125 .fields
126 .iter()
127 .map(|f| ExtrinsicInfoArg {
128 name: Cow::Borrowed(f.name.as_deref().unwrap_or("")),
129 id: f.ty.id,
130 })
131 .collect(),
132 })
133 }
134
135 fn extrinsic_signature_info(
136 &self,
137 ) -> Result<ExtrinsicSignatureInfo<Self::TypeId>, ExtrinsicInfoError<'_>> {
138 Ok(ExtrinsicSignatureInfo {
139 address_id: self.extrinsic().address_ty,
140 signature_id: self.extrinsic().signature_ty,
141 })
142 }
143
144 fn extrinsic_extension_info(
145 &self,
146 extension_version: Option<u8>,
147 ) -> Result<ExtrinsicExtensionInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
148 let extension_version = extension_version.unwrap_or_else(|| {
149 self.extrinsic()
153 .transaction_extension_version_to_use_for_decoding()
154 });
155
156 let extension_ids = self
157 .extrinsic()
158 .transaction_extensions_by_version(extension_version)
159 .ok_or(ExtrinsicInfoError::ExtrinsicExtensionVersionNotFound { extension_version })?
160 .map(|f| ExtrinsicInfoArg {
161 name: Cow::Borrowed(f.identifier()),
162 id: f.extra_ty(),
163 })
164 .collect();
165
166 Ok(ExtrinsicExtensionInfo { extension_ids })
167 }
168}
169impl frame_decode::storage::StorageTypeInfo for Metadata {
170 type TypeId = u32;
171
172 fn storage_info(
173 &self,
174 pallet_name: &str,
175 storage_entry: &str,
176 ) -> Result<StorageInfo<'_, Self::TypeId>, StorageInfoError<'_>> {
177 let pallet =
178 self.pallet_by_name(pallet_name)
179 .ok_or_else(|| StorageInfoError::PalletNotFound {
180 pallet_name: pallet_name.to_string(),
181 })?;
182 let entry = pallet
183 .storage()
184 .and_then(|storage| storage.entry_by_name(storage_entry))
185 .ok_or_else(|| StorageInfoError::StorageNotFound {
186 name: storage_entry.to_string(),
187 pallet_name: Cow::Borrowed(pallet.name()),
188 })?;
189
190 let info = StorageInfo {
191 keys: Cow::Borrowed(&*entry.info.keys),
192 value_id: entry.info.value_id,
193 default_value: entry
194 .info
195 .default_value
196 .as_ref()
197 .map(|def| Cow::Borrowed(&**def)),
198 use_old_v9_storage_hashers: false,
199 };
200
201 Ok(info)
202 }
203}
204impl frame_decode::storage::StorageEntryInfo for Metadata {
205 fn storage_entries(&self) -> impl Iterator<Item = StorageEntry<'_>> {
206 self.pallets().flat_map(|pallet| {
207 let pallet_name = pallet.name();
208 let pallet_iter = core::iter::once(StorageEntry::In(pallet_name.into()));
209 let entries_iter = pallet.storage().into_iter().flat_map(|storage| {
210 storage
211 .entries()
212 .iter()
213 .map(|entry| StorageEntry::Name(entry.name().into()))
214 });
215
216 pallet_iter.chain(entries_iter)
217 })
218 }
219}
220impl frame_decode::runtime_apis::RuntimeApiTypeInfo for Metadata {
221 type TypeId = u32;
222
223 fn runtime_api_info(
224 &self,
225 trait_name: &str,
226 method_name: &str,
227 ) -> Result<RuntimeApiInfo<'_, Self::TypeId>, RuntimeApiInfoError<'_>> {
228 let api_trait =
229 self.apis
230 .get_by_key(trait_name)
231 .ok_or_else(|| RuntimeApiInfoError::TraitNotFound {
232 trait_name: trait_name.to_string(),
233 })?;
234 let api_method = api_trait.methods.get_by_key(method_name).ok_or_else(|| {
235 RuntimeApiInfoError::MethodNotFound {
236 trait_name: Cow::Borrowed(&api_trait.name),
237 method_name: method_name.to_string(),
238 }
239 })?;
240
241 let info = RuntimeApiInfo {
242 inputs: Cow::Borrowed(&api_method.info.inputs),
243 output_id: api_method.info.output_id,
244 };
245
246 Ok(info)
247 }
248}
249impl frame_decode::runtime_apis::RuntimeApiEntryInfo for Metadata {
250 fn runtime_api_entries(&self) -> impl Iterator<Item = RuntimeApiEntry<'_>> {
251 self.runtime_api_traits().flat_map(|api_trait| {
252 let trait_name = api_trait.name();
253 let trait_iter = core::iter::once(RuntimeApiEntry::In(trait_name.into()));
254 let method_iter = api_trait
255 .methods()
256 .map(|method| RuntimeApiEntry::Name(method.name().into()));
257
258 trait_iter.chain(method_iter)
259 })
260 }
261}
262impl frame_decode::view_functions::ViewFunctionTypeInfo for Metadata {
263 type TypeId = u32;
264
265 fn view_function_info(
266 &self,
267 pallet_name: &str,
268 function_name: &str,
269 ) -> Result<ViewFunctionInfo<'_, Self::TypeId>, ViewFunctionInfoError<'_>> {
270 let pallet = self.pallet_by_name(pallet_name).ok_or_else(|| {
271 ViewFunctionInfoError::PalletNotFound {
272 pallet_name: pallet_name.to_string(),
273 }
274 })?;
275 let function = pallet.view_function_by_name(function_name).ok_or_else(|| {
276 ViewFunctionInfoError::FunctionNotFound {
277 pallet_name: Cow::Borrowed(pallet.name()),
278 function_name: function_name.to_string(),
279 }
280 })?;
281
282 let info = ViewFunctionInfo {
283 inputs: Cow::Borrowed(&function.inner.info.inputs),
284 output_id: function.inner.info.output_id,
285 query_id: *function.query_id(),
286 };
287
288 Ok(info)
289 }
290}
291impl frame_decode::view_functions::ViewFunctionEntryInfo for Metadata {
292 fn view_function_entries(&self) -> impl Iterator<Item = ViewFunctionEntry<'_>> {
293 self.pallets().flat_map(|pallet| {
294 let pallet_name = pallet.name();
295 let pallet_iter = core::iter::once(ViewFunctionEntry::In(pallet_name.into()));
296 let fn_iter = pallet
297 .view_functions()
298 .map(|function| ViewFunctionEntry::Name(function.name().into()));
299
300 pallet_iter.chain(fn_iter)
301 })
302 }
303}
304impl frame_decode::constants::ConstantTypeInfo for Metadata {
305 type TypeId = u32;
306
307 fn constant_info(
308 &self,
309 pallet_name: &str,
310 constant_name: &str,
311 ) -> Result<ConstantInfo<'_, Self::TypeId>, ConstantInfoError<'_>> {
312 let pallet =
313 self.pallet_by_name(pallet_name)
314 .ok_or_else(|| ConstantInfoError::PalletNotFound {
315 pallet_name: pallet_name.to_string(),
316 })?;
317 let constant = pallet.constant_by_name(constant_name).ok_or_else(|| {
318 ConstantInfoError::ConstantNotFound {
319 pallet_name: Cow::Borrowed(pallet.name()),
320 constant_name: constant_name.to_string(),
321 }
322 })?;
323
324 let info = ConstantInfo {
325 bytes: &constant.value,
326 type_id: constant.ty,
327 };
328
329 Ok(info)
330 }
331}
332impl frame_decode::constants::ConstantEntryInfo for Metadata {
333 fn constant_entries(&self) -> impl Iterator<Item = ConstantEntry<'_>> {
334 self.pallets().flat_map(|pallet| {
335 let pallet_name = pallet.name();
336 let pallet_iter = core::iter::once(ConstantEntry::In(pallet_name.into()));
337 let constant_iter = pallet
338 .constants()
339 .map(|constant| ConstantEntry::Name(constant.name().into()));
340
341 pallet_iter.chain(constant_iter)
342 })
343 }
344}
345impl frame_decode::custom_values::CustomValueTypeInfo for Metadata {
346 type TypeId = u32;
347
348 fn custom_value_info(
349 &self,
350 name: &str,
351 ) -> Result<CustomValueInfo<'_, Self::TypeId>, CustomValueInfoError> {
352 let custom_value = self
353 .custom()
354 .get(name)
355 .ok_or_else(|| CustomValueInfoError {
356 not_found: name.to_string(),
357 })?;
358
359 let info = CustomValueInfo {
360 bytes: custom_value.data,
361 type_id: custom_value.type_id,
362 };
363
364 Ok(info)
365 }
366}
367impl frame_decode::custom_values::CustomValueEntryInfo for Metadata {
368 fn custom_values(&self) -> impl Iterator<Item = CustomValue<'_>> {
369 self.custom.map.keys().map(|name| CustomValue {
370 name: Cow::Borrowed(name),
371 })
372 }
373}
374
375impl Metadata {
376 pub fn arc(self) -> ArcMetadata {
379 Arc::new(self)
380 }
381
382 pub fn decode_from(bytes: &[u8]) -> Result<Self, codec::Error> {
390 let metadata = decode_runtime_metadata(bytes)?;
391 from_runtime_metadata(metadata)
392 }
393
394 pub fn from_v16(
396 metadata: frame_metadata::v16::RuntimeMetadataV16,
397 ) -> Result<Self, TryFromError> {
398 metadata.try_into()
399 }
400
401 pub fn from_v15(
403 metadata: frame_metadata::v15::RuntimeMetadataV15,
404 ) -> Result<Self, TryFromError> {
405 metadata.try_into()
406 }
407
408 pub fn from_v14(
410 metadata: frame_metadata::v14::RuntimeMetadataV14,
411 ) -> Result<Self, TryFromError> {
412 metadata.try_into()
413 }
414
415 #[cfg(feature = "legacy")]
417 pub fn from_v13(
418 metadata: &frame_metadata::v13::RuntimeMetadataV13,
419 types: &scale_info_legacy::TypeRegistrySet<'_>,
420 ) -> Result<Self, LegacyFromError> {
421 from::legacy::from_v13(metadata, types, from::legacy::Opts::compat())
422 }
423
424 #[cfg(feature = "legacy")]
426 pub fn from_v12(
427 metadata: &frame_metadata::v12::RuntimeMetadataV12,
428 types: &scale_info_legacy::TypeRegistrySet<'_>,
429 ) -> Result<Self, LegacyFromError> {
430 from::legacy::from_v12(metadata, types, from::legacy::Opts::compat())
431 }
432
433 #[cfg(feature = "legacy")]
435 pub fn from_v11(
436 metadata: &frame_metadata::v11::RuntimeMetadataV11,
437 types: &scale_info_legacy::TypeRegistrySet<'_>,
438 ) -> Result<Self, LegacyFromError> {
439 from::legacy::from_v11(metadata, types, from::legacy::Opts::compat())
440 }
441
442 #[cfg(feature = "legacy")]
444 pub fn from_v10(
445 metadata: &frame_metadata::v10::RuntimeMetadataV10,
446 types: &scale_info_legacy::TypeRegistrySet<'_>,
447 ) -> Result<Self, LegacyFromError> {
448 from::legacy::from_v10(metadata, types, from::legacy::Opts::compat())
449 }
450
451 #[cfg(feature = "legacy")]
453 pub fn from_v9(
454 metadata: &frame_metadata::v9::RuntimeMetadataV9,
455 types: &scale_info_legacy::TypeRegistrySet<'_>,
456 ) -> Result<Self, LegacyFromError> {
457 from::legacy::from_v9(metadata, types, from::legacy::Opts::compat())
458 }
459
460 #[cfg(feature = "legacy")]
462 pub fn from_v8(
463 metadata: &frame_metadata::v8::RuntimeMetadataV8,
464 types: &scale_info_legacy::TypeRegistrySet<'_>,
465 ) -> Result<Self, LegacyFromError> {
466 from::legacy::from_v8(metadata, types, from::legacy::Opts::compat())
467 }
468
469 pub fn types(&self) -> &PortableRegistry {
471 &self.types
472 }
473
474 pub fn types_mut(&mut self) -> &mut PortableRegistry {
476 &mut self.types
477 }
478
479 pub fn dispatch_error_ty(&self) -> Option<u32> {
481 self.dispatch_error_ty
482 }
483
484 pub fn extrinsic(&self) -> &ExtrinsicMetadata {
486 &self.extrinsic
487 }
488
489 pub fn outer_enums(&self) -> OuterEnumsMetadata {
491 self.outer_enums
492 }
493
494 pub fn pallets(&self) -> impl ExactSizeIterator<Item = PalletMetadata<'_>> {
496 self.pallets.values().iter().map(|inner| PalletMetadata {
497 inner,
498 types: self.types(),
499 })
500 }
501
502 pub fn pallet_by_call_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
504 let inner = self
505 .pallets_by_call_index
506 .get(&variant_index)
507 .and_then(|i| self.pallets.get_by_index(*i))?;
508
509 Some(PalletMetadata {
510 inner,
511 types: self.types(),
512 })
513 }
514
515 pub fn pallet_by_event_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
517 let inner = self
518 .pallets_by_event_index
519 .get(&variant_index)
520 .and_then(|i| self.pallets.get_by_index(*i))?;
521
522 Some(PalletMetadata {
523 inner,
524 types: self.types(),
525 })
526 }
527
528 pub fn pallet_by_error_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
530 let inner = self
531 .pallets_by_error_index
532 .get(&variant_index)
533 .and_then(|i| self.pallets.get_by_index(*i))?;
534
535 Some(PalletMetadata {
536 inner,
537 types: self.types(),
538 })
539 }
540
541 pub fn pallet_by_name(&self, pallet_name: &str) -> Option<PalletMetadata<'_>> {
543 let inner = self.pallets.get_by_key(pallet_name)?;
544
545 Some(PalletMetadata {
546 inner,
547 types: self.types(),
548 })
549 }
550
551 pub fn runtime_api_traits(&self) -> impl ExactSizeIterator<Item = RuntimeApiMetadata<'_>> {
553 self.apis.values().iter().map(|inner| RuntimeApiMetadata {
554 inner,
555 types: self.types(),
556 })
557 }
558
559 pub fn runtime_api_trait_by_name(&'_ self, name: &str) -> Option<RuntimeApiMetadata<'_>> {
561 let inner = self.apis.get_by_key(name)?;
562 Some(RuntimeApiMetadata {
563 inner,
564 types: self.types(),
565 })
566 }
567
568 pub fn custom(&self) -> CustomMetadata<'_> {
570 CustomMetadata {
571 types: self.types(),
572 inner: &self.custom,
573 }
574 }
575
576 pub fn hasher(&self) -> MetadataHasher<'_> {
578 MetadataHasher::new(self)
579 }
580
581 pub fn type_hash(&self, id: u32) -> Option<[u8; HASH_LEN]> {
583 self.types.resolve(id)?;
584 Some(crate::utils::validation::get_type_hash(&self.types, id))
585 }
586}
587
588#[derive(Debug, Clone, Copy)]
590pub struct PalletMetadata<'a> {
591 inner: &'a PalletMetadataInner,
592 types: &'a PortableRegistry,
593}
594
595impl<'a> PalletMetadata<'a> {
596 pub fn name(&self) -> &'a str {
598 &self.inner.name
599 }
600
601 pub fn call_index(&self) -> u8 {
603 self.inner.call_index
604 }
605
606 pub fn event_index(&self) -> u8 {
608 self.inner.event_index
609 }
610
611 pub fn error_index(&self) -> u8 {
613 self.inner.error_index
614 }
615
616 pub fn docs(&self) -> &'a [String] {
618 &self.inner.docs
619 }
620
621 pub fn call_ty_id(&self) -> Option<u32> {
623 self.inner.call_ty
624 }
625
626 pub fn event_ty_id(&self) -> Option<u32> {
628 self.inner.event_ty
629 }
630
631 pub fn error_ty_id(&self) -> Option<u32> {
633 self.inner.error_ty
634 }
635
636 pub fn storage(&self) -> Option<&'a StorageMetadata> {
638 self.inner.storage.as_ref()
639 }
640
641 pub fn event_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
643 VariantIndex::get(self.inner.event_ty, self.types)
644 }
645
646 pub fn event_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
648 self.inner.event_variant_index.lookup_by_index(
649 variant_index,
650 self.inner.event_ty,
651 self.types,
652 )
653 }
654
655 pub fn has_view_functions(&self) -> bool {
657 !self.inner.view_functions.is_empty()
658 }
659
660 pub fn view_functions(
662 &self,
663 ) -> impl ExactSizeIterator<Item = ViewFunctionMetadata<'a>> + use<'a> {
664 self.inner
665 .view_functions
666 .values()
667 .iter()
668 .map(|vf: &'a _| ViewFunctionMetadata {
669 inner: vf,
670 types: self.types,
671 })
672 }
673
674 pub fn view_function_by_name(&self, name: &str) -> Option<ViewFunctionMetadata<'a>> {
676 self.inner
677 .view_functions
678 .get_by_key(name)
679 .map(|vf: &'a _| ViewFunctionMetadata {
680 inner: vf,
681 types: self.types,
682 })
683 }
684
685 pub fn associated_types(&self) -> impl ExactSizeIterator<Item = (&'a str, u32)> + use<'a> {
687 self.inner
688 .associated_types
689 .iter()
690 .map(|(name, ty)| (&**name, *ty))
691 }
692
693 pub fn associated_type_id(&self, name: &str) -> Option<u32> {
695 self.inner.associated_types.get(name).copied()
696 }
697
698 pub fn call_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
700 VariantIndex::get(self.inner.call_ty, self.types)
701 }
702
703 pub fn call_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
705 self.inner
706 .call_variant_index
707 .lookup_by_index(variant_index, self.inner.call_ty, self.types)
708 }
709
710 pub fn call_variant_by_name(&self, call_name: &str) -> Option<&'a Variant<PortableForm>> {
712 self.inner
713 .call_variant_index
714 .lookup_by_name(call_name, self.inner.call_ty, self.types)
715 }
716
717 pub fn error_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
719 VariantIndex::get(self.inner.error_ty, self.types)
720 }
721
722 pub fn error_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
724 self.inner.error_variant_index.lookup_by_index(
725 variant_index,
726 self.inner.error_ty,
727 self.types,
728 )
729 }
730
731 pub fn constant_by_name(&self, name: &str) -> Option<&'a ConstantMetadata> {
733 self.inner.constants.get_by_key(name)
734 }
735
736 pub fn constants(&self) -> impl ExactSizeIterator<Item = &'a ConstantMetadata> + use<'a> {
738 self.inner.constants.values().iter()
739 }
740
741 pub fn storage_hash(&self, entry_name: &str) -> Option<[u8; HASH_LEN]> {
743 crate::utils::validation::get_storage_hash(self, entry_name)
744 }
745
746 pub fn constant_hash(&self, constant_name: &str) -> Option<[u8; HASH_LEN]> {
748 crate::utils::validation::get_constant_hash(self, constant_name)
749 }
750
751 pub fn call_hash(&self, call_name: &str) -> Option<[u8; HASH_LEN]> {
753 crate::utils::validation::get_call_hash(self, call_name)
754 }
755
756 pub fn hash(&self) -> [u8; HASH_LEN] {
758 crate::utils::validation::get_pallet_hash(*self)
759 }
760}
761
762#[derive(Debug, Clone)]
763struct PalletMetadataInner {
764 name: String,
766 call_index: u8,
768 event_index: u8,
773 error_index: u8,
778 storage: Option<StorageMetadata>,
780 call_ty: Option<u32>,
782 call_variant_index: VariantIndex,
784 event_ty: Option<u32>,
786 event_variant_index: VariantIndex,
788 error_ty: Option<u32>,
790 error_variant_index: VariantIndex,
792 constants: OrderedMap<String, ConstantMetadata>,
794 view_functions: OrderedMap<String, ViewFunctionMetadataInner>,
796 associated_types: BTreeMap<String, u32>,
798 docs: Vec<String>,
800}
801
802#[derive(Debug, Clone)]
804pub struct StorageMetadata {
805 prefix: String,
807 entries: OrderedMap<String, StorageEntryMetadata>,
809}
810
811impl StorageMetadata {
812 pub fn prefix(&self) -> &str {
814 &self.prefix
815 }
816
817 pub fn entries(&self) -> &[StorageEntryMetadata] {
819 self.entries.values()
820 }
821
822 pub fn entry_by_name(&self, name: &str) -> Option<&StorageEntryMetadata> {
824 self.entries.get_by_key(name)
825 }
826}
827
828#[derive(Debug, Clone)]
830pub struct StorageEntryMetadata {
831 name: String,
833 info: StorageInfo<'static, u32>,
835 docs: Vec<String>,
837}
838
839impl StorageEntryMetadata {
840 pub fn name(&self) -> &str {
842 &self.name
843 }
844 pub fn keys(&self) -> impl ExactSizeIterator<Item = &StorageKeyInfo<u32>> {
846 let keys = &*self.info.keys;
847 keys.iter()
848 }
849 pub fn value_ty(&self) -> u32 {
851 self.info.value_id
852 }
853 pub fn default_value(&self) -> Option<&[u8]> {
855 self.info.default_value.as_deref()
856 }
857 pub fn docs(&self) -> &[String] {
859 &self.docs
860 }
861}
862
863#[derive(Debug, Clone)]
865pub struct ConstantMetadata {
866 name: String,
868 ty: u32,
870 value: Vec<u8>,
872 docs: Vec<String>,
874}
875
876impl ConstantMetadata {
877 pub fn name(&self) -> &str {
879 &self.name
880 }
881 pub fn ty(&self) -> u32 {
883 self.ty
884 }
885 pub fn value(&self) -> &[u8] {
887 &self.value
888 }
889 pub fn docs(&self) -> &[String] {
891 &self.docs
892 }
893}
894
895#[derive(Debug, Clone)]
897pub struct ExtrinsicMetadata {
898 address_ty: u32,
901 signature_ty: u32,
904 supported_versions: Vec<u8>,
906 transaction_extensions: Vec<TransactionExtensionMetadataInner>,
908 transaction_extensions_by_version: BTreeMap<u8, Vec<u32>>,
912}
913
914impl ExtrinsicMetadata {
915 pub fn supported_versions(&self) -> &[u8] {
917 &self.supported_versions
918 }
919
920 pub fn transaction_extensions_by_version(
922 &self,
923 version: u8,
924 ) -> Option<impl Iterator<Item = TransactionExtensionMetadata<'_>>> {
925 let extension_indexes = self.transaction_extensions_by_version.get(&version)?;
926 let iter = extension_indexes.iter().map(|index| {
927 let tx_metadata = self
928 .transaction_extensions
929 .get(*index as usize)
930 .expect("transaction extension should exist if index is in transaction_extensions_by_version");
931
932 TransactionExtensionMetadata {
933 identifier: &tx_metadata.identifier,
934 extra_ty: tx_metadata.extra_ty,
935 additional_ty: tx_metadata.additional_ty,
936 }
937 });
938
939 Some(iter)
940 }
941
942 pub fn transaction_extension_version_to_use_for_encoding(&self) -> u8 {
944 *self
945 .transaction_extensions_by_version
946 .keys()
947 .max()
948 .expect("At least one version of transaction extensions is expected")
949 }
950
951 pub fn transaction_extensions_to_use_for_encoding(
954 &self,
955 ) -> impl Iterator<Item = TransactionExtensionMetadata<'_>> {
956 let encoding_version = self.transaction_extension_version_to_use_for_encoding();
957 self.transaction_extensions_by_version(encoding_version)
958 .unwrap()
959 }
960
961 pub fn transaction_extension_version_to_use_for_decoding(&self) -> u8 {
963 *self
964 .transaction_extensions_by_version
965 .keys()
966 .max()
967 .expect("At least one version of transaction extensions is expected")
968 }
969}
970
971#[derive(Debug, Clone)]
973pub struct TransactionExtensionMetadata<'a> {
974 identifier: &'a str,
976 extra_ty: u32,
978 additional_ty: u32,
980}
981
982#[derive(Debug, Clone)]
983struct TransactionExtensionMetadataInner {
984 identifier: String,
985 extra_ty: u32,
986 additional_ty: u32,
987}
988
989impl<'a> TransactionExtensionMetadata<'a> {
990 pub fn identifier(&self) -> &'a str {
992 self.identifier
993 }
994 pub fn extra_ty(&self) -> u32 {
996 self.extra_ty
997 }
998 pub fn additional_ty(&self) -> u32 {
1000 self.additional_ty
1001 }
1002}
1003
1004#[derive(Debug, Clone, Copy)]
1006pub struct OuterEnumsMetadata {
1007 call_enum_ty: u32,
1009 event_enum_ty: u32,
1011 error_enum_ty: u32,
1013}
1014
1015impl OuterEnumsMetadata {
1016 pub fn call_enum_ty(&self) -> u32 {
1018 self.call_enum_ty
1019 }
1020
1021 pub fn event_enum_ty(&self) -> u32 {
1023 self.event_enum_ty
1024 }
1025
1026 pub fn error_enum_ty(&self) -> u32 {
1028 self.error_enum_ty
1029 }
1030}
1031
1032#[derive(Debug, Clone, Copy)]
1034pub struct RuntimeApiMetadata<'a> {
1035 inner: &'a RuntimeApiMetadataInner,
1036 types: &'a PortableRegistry,
1037}
1038
1039impl<'a> RuntimeApiMetadata<'a> {
1040 pub fn name(&self) -> &'a str {
1042 &self.inner.name
1043 }
1044 pub fn docs(&self) -> &[String] {
1046 &self.inner.docs
1047 }
1048 pub fn methods(&self) -> impl ExactSizeIterator<Item = RuntimeApiMethodMetadata<'a>> + use<'a> {
1050 self.inner
1051 .methods
1052 .values()
1053 .iter()
1054 .map(|item| RuntimeApiMethodMetadata {
1055 trait_name: &self.inner.name,
1056 inner: item,
1057 types: self.types,
1058 })
1059 }
1060 pub fn method_by_name(&self, name: &str) -> Option<RuntimeApiMethodMetadata<'a>> {
1062 self.inner
1063 .methods
1064 .get_by_key(name)
1065 .map(|item| RuntimeApiMethodMetadata {
1066 trait_name: &self.inner.name,
1067 inner: item,
1068 types: self.types,
1069 })
1070 }
1071 pub fn hash(&self) -> [u8; HASH_LEN] {
1073 crate::utils::validation::get_runtime_apis_hash(*self)
1074 }
1075}
1076
1077#[derive(Debug, Clone)]
1078struct RuntimeApiMetadataInner {
1079 name: String,
1081 methods: OrderedMap<String, RuntimeApiMethodMetadataInner>,
1083 docs: Vec<String>,
1085}
1086
1087#[derive(Debug, Clone)]
1089pub struct RuntimeApiMethodMetadata<'a> {
1090 trait_name: &'a str,
1091 inner: &'a RuntimeApiMethodMetadataInner,
1092 types: &'a PortableRegistry,
1093}
1094
1095impl<'a> RuntimeApiMethodMetadata<'a> {
1096 pub fn name(&self) -> &'a str {
1098 &self.inner.name
1099 }
1100 pub fn docs(&self) -> &[String] {
1102 &self.inner.docs
1103 }
1104 pub fn inputs(
1106 &self,
1107 ) -> impl ExactSizeIterator<Item = &'a RuntimeApiInput<'static, u32>> + use<'a> {
1108 let inputs = &*self.inner.info.inputs;
1109 inputs.iter()
1110 }
1111 pub fn output_ty(&self) -> u32 {
1113 self.inner.info.output_id
1114 }
1115 pub fn hash(&self) -> [u8; HASH_LEN] {
1117 crate::utils::validation::get_runtime_api_hash(self)
1118 }
1119}
1120
1121#[derive(Debug, Clone)]
1122struct RuntimeApiMethodMetadataInner {
1123 name: String,
1125 info: RuntimeApiInfo<'static, u32>,
1127 docs: Vec<String>,
1129}
1130
1131#[derive(Debug, Clone, Copy)]
1134pub struct ViewFunctionMetadata<'a> {
1135 inner: &'a ViewFunctionMetadataInner,
1136 types: &'a PortableRegistry,
1137}
1138
1139impl<'a> ViewFunctionMetadata<'a> {
1140 pub fn name(&self) -> &'a str {
1142 &self.inner.name
1143 }
1144 pub fn query_id(&self) -> &'a [u8; 32] {
1147 &self.inner.info.query_id
1148 }
1149 pub fn docs(&self) -> &'a [String] {
1151 &self.inner.docs
1152 }
1153 pub fn inputs(
1155 &self,
1156 ) -> impl ExactSizeIterator<Item = &'a ViewFunctionInput<'static, u32>> + use<'a> {
1157 let inputs = &*self.inner.info.inputs;
1158 inputs.iter()
1159 }
1160 pub fn output_ty(&self) -> u32 {
1162 self.inner.info.output_id
1163 }
1164 pub fn hash(&self) -> [u8; HASH_LEN] {
1168 crate::utils::validation::get_view_function_hash(self)
1169 }
1170}
1171
1172#[derive(Debug, Clone)]
1173struct ViewFunctionMetadataInner {
1174 name: String,
1176 info: ViewFunctionInfo<'static, u32>,
1178 docs: Vec<String>,
1180}
1181
1182#[derive(Debug, Clone)]
1184pub struct MethodParamMetadata {
1185 pub name: String,
1187 pub ty: u32,
1189}
1190
1191#[derive(Debug, Clone)]
1193pub struct CustomMetadata<'a> {
1194 types: &'a PortableRegistry,
1195 inner: &'a CustomMetadataInner,
1196}
1197
1198impl<'a> CustomMetadata<'a> {
1199 pub fn get(&self, name: &str) -> Option<CustomValueMetadata<'a>> {
1201 self.inner
1202 .map
1203 .get_key_value(name)
1204 .map(|(name, e)| CustomValueMetadata {
1205 types: self.types,
1206 type_id: e.ty.id,
1207 data: &e.value,
1208 name,
1209 })
1210 }
1211
1212 pub fn iter(&self) -> impl Iterator<Item = CustomValueMetadata<'a>> + use<'a> {
1214 self.inner.map.iter().map(|(name, e)| CustomValueMetadata {
1215 types: self.types,
1216 type_id: e.ty.id,
1217 data: &e.value,
1218 name: name.as_ref(),
1219 })
1220 }
1221
1222 pub fn types(&self) -> &PortableRegistry {
1224 self.types
1225 }
1226}
1227
1228pub struct CustomValueMetadata<'a> {
1230 types: &'a PortableRegistry,
1231 type_id: u32,
1232 data: &'a [u8],
1233 name: &'a str,
1234}
1235
1236impl<'a> CustomValueMetadata<'a> {
1237 pub fn types(&self) -> &PortableRegistry {
1239 self.types
1240 }
1241
1242 pub fn bytes(&self) -> &'a [u8] {
1244 self.data
1245 }
1246
1247 pub fn type_id(&self) -> u32 {
1249 self.type_id
1250 }
1251
1252 pub fn name(&self) -> &str {
1254 self.name
1255 }
1256
1257 pub fn hash(&self) -> [u8; HASH_LEN] {
1259 get_custom_value_hash(self)
1260 }
1261}
1262
1263impl codec::Decode for Metadata {
1265 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
1266 let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(input)?;
1267 from_runtime_metadata(metadata.1)
1268 }
1269}
1270
1271pub fn decode_runtime_metadata(
1279 input: &[u8],
1280) -> Result<frame_metadata::RuntimeMetadata, codec::Error> {
1281 use codec::Decode;
1282
1283 let err = match frame_metadata::RuntimeMetadataPrefixed::decode(&mut &*input) {
1284 Ok(md) => return Ok(md.1),
1285 Err(e) => e,
1286 };
1287
1288 if let Ok(md) = frame_metadata::RuntimeMetadata::decode(&mut &*input) {
1289 return Ok(md);
1290 }
1291
1292 if let Ok(len) = codec::Compact::<u64>::decode(&mut &*input) {
1296 if input.len() == len.0 as usize {
1297 return decode_runtime_metadata(input);
1298 }
1299 }
1300
1301 Err(err)
1302}
1303
1304fn from_runtime_metadata(
1306 metadata: frame_metadata::RuntimeMetadata,
1307) -> Result<Metadata, codec::Error> {
1308 let metadata = match metadata {
1309 frame_metadata::RuntimeMetadata::V14(md) => md.try_into(),
1310 frame_metadata::RuntimeMetadata::V15(md) => md.try_into(),
1311 frame_metadata::RuntimeMetadata::V16(md) => md.try_into(),
1312 _ => {
1313 let reason = alloc::format!(
1314 "RuntimeMetadata version {} cannot be decoded from",
1315 metadata.version()
1316 );
1317 let e: codec::Error = "Metadata::decode failed: Cannot try_into() to Metadata: unsupported metadata version".into();
1318 return Err(e.chain(reason));
1319 }
1320 };
1321
1322 metadata.map_err(|reason: TryFromError| {
1323 let e: codec::Error = "Metadata::decode failed: Cannot try_into() to Metadata".into();
1324 e.chain(reason.to_string())
1325 })
1326}