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, ExtrinsicCallInfoArg, ExtrinsicExtensionInfo, ExtrinsicExtensionInfoArg,
34 ExtrinsicInfoError, 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_by_index(
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 call_index,
123 pallet_index,
124 pallet_name: Cow::Borrowed(pallet.name()),
125 call_name: Cow::Borrowed(&call.name),
126 args: call
127 .fields
128 .iter()
129 .map(|f| ExtrinsicCallInfoArg {
130 name: Cow::Borrowed(f.name.as_deref().unwrap_or("")),
131 id: f.ty.id,
132 })
133 .collect(),
134 })
135 }
136
137 fn extrinsic_call_info_by_name(
138 &self,
139 pallet_name: &str,
140 call_name: &str,
141 ) -> Result<ExtrinsicCallInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
142 let pallet = self.pallet_by_name(pallet_name).ok_or({
143 ExtrinsicInfoError::PalletNotFoundByName {
144 name: Cow::Owned(pallet_name.to_string()),
145 }
146 })?;
147
148 let call = pallet.call_variant_by_name(call_name).ok_or_else(|| {
149 ExtrinsicInfoError::CallNotFoundByName {
150 pallet_index: pallet.call_index(),
151 pallet_name: Cow::Borrowed(pallet.name()),
152 call_name: Cow::Owned(call_name.to_string()),
153 }
154 })?;
155
156 Ok(ExtrinsicCallInfo {
157 call_index: call.index,
158 pallet_index: pallet.call_index(),
159 pallet_name: Cow::Borrowed(pallet.name()),
160 call_name: Cow::Borrowed(&call.name),
161 args: call
162 .fields
163 .iter()
164 .map(|f| ExtrinsicCallInfoArg {
165 name: Cow::Borrowed(f.name.as_deref().unwrap_or("")),
166 id: f.ty.id,
167 })
168 .collect(),
169 })
170 }
171
172 fn extrinsic_signature_info(
173 &self,
174 ) -> Result<ExtrinsicSignatureInfo<Self::TypeId>, ExtrinsicInfoError<'_>> {
175 Ok(ExtrinsicSignatureInfo {
176 address_id: self.extrinsic().address_ty,
177 signature_id: self.extrinsic().signature_ty,
178 })
179 }
180
181 fn extrinsic_extension_version_info(
182 &self,
183 ) -> Result<impl Iterator<Item = u8>, ExtrinsicInfoError<'_>> {
184 Ok(self
185 .extrinsic
186 .transaction_extensions_by_version
187 .keys()
188 .copied())
189 }
190
191 fn extrinsic_extension_info(
192 &self,
193 extension_version: Option<u8>,
194 ) -> Result<ExtrinsicExtensionInfo<'_, Self::TypeId>, ExtrinsicInfoError<'_>> {
195 let extension_version = extension_version.unwrap_or_else(|| {
196 self.extrinsic()
200 .transaction_extension_version_to_use_for_decoding()
201 });
202
203 let extension_ids = self
204 .extrinsic()
205 .transaction_extensions_by_version(extension_version)
206 .ok_or(ExtrinsicInfoError::ExtrinsicExtensionVersionNotFound { extension_version })?
207 .map(|f| ExtrinsicExtensionInfoArg {
208 name: Cow::Borrowed(f.identifier()),
209 id: f.extra_ty(),
210 implicit_id: f.additional_ty(),
211 })
212 .collect();
213
214 Ok(ExtrinsicExtensionInfo { extension_ids })
215 }
216}
217impl frame_decode::storage::StorageTypeInfo for Metadata {
218 type TypeId = u32;
219
220 fn storage_info(
221 &self,
222 pallet_name: &str,
223 storage_entry: &str,
224 ) -> Result<StorageInfo<'_, Self::TypeId>, StorageInfoError<'_>> {
225 let pallet =
226 self.pallet_by_name(pallet_name)
227 .ok_or_else(|| StorageInfoError::PalletNotFound {
228 pallet_name: pallet_name.to_string(),
229 })?;
230 let entry = pallet
231 .storage()
232 .and_then(|storage| storage.entry_by_name(storage_entry))
233 .ok_or_else(|| StorageInfoError::StorageNotFound {
234 name: storage_entry.to_string(),
235 pallet_name: Cow::Borrowed(pallet.name()),
236 })?;
237
238 let info = StorageInfo {
239 keys: Cow::Borrowed(&*entry.info.keys),
240 value_id: entry.info.value_id,
241 default_value: entry
242 .info
243 .default_value
244 .as_ref()
245 .map(|def| Cow::Borrowed(&**def)),
246 use_old_v9_storage_hashers: false,
247 };
248
249 Ok(info)
250 }
251}
252impl frame_decode::storage::StorageEntryInfo for Metadata {
253 fn storage_entries(&self) -> impl Iterator<Item = StorageEntry<'_>> {
254 self.pallets().flat_map(|pallet| {
255 let pallet_name = pallet.name();
256 let pallet_iter = core::iter::once(StorageEntry::In(pallet_name.into()));
257 let entries_iter = pallet.storage().into_iter().flat_map(|storage| {
258 storage
259 .entries()
260 .iter()
261 .map(|entry| StorageEntry::Name(entry.name().into()))
262 });
263
264 pallet_iter.chain(entries_iter)
265 })
266 }
267}
268impl frame_decode::runtime_apis::RuntimeApiTypeInfo for Metadata {
269 type TypeId = u32;
270
271 fn runtime_api_info(
272 &self,
273 trait_name: &str,
274 method_name: &str,
275 ) -> Result<RuntimeApiInfo<'_, Self::TypeId>, RuntimeApiInfoError<'_>> {
276 let api_trait =
277 self.apis
278 .get_by_key(trait_name)
279 .ok_or_else(|| RuntimeApiInfoError::TraitNotFound {
280 trait_name: trait_name.to_string(),
281 })?;
282 let api_method = api_trait.methods.get_by_key(method_name).ok_or_else(|| {
283 RuntimeApiInfoError::MethodNotFound {
284 trait_name: Cow::Borrowed(&api_trait.name),
285 method_name: method_name.to_string(),
286 }
287 })?;
288
289 let info = RuntimeApiInfo {
290 inputs: Cow::Borrowed(&api_method.info.inputs),
291 output_id: api_method.info.output_id,
292 };
293
294 Ok(info)
295 }
296}
297impl frame_decode::runtime_apis::RuntimeApiEntryInfo for Metadata {
298 fn runtime_api_entries(&self) -> impl Iterator<Item = RuntimeApiEntry<'_>> {
299 self.runtime_api_traits().flat_map(|api_trait| {
300 let trait_name = api_trait.name();
301 let trait_iter = core::iter::once(RuntimeApiEntry::In(trait_name.into()));
302 let method_iter = api_trait
303 .methods()
304 .map(|method| RuntimeApiEntry::Name(method.name().into()));
305
306 trait_iter.chain(method_iter)
307 })
308 }
309}
310impl frame_decode::view_functions::ViewFunctionTypeInfo for Metadata {
311 type TypeId = u32;
312
313 fn view_function_info(
314 &self,
315 pallet_name: &str,
316 function_name: &str,
317 ) -> Result<ViewFunctionInfo<'_, Self::TypeId>, ViewFunctionInfoError<'_>> {
318 let pallet = self.pallet_by_name(pallet_name).ok_or_else(|| {
319 ViewFunctionInfoError::PalletNotFound {
320 pallet_name: pallet_name.to_string(),
321 }
322 })?;
323 let function = pallet.view_function_by_name(function_name).ok_or_else(|| {
324 ViewFunctionInfoError::FunctionNotFound {
325 pallet_name: Cow::Borrowed(pallet.name()),
326 function_name: function_name.to_string(),
327 }
328 })?;
329
330 let info = ViewFunctionInfo {
331 inputs: Cow::Borrowed(&function.inner.info.inputs),
332 output_id: function.inner.info.output_id,
333 query_id: *function.query_id(),
334 };
335
336 Ok(info)
337 }
338}
339impl frame_decode::view_functions::ViewFunctionEntryInfo for Metadata {
340 fn view_function_entries(&self) -> impl Iterator<Item = ViewFunctionEntry<'_>> {
341 self.pallets().flat_map(|pallet| {
342 let pallet_name = pallet.name();
343 let pallet_iter = core::iter::once(ViewFunctionEntry::In(pallet_name.into()));
344 let fn_iter = pallet
345 .view_functions()
346 .map(|function| ViewFunctionEntry::Name(function.name().into()));
347
348 pallet_iter.chain(fn_iter)
349 })
350 }
351}
352impl frame_decode::constants::ConstantTypeInfo for Metadata {
353 type TypeId = u32;
354
355 fn constant_info(
356 &self,
357 pallet_name: &str,
358 constant_name: &str,
359 ) -> Result<ConstantInfo<'_, Self::TypeId>, ConstantInfoError<'_>> {
360 let pallet =
361 self.pallet_by_name(pallet_name)
362 .ok_or_else(|| ConstantInfoError::PalletNotFound {
363 pallet_name: pallet_name.to_string(),
364 })?;
365 let constant = pallet.constant_by_name(constant_name).ok_or_else(|| {
366 ConstantInfoError::ConstantNotFound {
367 pallet_name: Cow::Borrowed(pallet.name()),
368 constant_name: constant_name.to_string(),
369 }
370 })?;
371
372 let info = ConstantInfo {
373 bytes: &constant.value,
374 type_id: constant.ty,
375 };
376
377 Ok(info)
378 }
379}
380impl frame_decode::constants::ConstantEntryInfo for Metadata {
381 fn constant_entries(&self) -> impl Iterator<Item = ConstantEntry<'_>> {
382 self.pallets().flat_map(|pallet| {
383 let pallet_name = pallet.name();
384 let pallet_iter = core::iter::once(ConstantEntry::In(pallet_name.into()));
385 let constant_iter = pallet
386 .constants()
387 .map(|constant| ConstantEntry::Name(constant.name().into()));
388
389 pallet_iter.chain(constant_iter)
390 })
391 }
392}
393impl frame_decode::custom_values::CustomValueTypeInfo for Metadata {
394 type TypeId = u32;
395
396 fn custom_value_info(
397 &self,
398 name: &str,
399 ) -> Result<CustomValueInfo<'_, Self::TypeId>, CustomValueInfoError> {
400 let custom_value = self
401 .custom()
402 .get(name)
403 .ok_or_else(|| CustomValueInfoError {
404 not_found: name.to_string(),
405 })?;
406
407 let info = CustomValueInfo {
408 bytes: custom_value.data,
409 type_id: custom_value.type_id,
410 };
411
412 Ok(info)
413 }
414}
415impl frame_decode::custom_values::CustomValueEntryInfo for Metadata {
416 fn custom_values(&self) -> impl Iterator<Item = CustomValue<'_>> {
417 self.custom.map.keys().map(|name| CustomValue {
418 name: Cow::Borrowed(name),
419 })
420 }
421}
422
423impl Metadata {
424 pub fn arc(self) -> ArcMetadata {
427 Arc::new(self)
428 }
429
430 pub fn decode_from(bytes: &[u8]) -> Result<Self, codec::Error> {
438 let metadata = decode_runtime_metadata(bytes)?;
439 from_runtime_metadata(metadata)
440 }
441
442 pub fn from_v16(
444 metadata: frame_metadata::v16::RuntimeMetadataV16,
445 ) -> Result<Self, TryFromError> {
446 metadata.try_into()
447 }
448
449 pub fn from_v15(
451 metadata: frame_metadata::v15::RuntimeMetadataV15,
452 ) -> Result<Self, TryFromError> {
453 metadata.try_into()
454 }
455
456 pub fn from_v14(
458 metadata: frame_metadata::v14::RuntimeMetadataV14,
459 ) -> Result<Self, TryFromError> {
460 metadata.try_into()
461 }
462
463 #[cfg(feature = "legacy")]
465 pub fn from_v13(
466 metadata: &frame_metadata::v13::RuntimeMetadataV13,
467 types: &scale_info_legacy::TypeRegistrySet<'_>,
468 ) -> Result<Self, LegacyFromError> {
469 from::legacy::from_v13(metadata, types, from::legacy::Opts::compat())
470 }
471
472 #[cfg(feature = "legacy")]
474 pub fn from_v12(
475 metadata: &frame_metadata::v12::RuntimeMetadataV12,
476 types: &scale_info_legacy::TypeRegistrySet<'_>,
477 ) -> Result<Self, LegacyFromError> {
478 from::legacy::from_v12(metadata, types, from::legacy::Opts::compat())
479 }
480
481 #[cfg(feature = "legacy")]
483 pub fn from_v11(
484 metadata: &frame_metadata::v11::RuntimeMetadataV11,
485 types: &scale_info_legacy::TypeRegistrySet<'_>,
486 ) -> Result<Self, LegacyFromError> {
487 from::legacy::from_v11(metadata, types, from::legacy::Opts::compat())
488 }
489
490 #[cfg(feature = "legacy")]
492 pub fn from_v10(
493 metadata: &frame_metadata::v10::RuntimeMetadataV10,
494 types: &scale_info_legacy::TypeRegistrySet<'_>,
495 ) -> Result<Self, LegacyFromError> {
496 from::legacy::from_v10(metadata, types, from::legacy::Opts::compat())
497 }
498
499 #[cfg(feature = "legacy")]
501 pub fn from_v9(
502 metadata: &frame_metadata::v9::RuntimeMetadataV9,
503 types: &scale_info_legacy::TypeRegistrySet<'_>,
504 ) -> Result<Self, LegacyFromError> {
505 from::legacy::from_v9(metadata, types, from::legacy::Opts::compat())
506 }
507
508 #[cfg(feature = "legacy")]
510 pub fn from_v8(
511 metadata: &frame_metadata::v8::RuntimeMetadataV8,
512 types: &scale_info_legacy::TypeRegistrySet<'_>,
513 ) -> Result<Self, LegacyFromError> {
514 from::legacy::from_v8(metadata, types, from::legacy::Opts::compat())
515 }
516
517 pub fn types(&self) -> &PortableRegistry {
519 &self.types
520 }
521
522 pub fn types_mut(&mut self) -> &mut PortableRegistry {
524 &mut self.types
525 }
526
527 pub fn dispatch_error_ty(&self) -> Option<u32> {
529 self.dispatch_error_ty
530 }
531
532 pub fn extrinsic(&self) -> &ExtrinsicMetadata {
534 &self.extrinsic
535 }
536
537 pub fn outer_enums(&self) -> OuterEnumsMetadata {
539 self.outer_enums
540 }
541
542 pub fn pallets(&self) -> impl ExactSizeIterator<Item = PalletMetadata<'_>> {
544 self.pallets.values().iter().map(|inner| PalletMetadata {
545 inner,
546 types: self.types(),
547 })
548 }
549
550 pub fn pallet_by_call_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
552 let inner = self
553 .pallets_by_call_index
554 .get(&variant_index)
555 .and_then(|i| self.pallets.get_by_index(*i))?;
556
557 Some(PalletMetadata {
558 inner,
559 types: self.types(),
560 })
561 }
562
563 pub fn pallet_by_event_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
565 let inner = self
566 .pallets_by_event_index
567 .get(&variant_index)
568 .and_then(|i| self.pallets.get_by_index(*i))?;
569
570 Some(PalletMetadata {
571 inner,
572 types: self.types(),
573 })
574 }
575
576 pub fn pallet_by_error_index(&self, variant_index: u8) -> Option<PalletMetadata<'_>> {
578 let inner = self
579 .pallets_by_error_index
580 .get(&variant_index)
581 .and_then(|i| self.pallets.get_by_index(*i))?;
582
583 Some(PalletMetadata {
584 inner,
585 types: self.types(),
586 })
587 }
588
589 pub fn pallet_by_name(&self, pallet_name: &str) -> Option<PalletMetadata<'_>> {
591 let inner = self.pallets.get_by_key(pallet_name)?;
592
593 Some(PalletMetadata {
594 inner,
595 types: self.types(),
596 })
597 }
598
599 pub fn runtime_api_traits(&self) -> impl ExactSizeIterator<Item = RuntimeApiMetadata<'_>> {
601 self.apis.values().iter().map(|inner| RuntimeApiMetadata {
602 inner,
603 types: self.types(),
604 })
605 }
606
607 pub fn runtime_api_trait_by_name(&'_ self, name: &str) -> Option<RuntimeApiMetadata<'_>> {
609 let inner = self.apis.get_by_key(name)?;
610 Some(RuntimeApiMetadata {
611 inner,
612 types: self.types(),
613 })
614 }
615
616 pub fn custom(&self) -> CustomMetadata<'_> {
618 CustomMetadata {
619 types: self.types(),
620 inner: &self.custom,
621 }
622 }
623
624 pub fn hasher(&self) -> MetadataHasher<'_> {
626 MetadataHasher::new(self)
627 }
628
629 pub fn type_hash(&self, id: u32) -> Option<[u8; HASH_LEN]> {
631 self.types.resolve(id)?;
632 Some(crate::utils::validation::get_type_hash(&self.types, id))
633 }
634}
635
636#[derive(Debug, Clone, Copy)]
638pub struct PalletMetadata<'a> {
639 inner: &'a PalletMetadataInner,
640 types: &'a PortableRegistry,
641}
642
643impl<'a> PalletMetadata<'a> {
644 pub fn name(&self) -> &'a str {
646 &self.inner.name
647 }
648
649 pub fn call_index(&self) -> u8 {
651 self.inner.call_index
652 }
653
654 pub fn event_index(&self) -> u8 {
656 self.inner.event_index
657 }
658
659 pub fn error_index(&self) -> u8 {
661 self.inner.error_index
662 }
663
664 pub fn docs(&self) -> &'a [String] {
666 &self.inner.docs
667 }
668
669 pub fn call_ty_id(&self) -> Option<u32> {
671 self.inner.call_ty
672 }
673
674 pub fn event_ty_id(&self) -> Option<u32> {
676 self.inner.event_ty
677 }
678
679 pub fn error_ty_id(&self) -> Option<u32> {
681 self.inner.error_ty
682 }
683
684 pub fn storage(&self) -> Option<&'a StorageMetadata> {
686 self.inner.storage.as_ref()
687 }
688
689 pub fn event_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
691 VariantIndex::get(self.inner.event_ty, self.types)
692 }
693
694 pub fn event_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
696 self.inner.event_variant_index.lookup_by_index(
697 variant_index,
698 self.inner.event_ty,
699 self.types,
700 )
701 }
702
703 pub fn has_view_functions(&self) -> bool {
705 !self.inner.view_functions.is_empty()
706 }
707
708 pub fn view_functions(
710 &self,
711 ) -> impl ExactSizeIterator<Item = ViewFunctionMetadata<'a>> + use<'a> {
712 self.inner
713 .view_functions
714 .values()
715 .iter()
716 .map(|vf: &'a _| ViewFunctionMetadata {
717 inner: vf,
718 types: self.types,
719 })
720 }
721
722 pub fn view_function_by_name(&self, name: &str) -> Option<ViewFunctionMetadata<'a>> {
724 self.inner
725 .view_functions
726 .get_by_key(name)
727 .map(|vf: &'a _| ViewFunctionMetadata {
728 inner: vf,
729 types: self.types,
730 })
731 }
732
733 pub fn associated_types(&self) -> impl ExactSizeIterator<Item = (&'a str, u32)> + use<'a> {
735 self.inner
736 .associated_types
737 .iter()
738 .map(|(name, ty)| (&**name, *ty))
739 }
740
741 pub fn associated_type_id(&self, name: &str) -> Option<u32> {
743 self.inner.associated_types.get(name).copied()
744 }
745
746 pub fn call_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
748 VariantIndex::get(self.inner.call_ty, self.types)
749 }
750
751 pub fn call_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
753 self.inner
754 .call_variant_index
755 .lookup_by_index(variant_index, self.inner.call_ty, self.types)
756 }
757
758 pub fn call_variant_by_name(&self, call_name: &str) -> Option<&'a Variant<PortableForm>> {
760 self.inner
761 .call_variant_index
762 .lookup_by_name(call_name, self.inner.call_ty, self.types)
763 }
764
765 pub fn error_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
767 VariantIndex::get(self.inner.error_ty, self.types)
768 }
769
770 pub fn error_variant_by_index(&self, variant_index: u8) -> Option<&'a Variant<PortableForm>> {
772 self.inner.error_variant_index.lookup_by_index(
773 variant_index,
774 self.inner.error_ty,
775 self.types,
776 )
777 }
778
779 pub fn constant_by_name(&self, name: &str) -> Option<&'a ConstantMetadata> {
781 self.inner.constants.get_by_key(name)
782 }
783
784 pub fn constants(&self) -> impl ExactSizeIterator<Item = &'a ConstantMetadata> + use<'a> {
786 self.inner.constants.values().iter()
787 }
788
789 pub fn storage_hash(&self, entry_name: &str) -> Option<[u8; HASH_LEN]> {
791 crate::utils::validation::get_storage_hash(self, entry_name)
792 }
793
794 pub fn constant_hash(&self, constant_name: &str) -> Option<[u8; HASH_LEN]> {
796 crate::utils::validation::get_constant_hash(self, constant_name)
797 }
798
799 pub fn call_hash(&self, call_name: &str) -> Option<[u8; HASH_LEN]> {
801 crate::utils::validation::get_call_hash(self, call_name)
802 }
803
804 pub fn hash(&self) -> [u8; HASH_LEN] {
806 crate::utils::validation::get_pallet_hash(*self)
807 }
808}
809
810#[derive(Debug, Clone)]
811struct PalletMetadataInner {
812 name: String,
814 call_index: u8,
816 event_index: u8,
821 error_index: u8,
826 storage: Option<StorageMetadata>,
828 call_ty: Option<u32>,
830 call_variant_index: VariantIndex,
832 event_ty: Option<u32>,
834 event_variant_index: VariantIndex,
836 error_ty: Option<u32>,
838 error_variant_index: VariantIndex,
840 constants: OrderedMap<String, ConstantMetadata>,
842 view_functions: OrderedMap<String, ViewFunctionMetadataInner>,
844 associated_types: BTreeMap<String, u32>,
846 docs: Vec<String>,
848}
849
850#[derive(Debug, Clone)]
852pub struct StorageMetadata {
853 prefix: String,
855 entries: OrderedMap<String, StorageEntryMetadata>,
857}
858
859impl StorageMetadata {
860 pub fn prefix(&self) -> &str {
862 &self.prefix
863 }
864
865 pub fn entries(&self) -> &[StorageEntryMetadata] {
867 self.entries.values()
868 }
869
870 pub fn entry_by_name(&self, name: &str) -> Option<&StorageEntryMetadata> {
872 self.entries.get_by_key(name)
873 }
874}
875
876#[derive(Debug, Clone)]
878pub struct StorageEntryMetadata {
879 name: String,
881 info: StorageInfo<'static, u32>,
883 docs: Vec<String>,
885}
886
887impl StorageEntryMetadata {
888 pub fn name(&self) -> &str {
890 &self.name
891 }
892 pub fn keys(&self) -> impl ExactSizeIterator<Item = &StorageKeyInfo<u32>> {
894 let keys = &*self.info.keys;
895 keys.iter()
896 }
897 pub fn value_ty(&self) -> u32 {
899 self.info.value_id
900 }
901 pub fn default_value(&self) -> Option<&[u8]> {
903 self.info.default_value.as_deref()
904 }
905 pub fn docs(&self) -> &[String] {
907 &self.docs
908 }
909}
910
911#[derive(Debug, Clone)]
913pub struct ConstantMetadata {
914 name: String,
916 ty: u32,
918 value: Vec<u8>,
920 docs: Vec<String>,
922}
923
924impl ConstantMetadata {
925 pub fn name(&self) -> &str {
927 &self.name
928 }
929 pub fn ty(&self) -> u32 {
931 self.ty
932 }
933 pub fn value(&self) -> &[u8] {
935 &self.value
936 }
937 pub fn docs(&self) -> &[String] {
939 &self.docs
940 }
941}
942
943#[derive(Debug, Clone)]
945pub struct ExtrinsicMetadata {
946 address_ty: u32,
949 signature_ty: u32,
952 supported_versions: Vec<u8>,
954 transaction_extensions: Vec<TransactionExtensionMetadataInner>,
956 transaction_extensions_by_version: BTreeMap<u8, Vec<u32>>,
960}
961
962impl ExtrinsicMetadata {
963 pub fn supported_versions(&self) -> &[u8] {
965 &self.supported_versions
966 }
967
968 pub fn transaction_extensions_by_version(
970 &self,
971 version: u8,
972 ) -> Option<impl Iterator<Item = TransactionExtensionMetadata<'_>>> {
973 let extension_indexes = self.transaction_extensions_by_version.get(&version)?;
974 let iter = extension_indexes.iter().map(|index| {
975 let tx_metadata = self
976 .transaction_extensions
977 .get(*index as usize)
978 .expect("transaction extension should exist if index is in transaction_extensions_by_version");
979
980 TransactionExtensionMetadata {
981 identifier: &tx_metadata.identifier,
982 extra_ty: tx_metadata.extra_ty,
983 additional_ty: tx_metadata.additional_ty,
984 }
985 });
986
987 Some(iter)
988 }
989
990 pub fn transaction_extension_version_to_use_for_encoding(&self) -> u8 {
992 *self
993 .transaction_extensions_by_version
994 .keys()
995 .max()
996 .expect("At least one version of transaction extensions is expected")
997 }
998
999 pub fn transaction_extensions_to_use_for_encoding(
1002 &self,
1003 ) -> impl Iterator<Item = TransactionExtensionMetadata<'_>> {
1004 let encoding_version = self.transaction_extension_version_to_use_for_encoding();
1005 self.transaction_extensions_by_version(encoding_version)
1006 .unwrap()
1007 }
1008
1009 pub fn transaction_extension_version_to_use_for_decoding(&self) -> u8 {
1011 *self
1012 .transaction_extensions_by_version
1013 .keys()
1014 .max()
1015 .expect("At least one version of transaction extensions is expected")
1016 }
1017}
1018
1019#[derive(Debug, Clone)]
1021pub struct TransactionExtensionMetadata<'a> {
1022 identifier: &'a str,
1024 extra_ty: u32,
1026 additional_ty: u32,
1028}
1029
1030#[derive(Debug, Clone)]
1031struct TransactionExtensionMetadataInner {
1032 identifier: String,
1033 extra_ty: u32,
1034 additional_ty: u32,
1035}
1036
1037impl<'a> TransactionExtensionMetadata<'a> {
1038 pub fn identifier(&self) -> &'a str {
1040 self.identifier
1041 }
1042 pub fn extra_ty(&self) -> u32 {
1044 self.extra_ty
1045 }
1046 pub fn additional_ty(&self) -> u32 {
1048 self.additional_ty
1049 }
1050}
1051
1052#[derive(Debug, Clone, Copy)]
1054pub struct OuterEnumsMetadata {
1055 call_enum_ty: u32,
1057 event_enum_ty: u32,
1059 error_enum_ty: u32,
1061}
1062
1063impl OuterEnumsMetadata {
1064 pub fn call_enum_ty(&self) -> u32 {
1066 self.call_enum_ty
1067 }
1068
1069 pub fn event_enum_ty(&self) -> u32 {
1071 self.event_enum_ty
1072 }
1073
1074 pub fn error_enum_ty(&self) -> u32 {
1076 self.error_enum_ty
1077 }
1078}
1079
1080#[derive(Debug, Clone, Copy)]
1082pub struct RuntimeApiMetadata<'a> {
1083 inner: &'a RuntimeApiMetadataInner,
1084 types: &'a PortableRegistry,
1085}
1086
1087impl<'a> RuntimeApiMetadata<'a> {
1088 pub fn name(&self) -> &'a str {
1090 &self.inner.name
1091 }
1092 pub fn docs(&self) -> &[String] {
1094 &self.inner.docs
1095 }
1096 pub fn methods(&self) -> impl ExactSizeIterator<Item = RuntimeApiMethodMetadata<'a>> + use<'a> {
1098 self.inner
1099 .methods
1100 .values()
1101 .iter()
1102 .map(|item| RuntimeApiMethodMetadata {
1103 trait_name: &self.inner.name,
1104 inner: item,
1105 types: self.types,
1106 })
1107 }
1108 pub fn method_by_name(&self, name: &str) -> Option<RuntimeApiMethodMetadata<'a>> {
1110 self.inner
1111 .methods
1112 .get_by_key(name)
1113 .map(|item| RuntimeApiMethodMetadata {
1114 trait_name: &self.inner.name,
1115 inner: item,
1116 types: self.types,
1117 })
1118 }
1119 pub fn hash(&self) -> [u8; HASH_LEN] {
1121 crate::utils::validation::get_runtime_apis_hash(*self)
1122 }
1123}
1124
1125#[derive(Debug, Clone)]
1126struct RuntimeApiMetadataInner {
1127 name: String,
1129 methods: OrderedMap<String, RuntimeApiMethodMetadataInner>,
1131 docs: Vec<String>,
1133}
1134
1135#[derive(Debug, Clone)]
1137pub struct RuntimeApiMethodMetadata<'a> {
1138 trait_name: &'a str,
1139 inner: &'a RuntimeApiMethodMetadataInner,
1140 types: &'a PortableRegistry,
1141}
1142
1143impl<'a> RuntimeApiMethodMetadata<'a> {
1144 pub fn name(&self) -> &'a str {
1146 &self.inner.name
1147 }
1148 pub fn docs(&self) -> &[String] {
1150 &self.inner.docs
1151 }
1152 pub fn inputs(
1154 &self,
1155 ) -> impl ExactSizeIterator<Item = &'a RuntimeApiInput<'static, u32>> + use<'a> {
1156 let inputs = &*self.inner.info.inputs;
1157 inputs.iter()
1158 }
1159 pub fn output_ty(&self) -> u32 {
1161 self.inner.info.output_id
1162 }
1163 pub fn hash(&self) -> [u8; HASH_LEN] {
1165 crate::utils::validation::get_runtime_api_hash(self)
1166 }
1167}
1168
1169#[derive(Debug, Clone)]
1170struct RuntimeApiMethodMetadataInner {
1171 name: String,
1173 info: RuntimeApiInfo<'static, u32>,
1175 docs: Vec<String>,
1177}
1178
1179#[derive(Debug, Clone, Copy)]
1182pub struct ViewFunctionMetadata<'a> {
1183 inner: &'a ViewFunctionMetadataInner,
1184 types: &'a PortableRegistry,
1185}
1186
1187impl<'a> ViewFunctionMetadata<'a> {
1188 pub fn name(&self) -> &'a str {
1190 &self.inner.name
1191 }
1192 pub fn query_id(&self) -> &'a [u8; 32] {
1195 &self.inner.info.query_id
1196 }
1197 pub fn docs(&self) -> &'a [String] {
1199 &self.inner.docs
1200 }
1201 pub fn inputs(
1203 &self,
1204 ) -> impl ExactSizeIterator<Item = &'a ViewFunctionInput<'static, u32>> + use<'a> {
1205 let inputs = &*self.inner.info.inputs;
1206 inputs.iter()
1207 }
1208 pub fn output_ty(&self) -> u32 {
1210 self.inner.info.output_id
1211 }
1212 pub fn hash(&self) -> [u8; HASH_LEN] {
1216 crate::utils::validation::get_view_function_hash(self)
1217 }
1218}
1219
1220#[derive(Debug, Clone)]
1221struct ViewFunctionMetadataInner {
1222 name: String,
1224 info: ViewFunctionInfo<'static, u32>,
1226 docs: Vec<String>,
1228}
1229
1230#[derive(Debug, Clone)]
1232pub struct MethodParamMetadata {
1233 pub name: String,
1235 pub ty: u32,
1237}
1238
1239#[derive(Debug, Clone)]
1241pub struct CustomMetadata<'a> {
1242 types: &'a PortableRegistry,
1243 inner: &'a CustomMetadataInner,
1244}
1245
1246impl<'a> CustomMetadata<'a> {
1247 pub fn get(&self, name: &str) -> Option<CustomValueMetadata<'a>> {
1249 self.inner
1250 .map
1251 .get_key_value(name)
1252 .map(|(name, e)| CustomValueMetadata {
1253 types: self.types,
1254 type_id: e.ty.id,
1255 data: &e.value,
1256 name,
1257 })
1258 }
1259
1260 pub fn iter(&self) -> impl Iterator<Item = CustomValueMetadata<'a>> + use<'a> {
1262 self.inner.map.iter().map(|(name, e)| CustomValueMetadata {
1263 types: self.types,
1264 type_id: e.ty.id,
1265 data: &e.value,
1266 name: name.as_ref(),
1267 })
1268 }
1269
1270 pub fn types(&self) -> &PortableRegistry {
1272 self.types
1273 }
1274}
1275
1276pub struct CustomValueMetadata<'a> {
1278 types: &'a PortableRegistry,
1279 type_id: u32,
1280 data: &'a [u8],
1281 name: &'a str,
1282}
1283
1284impl<'a> CustomValueMetadata<'a> {
1285 pub fn types(&self) -> &PortableRegistry {
1287 self.types
1288 }
1289
1290 pub fn bytes(&self) -> &'a [u8] {
1292 self.data
1293 }
1294
1295 pub fn type_id(&self) -> u32 {
1297 self.type_id
1298 }
1299
1300 pub fn name(&self) -> &str {
1302 self.name
1303 }
1304
1305 pub fn hash(&self) -> [u8; HASH_LEN] {
1307 get_custom_value_hash(self)
1308 }
1309}
1310
1311impl codec::Decode for Metadata {
1313 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
1314 let metadata = frame_metadata::RuntimeMetadataPrefixed::decode(input)?;
1315 from_runtime_metadata(metadata.1)
1316 }
1317}
1318
1319pub fn decode_runtime_metadata(
1327 input: &[u8],
1328) -> Result<frame_metadata::RuntimeMetadata, codec::Error> {
1329 use codec::Decode;
1330
1331 let err = match frame_metadata::RuntimeMetadataPrefixed::decode(&mut &*input) {
1332 Ok(md) => return Ok(md.1),
1333 Err(e) => e,
1334 };
1335
1336 if let Ok(md) = frame_metadata::RuntimeMetadata::decode(&mut &*input) {
1337 return Ok(md);
1338 }
1339
1340 if let Ok(len) = codec::Compact::<u64>::decode(&mut &*input) {
1344 if input.len() == len.0 as usize {
1345 return decode_runtime_metadata(input);
1346 }
1347 }
1348
1349 Err(err)
1350}
1351
1352fn from_runtime_metadata(
1354 metadata: frame_metadata::RuntimeMetadata,
1355) -> Result<Metadata, codec::Error> {
1356 let metadata = match metadata {
1357 frame_metadata::RuntimeMetadata::V14(md) => md.try_into(),
1358 frame_metadata::RuntimeMetadata::V15(md) => md.try_into(),
1359 frame_metadata::RuntimeMetadata::V16(md) => md.try_into(),
1360 _ => {
1361 let reason = alloc::format!(
1362 "RuntimeMetadata version {} cannot be decoded from",
1363 metadata.version()
1364 );
1365 let e: codec::Error = "Metadata::decode failed: Cannot try_into() to Metadata: unsupported metadata version".into();
1366 return Err(e.chain(reason));
1367 }
1368 };
1369
1370 metadata.map_err(|reason: TryFromError| {
1371 let e: codec::Error = "Metadata::decode failed: Cannot try_into() to Metadata".into();
1372 e.chain(reason.to_string())
1373 })
1374}