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