polymesh_api_client/
metadata.rs

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