polymesh_api_client/
metadata.rs

1#[cfg(not(feature = "std"))]
2use alloc::collections::btree_map::BTreeMap;
3#[cfg(feature = "std")]
4use std::collections::BTreeMap;
5
6#[cfg(any(feature = "v13", feature = "v12",))]
7use frame_metadata::decode_different::{DecodeDifferent, DecodeDifferentArray};
8
9#[cfg(feature = "v14")]
10use scale_info::form::PortableForm;
11
12use codec::{Decode, Encode};
13
14#[cfg(not(feature = "std"))]
15use alloc::{
16  format,
17  string::{String, ToString},
18};
19use sp_std::prelude::*;
20
21mod storage;
22pub use storage::*;
23
24use crate::error::*;
25use crate::schema::*;
26use crate::type_def::*;
27use crate::*;
28
29#[cfg(any(feature = "v13", feature = "v12",))]
30pub(crate) fn decode_meta<B: Encode + 'static, O: Decode + Clone + 'static>(
31  encoded: &DecodeDifferent<B, O>,
32) -> Result<O> {
33  match encoded {
34    DecodeDifferent::Decoded(val) => Ok(val.clone()),
35    DecodeDifferent::Encode(val) => {
36      let encoded = val.encode();
37      O::decode(&mut &encoded[..])
38        .map_err(|_| Error::MetadataParseFailed(format!("Failed to decode value.")))
39    }
40  }
41}
42
43#[derive(Clone)]
44pub struct Metadata {
45  modules: BTreeMap<String, ModuleMetadata>,
46  idx_map: BTreeMap<u8, String>,
47}
48
49impl Metadata {
50  #[cfg(feature = "v12")]
51  pub fn from_v12_metadata(
52    md: frame_metadata::v12::RuntimeMetadataV12,
53    lookup: &mut Types,
54  ) -> Result<Self> {
55    let mut api_md = Self {
56      modules: BTreeMap::new(),
57      idx_map: BTreeMap::new(),
58    };
59
60    // Top-level event/error/call types.
61    let mut mod_events = TypeDefVariant::new();
62    let mut mod_errors = TypeDefVariant::new();
63    let mut mod_calls = TypeDefVariant::new();
64
65    // Decode module metadata.
66    decode_meta(&md.modules)?
67      .iter()
68      .try_for_each(|m| -> Result<()> {
69        let m = ModuleMetadata::from_v12_meta(m, lookup)?;
70        let name = m.name.clone();
71        mod_events.insert(m.index, &name, m.event_ref.clone());
72        mod_errors.insert(m.index, &name, m.error_ref.clone());
73        mod_calls.insert(m.index, &name, m.call_ref.clone());
74        api_md.idx_map.insert(m.index, name.clone());
75        api_md.modules.insert(name, m);
76        Ok(())
77      })?;
78
79    let raw_event_ref = lookup.insert_type("RawEvent", TypeDef::Variant(mod_events));
80    lookup.insert_new_type("Event", raw_event_ref);
81    let raw_error_ref = lookup.insert_type("RawError", TypeDef::Variant(mod_errors));
82    lookup.insert_new_type("DispatchErrorModule", raw_error_ref);
83    // Define 'RuntimeCall' type.
84    lookup.insert_type("RuntimeCall", TypeDef::Variant(mod_calls));
85
86    Ok(api_md)
87  }
88
89  #[cfg(feature = "v13")]
90  pub fn from_v13_metadata(
91    md: frame_metadata::v13::RuntimeMetadataV13,
92    lookup: &mut Types,
93  ) -> Result<Self> {
94    let mut api_md = Self {
95      modules: BTreeMap::new(),
96      idx_map: BTreeMap::new(),
97    };
98
99    // Top-level event/error/call types.
100    let mut mod_events = TypeDefVariant::new();
101    let mut mod_errors = TypeDefVariant::new();
102    let mut mod_calls = TypeDefVariant::new();
103
104    // Decode module metadata.
105    decode_meta(&md.modules)?
106      .iter()
107      .try_for_each(|m| -> Result<()> {
108        let m = ModuleMetadata::from_v13_meta(m, lookup)?;
109        let name = m.name.clone();
110        mod_events.insert(m.index, &name, m.event_ref.clone());
111        mod_errors.insert(m.index, &name, m.error_ref.clone());
112        mod_calls.insert(m.index, &name, m.call_ref.clone());
113        api_md.idx_map.insert(m.index, name.clone());
114        api_md.modules.insert(name, m);
115        Ok(())
116      })?;
117
118    let raw_event_ref = lookup.insert_type("RawEvent", TypeDef::Variant(mod_events));
119    lookup.insert_new_type("Event", raw_event_ref);
120    let raw_error_ref = lookup.insert_type("RawError", TypeDef::Variant(mod_errors));
121    lookup.insert_new_type("DispatchErrorModule", raw_error_ref);
122    // Define 'RuntimeCall' type.
123    lookup.insert_type("RuntimeCall", TypeDef::Variant(mod_calls));
124
125    Ok(api_md)
126  }
127
128  #[cfg(feature = "v14")]
129  pub fn from_v14_metadata(
130    md: frame_metadata::v14::RuntimeMetadataV14,
131    lookup: &mut Types,
132  ) -> Result<Self> {
133    let mut api_md = Self {
134      modules: BTreeMap::new(),
135      idx_map: BTreeMap::new(),
136    };
137
138    let types = PortableRegistry::from(&md.types);
139
140    // Import types from registry.
141    lookup.import_v14_types(&types)?;
142
143    // Top-level event/error/call types.
144    let mut mod_events = TypeDefVariant::new();
145    let mut mod_errors = TypeDefVariant::new();
146    let mut mod_calls = TypeDefVariant::new();
147
148    // Decode module metadata.
149    md.pallets.iter().try_for_each(|m| -> Result<()> {
150      let m = ModuleMetadata::from_v14_meta(m, &types)?;
151      let name = m.name.clone();
152      mod_events.insert(m.index, &name, m.event_ref.clone());
153      mod_errors.insert(m.index, &name, m.error_ref.clone());
154      mod_calls.insert(m.index, &name, m.call_ref.clone());
155      api_md.idx_map.insert(m.index, name.clone());
156      api_md.modules.insert(name, m);
157      Ok(())
158    })?;
159
160    let event_ty = lookup.insert_type("RuntimeEvent", TypeDef::Variant(mod_events));
161    lookup.insert_type("RuntimeError", TypeDef::Variant(mod_errors));
162    lookup.insert_type("RuntimeCall", TypeDef::Variant(mod_calls));
163
164    // Build `EventRecords` type.
165    lookup.parse_named_type("H256", "[u8; 32]")?;
166    let phase_ty = lookup.resolve("frame_system::Phase").id;
167    let topics_ty = lookup.parse_type("Vec<H256>")?;
168
169    lookup.insert_type(
170      "EventRecord",
171      TypeDefComposite::new(vec![
172        Field::new_named("phase", phase_ty, None),
173        Field::new_named("event", event_ty, None),
174        Field::new_named("topics", topics_ty, None),
175      ])
176      .into(),
177    );
178    lookup.parse_named_type("EventRecords", "Vec<EventRecord>")?;
179
180    Ok(api_md)
181  }
182
183  pub fn get_module(&self, name: &str) -> Option<&ModuleMetadata> {
184    self.modules.get(name)
185  }
186
187  pub fn modules(&self) -> impl Iterator<Item = &ModuleMetadata> {
188    self.modules.values()
189  }
190}
191
192#[derive(Clone)]
193pub struct ModuleMetadata {
194  pub name: String,
195  pub index: u8,
196  pub funcs: BTreeMap<String, FuncMetadata>,
197  pub events: BTreeMap<String, EventMetadata>,
198  pub errors: BTreeMap<String, ErrorMetadata>,
199  pub err_idx_map: BTreeMap<u8, String>,
200  pub event_ref: Option<TypeId>,
201  pub error_ref: Option<TypeId>,
202  pub call_ref: Option<TypeId>,
203  pub storage: Option<StorageMetadata>,
204}
205
206impl ModuleMetadata {
207  #[cfg(feature = "v12")]
208  fn from_v12_meta(md: &frame_metadata::v12::ModuleMetadata, lookup: &mut Types) -> Result<Self> {
209    let mod_idx = md.index;
210    let mod_name = decode_meta(&md.name)?;
211    let mut module = Self {
212      name: mod_name.clone(),
213      index: mod_idx,
214      funcs: BTreeMap::new(),
215      events: BTreeMap::new(),
216      errors: BTreeMap::new(),
217      err_idx_map: BTreeMap::new(),
218      event_ref: None,
219      error_ref: None,
220      call_ref: None,
221      storage: None,
222    };
223
224    // Decode module functions.
225    if let Some(calls) = &md.calls {
226      // Module RawCall type.
227      let mut raw_calls = TypeDefVariant::new();
228
229      decode_meta(calls)?
230        .iter()
231        .enumerate()
232        .try_for_each(|(func_idx, md)| -> Result<()> {
233          let (func, ty_ref) =
234            FuncMetadata::from_v12_meta(&mod_name, mod_idx, func_idx as u8, md, lookup)?;
235          let name = func.name.clone();
236          raw_calls.insert(func.func_idx, &name, ty_ref);
237          module.funcs.insert(name, func);
238          Ok(())
239        })?;
240      module.call_ref = Some(lookup.insert_type(
241        &format!("{}::RawCall", mod_name),
242        TypeDef::Variant(raw_calls),
243      ));
244    }
245
246    // Decode module events.
247    if let Some(events) = &md.event {
248      // Module RawEvent type.
249      let mut raw_events = TypeDefVariant::new();
250
251      decode_meta(events)?
252        .iter()
253        .enumerate()
254        .try_for_each(|(event_idx, md)| -> Result<()> {
255          let (event, ty_ref) =
256            EventMetadata::from_v12_meta(&mod_name, mod_idx, event_idx as u8, md, lookup)?;
257          let name = event.name.clone();
258          raw_events.insert(event.event_idx, &name, ty_ref);
259          module.events.insert(name, event);
260          Ok(())
261        })?;
262      module.event_ref = Some(lookup.insert_type(
263        &format!("{}::RawEvent", mod_name),
264        TypeDef::Variant(raw_events),
265      ));
266    }
267
268    // Decode module errors.
269    // Module RawError type.
270    let mut raw_errors = TypeDefVariant::new();
271
272    decode_meta(&md.errors)?
273      .iter()
274      .enumerate()
275      .try_for_each(|(error_idx, md)| -> Result<()> {
276        let error = ErrorMetadata::from_v12_meta(&mod_name, mod_idx, error_idx as u8, md)?;
277        let name = error.name.clone();
278        raw_errors.insert(error.error_idx, &name, None);
279        module.err_idx_map.insert(error.error_idx, name.clone());
280        module.errors.insert(name, error);
281        Ok(())
282      })?;
283    module.error_ref = Some(lookup.insert_type(
284      &format!("{}::RawError", mod_name),
285      TypeDef::Variant(raw_errors),
286    ));
287
288    // Parse storage metadata
289    if let Some(storage) = &md.storage {
290      let storage = decode_meta(storage)?;
291      module.storage = Some(StorageMetadata::from_v12_meta(storage, lookup)?);
292    }
293
294    Ok(module)
295  }
296
297  #[cfg(feature = "v13")]
298  fn from_v13_meta(md: &frame_metadata::v13::ModuleMetadata, lookup: &mut Types) -> Result<Self> {
299    let mod_idx = md.index;
300    let mod_name = decode_meta(&md.name)?;
301    let mut module = Self {
302      name: mod_name.clone(),
303      index: mod_idx,
304      funcs: BTreeMap::new(),
305      events: BTreeMap::new(),
306      errors: BTreeMap::new(),
307      err_idx_map: BTreeMap::new(),
308      event_ref: None,
309      error_ref: None,
310      call_ref: None,
311      storage: None,
312    };
313
314    // Decode module functions.
315    if let Some(calls) = &md.calls {
316      // Module RawCall type.
317      let mut raw_calls = TypeDefVariant::new();
318
319      decode_meta(calls)?
320        .iter()
321        .enumerate()
322        .try_for_each(|(func_idx, md)| -> Result<()> {
323          let (func, ty_ref) =
324            FuncMetadata::from_v13_meta(&mod_name, mod_idx, func_idx as u8, md, lookup)?;
325          let name = func.name.clone();
326          raw_calls.insert(func.func_idx, &name, ty_ref);
327          module.funcs.insert(name, func);
328          Ok(())
329        })?;
330      module.call_ref = Some(lookup.insert_type(
331        &format!("{}::RawCall", mod_name),
332        TypeDef::Variant(raw_calls),
333      ));
334    }
335
336    // Decode module events.
337    if let Some(events) = &md.event {
338      // Module RawEvent type.
339      let mut raw_events = TypeDefVariant::new();
340
341      decode_meta(events)?
342        .iter()
343        .enumerate()
344        .try_for_each(|(event_idx, md)| -> Result<()> {
345          let (event, ty_ref) =
346            EventMetadata::from_v13_meta(&mod_name, mod_idx, event_idx as u8, md, lookup)?;
347          let name = event.name.clone();
348          raw_events.insert(event.event_idx, &name, ty_ref);
349          module.events.insert(name, event);
350          Ok(())
351        })?;
352      module.event_ref = Some(lookup.insert_type(
353        &format!("{}::RawEvent", mod_name),
354        TypeDef::Variant(raw_events),
355      ));
356    }
357
358    // Decode module errors.
359    // Module RawError type.
360    let mut raw_errors = TypeDefVariant::new();
361
362    decode_meta(&md.errors)?
363      .iter()
364      .enumerate()
365      .try_for_each(|(error_idx, md)| -> Result<()> {
366        let error = ErrorMetadata::from_v13_meta(&mod_name, mod_idx, error_idx as u8, md)?;
367        let name = error.name.clone();
368        raw_errors.insert(error.error_idx, &name, None);
369        module.err_idx_map.insert(error.error_idx, name.clone());
370        module.errors.insert(name, error);
371        Ok(())
372      })?;
373    module.error_ref = Some(lookup.insert_type(
374      &format!("{}::RawError", mod_name),
375      TypeDef::Variant(raw_errors),
376    ));
377
378    // Parse storage metadata
379    if let Some(storage) = &md.storage {
380      let storage = decode_meta(storage)?;
381      module.storage = Some(StorageMetadata::from_v13_meta(storage, lookup)?);
382    }
383
384    Ok(module)
385  }
386
387  #[cfg(feature = "v14")]
388  fn from_v14_meta(
389    md: &frame_metadata::v14::PalletMetadata<PortableForm>,
390    types: &PortableRegistry,
391  ) -> Result<Self> {
392    let mod_idx = md.index;
393    let mod_name = &md.name;
394    let mut module = Self {
395      name: mod_name.clone(),
396      index: mod_idx,
397      funcs: BTreeMap::new(),
398      events: BTreeMap::new(),
399      errors: BTreeMap::new(),
400      err_idx_map: BTreeMap::new(),
401      event_ref: None,
402      error_ref: None,
403      call_ref: None,
404      storage: None,
405    };
406
407    // Decode module functions.
408    if let Some(calls) = &md.calls {
409      let id = calls.ty.id;
410      module.call_ref = Some(id.into());
411
412      let call_ty = types.resolve(id).expect("Missing Pallet call type");
413      match call_ty.type_def() {
414        TypeDef::Variant(v) => {
415          v.variants.iter().try_for_each(|md| -> Result<()> {
416            let func = FuncMetadata::from_v14_meta(&mod_name, mod_idx, md, types)?;
417            let name = func.name.clone();
418            module.funcs.insert(name, func);
419            Ok(())
420          })?;
421        }
422        _ => {
423          unimplemented!("Only Variant type supported for Pallet Call type.");
424        }
425      }
426    }
427
428    // Decode module events.
429    if let Some(events) = &md.event {
430      let id = events.ty.id;
431      module.event_ref = Some(id.into());
432
433      let event_ty = types.resolve(id).expect("Missing Pallet event type");
434      match event_ty.type_def() {
435        TypeDef::Variant(v) => {
436          v.variants.iter().try_for_each(|md| -> Result<()> {
437            let event = EventMetadata::from_v14_meta(&mod_name, mod_idx, md, types)?;
438            let name = event.name.clone();
439            module.events.insert(name, event);
440            Ok(())
441          })?;
442        }
443        _ => {
444          unimplemented!("Only Variant type supported for Pallet Event type.");
445        }
446      }
447    }
448
449    // Decode module errors.
450    if let Some(error) = &md.error {
451      let id = error.ty.id;
452      module.error_ref = Some(id.into());
453
454      let error_ty = types.resolve(id).expect("Missing Pallet error type");
455      match error_ty.type_def() {
456        TypeDef::Variant(v) => {
457          v.variants.iter().try_for_each(|md| -> Result<()> {
458            let error = ErrorMetadata::from_v14_meta(&mod_name, mod_idx, md)?;
459            let name = error.name.clone();
460            module.err_idx_map.insert(error.error_idx, name.clone());
461            module.errors.insert(name, error);
462            Ok(())
463          })?;
464        }
465        _ => {
466          unimplemented!("Only Variant type supported for Pallet Error type.");
467        }
468      }
469    }
470
471    // Parse storage metadata
472    if let Some(storage) = &md.storage {
473      module.storage = Some(StorageMetadata::from_v14_meta(storage, types)?);
474    }
475
476    Ok(module)
477  }
478}
479
480#[derive(Debug, Clone)]
481pub struct NamedType {
482  pub name: String,
483  pub ty_id: TypeId,
484}
485
486impl NamedType {
487  pub fn new(name: &str, lookup: &mut Types) -> Result<Self> {
488    let ty_id = lookup.parse_type(name)?;
489    let named = Self {
490      name: name.into(),
491      ty_id,
492    };
493
494    Ok(named)
495  }
496
497  #[cfg(feature = "v14")]
498  pub fn new_field_type(md: &Field, types: &PortableRegistry) -> Result<Self> {
499    let ty = types
500      .resolve(md.ty)
501      .ok_or_else(|| Error::MetadataParseFailed(format!("Failed to resolve type.")))?;
502    let name = md
503      .type_name
504      .as_ref()
505      .map(|ty_name| {
506        // Trim junk from `type_name`.
507        let name = if ty_name.starts_with("/*«*/") {
508          let end = ty_name.len() - 6;
509          &ty_name[6..end]
510        } else {
511          &ty_name[..]
512        }
513        .trim();
514        if is_type_compact(ty) {
515          format!("Compact<{}>", name)
516        } else {
517          name.to_string()
518        }
519      })
520      .unwrap_or_else(|| get_type_name(ty, types, false));
521    let named = Self {
522      name: name.into(),
523      ty_id: md.ty,
524    };
525
526    Ok(named)
527  }
528}
529
530#[derive(Clone)]
531pub struct EventMetadata {
532  pub mod_name: String,
533  pub name: String,
534  pub event_idx: u8,
535  pub args: Vec<NamedType>,
536  pub docs: Docs,
537}
538
539impl EventMetadata {
540  #[cfg(feature = "v12")]
541  fn from_v12_meta(
542    mod_name: &str,
543    _mod_idx: u8,
544    event_idx: u8,
545    md: &frame_metadata::v12::EventMetadata,
546    lookup: &mut Types,
547  ) -> Result<(Self, Option<TypeId>)> {
548    let mut event = Self {
549      mod_name: mod_name.into(),
550      name: decode_meta(&md.name)?.clone(),
551      event_idx,
552      args: Vec::new(),
553      docs: Docs::from_v12_meta(&md.documentation)?,
554    };
555
556    let mut event_tuple = Vec::new();
557
558    // Decode event arguments.
559    decode_meta(&md.arguments)?
560      .iter()
561      .try_for_each(|name| -> Result<()> {
562        let arg = NamedType::new(name, lookup)?;
563        event_tuple.push(arg.ty_id.clone());
564        event.args.push(arg);
565        Ok(())
566      })?;
567
568    let event_ref = if event_tuple.len() > 0 {
569      let type_name = format!("{}::RawEvent::{}", mod_name, event.name);
570      Some(lookup.insert_type(&type_name, TypeDef::new_tuple(event_tuple)))
571    } else {
572      None
573    };
574
575    Ok((event, event_ref))
576  }
577
578  #[cfg(feature = "v13")]
579  fn from_v13_meta(
580    mod_name: &str,
581    _mod_idx: u8,
582    event_idx: u8,
583    md: &frame_metadata::v13::EventMetadata,
584    lookup: &mut Types,
585  ) -> Result<(Self, Option<TypeId>)> {
586    let mut event = Self {
587      mod_name: mod_name.into(),
588      name: decode_meta(&md.name)?.clone(),
589      event_idx,
590      args: Vec::new(),
591      docs: Docs::from_v13_meta(&md.documentation)?,
592    };
593
594    let mut event_tuple = Vec::new();
595
596    // Decode event arguments.
597    decode_meta(&md.arguments)?
598      .iter()
599      .try_for_each(|name| -> Result<()> {
600        let arg = NamedType::new(name, lookup)?;
601        event_tuple.push(arg.ty_id.clone());
602        event.args.push(arg);
603        Ok(())
604      })?;
605
606    let event_ref = if event_tuple.len() > 0 {
607      let type_name = format!("{}::RawEvent::{}", mod_name, event.name);
608      Some(lookup.insert_type(&type_name, TypeDef::new_tuple(event_tuple)))
609    } else {
610      None
611    };
612
613    Ok((event, event_ref))
614  }
615
616  #[cfg(feature = "v14")]
617  fn from_v14_meta(
618    mod_name: &str,
619    _mod_idx: u8,
620    md: &Variant,
621    types: &PortableRegistry,
622  ) -> Result<Self> {
623    let mut event = Self {
624      mod_name: mod_name.into(),
625      name: md.name.clone(),
626      event_idx: md.index,
627      args: Vec::new(),
628      docs: Docs::from_v14_meta(&md.docs),
629    };
630
631    // Decode event arguments.
632    md.fields.iter().try_for_each(|md| -> Result<()> {
633      let arg = NamedType::new_field_type(md, types)?;
634      log::trace!("-- Event: {mod_name}.{}: field: {md:?}", event.name);
635      event.args.push(arg);
636      Ok(())
637    })?;
638
639    Ok(event)
640  }
641}
642
643#[derive(Clone)]
644pub struct ErrorMetadata {
645  pub mod_name: String,
646  pub name: String,
647  pub error_idx: u8,
648  pub docs: Docs,
649}
650
651impl ErrorMetadata {
652  #[cfg(feature = "v12")]
653  fn from_v12_meta(
654    mod_name: &str,
655    _mod_idx: u8,
656    error_idx: u8,
657    md: &frame_metadata::v12::ErrorMetadata,
658  ) -> Result<Self> {
659    Ok(Self {
660      mod_name: mod_name.into(),
661      name: decode_meta(&md.name)?.clone(),
662      error_idx,
663      docs: Docs::from_v12_meta(&md.documentation)?,
664    })
665  }
666
667  #[cfg(feature = "v13")]
668  fn from_v13_meta(
669    mod_name: &str,
670    _mod_idx: u8,
671    error_idx: u8,
672    md: &frame_metadata::v13::ErrorMetadata,
673  ) -> Result<Self> {
674    Ok(Self {
675      mod_name: mod_name.into(),
676      name: decode_meta(&md.name)?.clone(),
677      error_idx,
678      docs: Docs::from_v13_meta(&md.documentation)?,
679    })
680  }
681
682  #[cfg(feature = "v14")]
683  fn from_v14_meta(mod_name: &str, _mod_idx: u8, md: &Variant) -> Result<Self> {
684    Ok(Self {
685      mod_name: mod_name.into(),
686      name: md.name.clone(),
687      error_idx: md.index,
688      docs: Docs::from_v14_meta(&md.docs),
689    })
690  }
691}
692
693#[derive(Clone)]
694pub struct FuncMetadata {
695  pub mod_name: String,
696  pub name: String,
697  pub mod_idx: u8,
698  pub func_idx: u8,
699  pub args: Vec<FuncArg>,
700  pub docs: Docs,
701}
702
703impl FuncMetadata {
704  #[cfg(feature = "v12")]
705  fn from_v12_meta(
706    mod_name: &str,
707    mod_idx: u8,
708    func_idx: u8,
709    md: &frame_metadata::v12::FunctionMetadata,
710    lookup: &mut Types,
711  ) -> Result<(Self, Option<TypeId>)> {
712    let mut func = Self {
713      mod_name: mod_name.into(),
714      name: decode_meta(&md.name)?.clone(),
715      mod_idx,
716      func_idx,
717      args: Vec::new(),
718      docs: Docs::from_v12_meta(&md.documentation)?,
719    };
720
721    let mut func_tuple = Vec::new();
722
723    // Decode function arguments.
724    decode_meta(&md.arguments)?
725      .iter()
726      .try_for_each(|md| -> Result<()> {
727        let arg = FuncArg::from_v12_meta(md, lookup)?;
728        func_tuple.push(arg.ty.ty_id.clone());
729        func.args.push(arg);
730        Ok(())
731      })?;
732
733    let func_ref = if func_tuple.len() > 0 {
734      let type_name = format!("{}::RawFunc::{}", mod_name, func.name);
735      Some(lookup.insert_type(&type_name, TypeDef::new_tuple(func_tuple)))
736    } else {
737      None
738    };
739
740    Ok((func, func_ref))
741  }
742
743  #[cfg(feature = "v13")]
744  fn from_v13_meta(
745    mod_name: &str,
746    mod_idx: u8,
747    func_idx: u8,
748    md: &frame_metadata::v13::FunctionMetadata,
749    lookup: &mut Types,
750  ) -> Result<(Self, Option<TypeId>)> {
751    let mut func = Self {
752      mod_name: mod_name.into(),
753      name: decode_meta(&md.name)?.clone(),
754      mod_idx,
755      func_idx,
756      args: Vec::new(),
757      docs: Docs::from_v13_meta(&md.documentation)?,
758    };
759
760    let mut func_tuple = Vec::new();
761
762    // Decode function arguments.
763    decode_meta(&md.arguments)?
764      .iter()
765      .try_for_each(|md| -> Result<()> {
766        let arg = FuncArg::from_v13_meta(md, lookup)?;
767        func_tuple.push(arg.ty.ty_id.clone());
768        func.args.push(arg);
769        Ok(())
770      })?;
771
772    let func_ref = if func_tuple.len() > 0 {
773      let type_name = format!("{}::RawFunc::{}", mod_name, func.name);
774      Some(lookup.insert_type(&type_name, TypeDef::new_tuple(func_tuple)))
775    } else {
776      None
777    };
778
779    Ok((func, func_ref))
780  }
781
782  #[cfg(feature = "v14")]
783  fn from_v14_meta(
784    mod_name: &str,
785    mod_idx: u8,
786    md: &Variant,
787    types: &PortableRegistry,
788  ) -> Result<Self> {
789    let mut func = Self {
790      mod_name: mod_name.into(),
791      name: md.name.clone(),
792      mod_idx,
793      func_idx: md.index,
794      args: Vec::new(),
795      docs: Docs::from_v14_meta(&md.docs),
796    };
797
798    // Decode function arguments.
799    md.fields.iter().try_for_each(|md| -> Result<()> {
800      let arg = FuncArg::from_v14_meta(md, types)?;
801      func.args.push(arg);
802      Ok(())
803    })?;
804
805    Ok(func)
806  }
807}
808
809#[derive(Clone)]
810pub struct FuncArg {
811  pub name: String,
812  pub ty: NamedType,
813}
814
815impl FuncArg {
816  #[cfg(feature = "v12")]
817  fn from_v12_meta(
818    md: &frame_metadata::v12::FunctionArgumentMetadata,
819    lookup: &mut Types,
820  ) -> Result<Self> {
821    let ty = decode_meta(&md.ty)?;
822    let arg = Self {
823      name: decode_meta(&md.name)?.clone(),
824      ty: NamedType::new(&ty, lookup)?,
825    };
826
827    Ok(arg)
828  }
829
830  #[cfg(feature = "v13")]
831  fn from_v13_meta(
832    md: &frame_metadata::v13::FunctionArgumentMetadata,
833    lookup: &mut Types,
834  ) -> Result<Self> {
835    let ty = decode_meta(&md.ty)?;
836    let arg = Self {
837      name: decode_meta(&md.name)?.clone(),
838      ty: NamedType::new(&ty, lookup)?,
839    };
840
841    Ok(arg)
842  }
843
844  #[cfg(feature = "v14")]
845  fn from_v14_meta(md: &Field, types: &PortableRegistry) -> Result<Self> {
846    let arg = Self {
847      name: md.name.clone().unwrap_or_default(),
848      ty: NamedType::new_field_type(md, types)?,
849    };
850
851    Ok(arg)
852  }
853}
854
855#[derive(Clone)]
856pub struct Docs {
857  pub lines: Vec<String>,
858}
859
860impl Docs {
861  #[cfg(feature = "v12")]
862  fn from_v12_meta(md: &DecodeDifferentArray<&'static str, String>) -> Result<Self> {
863    Ok(Self {
864      lines: decode_meta(md)?.clone(),
865    })
866  }
867
868  #[cfg(feature = "v13")]
869  fn from_v13_meta(md: &DecodeDifferentArray<&'static str, String>) -> Result<Self> {
870    Ok(Self {
871      lines: decode_meta(md)?.clone(),
872    })
873  }
874
875  #[cfg(feature = "v14")]
876  fn from_v14_meta(docs: &[String]) -> Self {
877    Self {
878      lines: docs.to_vec(),
879    }
880  }
881}