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 let mut mod_events = TypeDefVariant::new();
55 let mut mod_errors = TypeDefVariant::new();
56 let mut mod_calls = TypeDefVariant::new();
57
58 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 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 let mut mod_events = TypeDefVariant::new();
94 let mut mod_errors = TypeDefVariant::new();
95 let mut mod_calls = TypeDefVariant::new();
96
97 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 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 lookup.import_v14_types(&types)?;
135
136 let mut mod_events = TypeDefVariant::new();
138 let mut mod_errors = TypeDefVariant::new();
139 let mut mod_calls = TypeDefVariant::new();
140
141 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 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 if let Some(calls) = &md.calls {
213 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 if let Some(events) = &md.event {
235 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 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 if let Some(calls) = &md.calls {
296 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 if let Some(events) = &md.event {
318 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 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 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 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 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 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_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_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 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_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_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 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}