polymesh_api_client/
schema.rs

1#[cfg(not(feature = "std"))]
2use alloc::{
3  collections::btree_map::BTreeMap,
4  sync::{Arc, RwLock},
5};
6#[cfg(feature = "std")]
7use std::{
8  collections::BTreeMap,
9  fs::File,
10  io::BufReader,
11  sync::{Arc, RwLock},
12};
13
14#[cfg(not(feature = "std"))]
15use alloc::{
16  format,
17  string::{String, ToString},
18};
19use sp_std::prelude::*;
20
21use frame_metadata::RuntimeMetadata;
22
23use serde_json::{Map, Value};
24
25use crate::error::*;
26use crate::metadata::*;
27use crate::type_def::*;
28use crate::*;
29
30/// Use large type ids for old schema and metadata (v12-v13) types.
31/// The newer v14 metadata uses small ids.
32pub const SCHEMA_TYPE_ID_BASE: u32 = 10_000_000;
33
34macro_rules! parse_error {
35  ($fmt:expr, $($arg:tt)*) => {
36    Error::SchemaParseFailed(format!($fmt, $($arg)*))
37  };
38}
39
40#[cfg(feature = "v14")]
41pub fn is_type_compact(ty: &Type) -> bool {
42  match ty.type_def() {
43    TypeDef::Compact(_) => true,
44    _ => false,
45  }
46}
47
48#[cfg(feature = "v14")]
49pub fn get_type_name(ty: &Type, types: &PortableRegistry, full: bool) -> String {
50  let name = match ty.type_def() {
51    TypeDef::Sequence(s) => {
52      let elm_ty = types
53        .resolve(s.type_param())
54        .expect("Failed to resolve sequence element type");
55      format!("Vec<{}>", get_type_name(elm_ty, types, full))
56    }
57    TypeDef::Array(a) => {
58      let elm_ty = types
59        .resolve(a.type_param())
60        .expect("Failed to resolve array element type");
61      format!("[{}; {}]", get_type_name(elm_ty, types, full), a.len())
62    }
63    TypeDef::Tuple(t) => {
64      let fields = t
65        .fields()
66        .iter()
67        .map(|f| {
68          let f_ty = types
69            .resolve(*f)
70            .expect("Failed to resolve tuple element type");
71          get_type_name(f_ty, types, full)
72        })
73        .collect::<Vec<_>>();
74      format!("({})", fields.join(","))
75    }
76    TypeDef::Primitive(p) => {
77      use TypeDefPrimitive::*;
78      match p {
79        Bool => "bool".into(),
80        Char => "char".into(),
81        Str => "Text".into(),
82        U8 => "u8".into(),
83        U16 => "u16".into(),
84        U32 => "u32".into(),
85        U64 => "u64".into(),
86        U128 => "u128".into(),
87        U256 => "u256".into(),
88        I8 => "i8".into(),
89        I16 => "i16".into(),
90        I32 => "i32".into(),
91        I64 => "i64".into(),
92        I128 => "i128".into(),
93        I256 => "i256".into(),
94      }
95    }
96    TypeDef::Compact(c) => {
97      let elm_ty = types
98        .resolve(c.type_param())
99        .expect("Failed to resolve Compact type");
100      format!("Compact<{}>", get_type_name(elm_ty, types, full))
101    }
102    _ => {
103      if full {
104        format!("{}", ty.path())
105      } else {
106        ty.path().ident().expect("Missing type name").into()
107      }
108    }
109  };
110  let ty_params = ty.type_params();
111  if ty_params.len() > 0 {
112    let params = ty_params
113      .iter()
114      .map(|p| match &p.ty {
115        Some(ty) => {
116          let p_ty = types
117            .resolve(*ty)
118            .expect("Failed to resolve type parameter");
119          get_type_name(p_ty, types, full)
120        }
121        None => p.name.clone(),
122      })
123      .collect::<Vec<_>>();
124    format!("{}<{}>", name, params.join(","))
125  } else {
126    name
127  }
128}
129
130#[derive(Clone, Debug)]
131pub struct TypeRef {
132  pub id: TypeId,
133  pub ty: Option<Type>,
134}
135
136impl TypeRef {
137  pub fn new(id: TypeId, ty: Option<Type>) -> Self {
138    Self { id, ty }
139  }
140
141  pub fn to_string(&mut self) -> String {
142    format!("TypeRef[{:?}]: {:?}", self.id, self.ty)
143  }
144}
145
146#[derive(Clone)]
147pub struct Types {
148  next_id: TypeId,
149  types: BTreeMap<TypeId, Type>,
150  name_to_id: BTreeMap<String, TypeId>,
151  runtime_version: RuntimeVersion,
152  metadata: Option<Metadata>,
153}
154
155impl Types {
156  pub fn new(runtime_version: RuntimeVersion) -> Self {
157    Self {
158      next_id: TypeId(SCHEMA_TYPE_ID_BASE),
159      types: BTreeMap::new(),
160      name_to_id: BTreeMap::new(),
161      runtime_version,
162      metadata: None,
163    }
164  }
165
166  pub fn get_runtime_version(&self) -> RuntimeVersion {
167    self.runtime_version.clone()
168  }
169
170  pub fn set_metadata(&mut self, metadata: Metadata) {
171    self.metadata = Some(metadata);
172  }
173
174  pub fn get_metadata(&self) -> Option<Metadata> {
175    self.metadata.as_ref().cloned()
176  }
177
178  #[cfg(feature = "std")]
179  fn load_schema(&mut self, filename: &str) -> Result<()> {
180    let file = File::open(filename)?;
181
182    let schema: serde_json::Value = serde_json::from_reader(BufReader::new(file))?;
183
184    let schema = schema
185      .as_object()
186      .expect("Invalid schema, expected object.");
187
188    let types = match schema.get("types") {
189      Some(val) => val.as_object().unwrap_or(schema),
190      _ => schema,
191    };
192    self.parse_schema_types(types)?;
193
194    Ok(())
195  }
196
197  #[cfg(feature = "std")]
198  pub fn try_load_schema(&mut self, filename: &str) -> bool {
199    log::info!("Try loading schema: {}", filename);
200    match self.load_schema(filename) {
201      Ok(_) => true,
202      Err(err) => {
203        log::debug!("Failed to load schema {}: {err:?}", filename);
204        false
205      }
206    }
207  }
208
209  #[cfg(not(feature = "std"))]
210  pub fn try_load_schema(&mut self, _filename: &str) -> bool {
211    false
212  }
213
214  fn parse_schema_types(&mut self, types: &Map<String, Value>) -> Result<()> {
215    for (name, val) in types.iter() {
216      match val {
217        Value::String(val) => {
218          log::trace!("Named type: name={name}, val={val}");
219          self.parse_named_type(name, val)?;
220        }
221        Value::Object(map) => {
222          if let Some(variants) = map.get("_enum") {
223            log::trace!("ENUM: name={name}, variants={variants}");
224            self.parse_enum(name, variants)?;
225          } else {
226            log::trace!("STRUCT: name={name}, fields={map:?}");
227            self.parse_struct(name, map)?;
228          }
229        }
230        _ => {
231          log::warn!("UNHANDLED JSON VALUE: {} => {:?}", name, val);
232        }
233      }
234    }
235    Ok(())
236  }
237
238  fn parse_variant(&mut self, def: &str) -> Result<Vec<Field>> {
239    match self.parse(def)? {
240      Some(TypeDef::Tuple(tuple)) => Ok(tuple.fields.into_iter().map(|t| Field::new(t)).collect()),
241      Some(_) => {
242        let type_id = self.parse_type(def)?;
243        Ok(vec![Field::new(type_id)])
244      }
245      None => {
246        let type_ref = self.resolve(def);
247        Ok(vec![Field::new(type_ref.id)])
248      }
249    }
250  }
251
252  fn parse_enum(&mut self, name: &str, variants: &Value) -> Result<()> {
253    let mut index = 0;
254    let variants = match variants {
255      Value::Array(arr) => arr
256        .iter()
257        .map(|val| match val.as_str() {
258          Some(var_name) => {
259            let idx = index;
260            index += 1;
261            Ok(Variant::new(var_name, vec![], idx))
262          }
263          None => Err(parse_error!(
264            "Expected json string for enum {}: got {:?}",
265            name,
266            val
267          )),
268        })
269        .collect::<Result<Vec<Variant>>>()?,
270      Value::Object(obj) => obj
271        .iter()
272        .map(|(var_name, val)| -> Result<_> {
273          let idx = index;
274          index += 1;
275          match val.as_str() {
276            Some("") => Ok(Variant::new(var_name, vec![], idx)),
277            Some(var_def) => {
278              let fields = self.parse_variant(var_def)?;
279              Ok(Variant::new(var_name, fields, idx))
280            }
281            None => {
282              Err(parse_error!("Expected json string for enum {}: got {:?}", name, val).into())
283            }
284          }
285        })
286        .collect::<Result<Vec<Variant>>>()?,
287      _ => {
288        return Err(parse_error!("Invalid json for `_enum`: {:?}", variants));
289      }
290    };
291    self.insert_type(name, TypeDefVariant::new_variants(variants).into());
292    Ok(())
293  }
294
295  fn parse_struct(&mut self, name: &str, def: &Map<String, Value>) -> Result<()> {
296    let fields = def
297      .iter()
298      .map(|(field_name, val)| -> Result<_> {
299        match val.as_str() {
300          Some(field_def) => {
301            let type_id = self.parse_type(field_def)?;
302            Ok(Field::new_named(
303              field_name,
304              type_id,
305              Some(field_def.to_string()),
306            ))
307          }
308          None => Err(parse_error!(
309            "Expected json string for struct {} field {}: got {:?}",
310            name,
311            field_name,
312            val
313          )),
314        }
315      })
316      .collect::<Result<Vec<Field>>>()?;
317    self.insert_type(name, TypeDefComposite::new(fields).into());
318    Ok(())
319  }
320
321  pub fn parse_named_type(&mut self, name: &str, def: &str) -> Result<TypeId> {
322    let id = self.parse_type(def)?;
323    Ok(self.insert_new_type(name, id))
324  }
325
326  pub fn parse_type(&mut self, def: &str) -> Result<TypeId> {
327    let name = def
328      .trim()
329      .replace("\r", "")
330      .replace("\n", "")
331      .replace("T::", "");
332    log::trace!("-- parse_type: {def} -> {name}");
333    // Try to resolve the type.
334    let type_ref = self.resolve(&name);
335    // Check if type is unresolved.
336    match type_ref.ty {
337      None => {
338        // Try parsing it.
339        log::trace!("Parse Unresolved: name={name}, def={def}");
340        if let Some(type_def) = self.parse(def)? {
341          // Insert TypeDef for unresolved type.
342          self.insert_type(&name, type_def);
343        }
344      }
345      _ => (),
346    }
347    Ok(type_ref.id)
348  }
349
350  fn is_primitive(def: &str) -> Option<TypeDefPrimitive> {
351    // Check for primitives.
352    match def {
353      "u8" => Some(TypeDefPrimitive::U8),
354      "u16" => Some(TypeDefPrimitive::U16),
355      "u32" => Some(TypeDefPrimitive::U32),
356      "u64" => Some(TypeDefPrimitive::U64),
357      "u128" => Some(TypeDefPrimitive::U128),
358      "u256" => Some(TypeDefPrimitive::U256),
359      "i8" => Some(TypeDefPrimitive::I8),
360      "i16" => Some(TypeDefPrimitive::I16),
361      "i32" => Some(TypeDefPrimitive::I32),
362      "i64" => Some(TypeDefPrimitive::I64),
363      "i128" => Some(TypeDefPrimitive::I128),
364      "i256" => Some(TypeDefPrimitive::I256),
365      "bool" => Some(TypeDefPrimitive::Bool),
366      "char" => Some(TypeDefPrimitive::Char),
367      "String" => Some(TypeDefPrimitive::Str),
368      "Text" => Some(TypeDefPrimitive::Str),
369      _ => None,
370    }
371  }
372
373  fn parse(&mut self, def: &str) -> Result<Option<TypeDef>> {
374    log::trace!("-- parse: {def}, last ch={:?}", def.chars().last());
375    match def.chars().last() {
376      Some('>') => {
377        // Handle: Vec<T>, Option<T>, Compact<T>
378        let (ty, param) = def
379          .strip_suffix('>')
380          .and_then(|s| s.split_once('<'))
381          .map(|(ty, param)| (ty.trim(), param.trim()))
382          .ok_or_else(|| parse_error!("Failed to parse Vec/Option/Compact: {}", def))?;
383        log::trace!("-- GENERIC type: {ty}, param: {param}");
384        match ty {
385          "Vec" => {
386            let param_ref = self.parse_type(param)?;
387            Ok(Some(TypeDefSequence::new(param_ref).into()))
388          }
389          "Option" => {
390            let param_ref = self.parse_type(param)?;
391            Ok(Some(TypeDefVariant::new_option(param_ref).into()))
392          }
393          "Compact" => {
394            let param_ref = self.parse_type(param)?;
395            Ok(Some(TypeDefCompact::new(param_ref).into()))
396          }
397          "Box" => {
398            let param_ref = self.parse_type(param)?;
399            Ok(Some(TypeDefTuple::new_type(param_ref).into()))
400          }
401          "Result" => {
402            let (ok_ref, err_ref) = match param.split_once(',') {
403              Some((ok_ty, err_ty)) => {
404                let ok_ref = self.parse_type(ok_ty)?;
405                let err_ref = self.parse_type(err_ty)?;
406                (ok_ref, err_ref)
407              }
408              None => {
409                let ok_ref = self.parse_type(param)?;
410                let err_ref = self.parse_type("Error")?;
411                (ok_ref, err_ref)
412              }
413            };
414            Ok(Some(TypeDefVariant::new_result(ok_ref, err_ref).into()))
415          }
416          "PhantomData" | "sp_std::marker::PhantomData" => Ok(Some(TypeDefTuple::unit().into())),
417          ty => Ok(
418            self
419              .name_to_id
420              .get(ty)
421              .map(|id| TypeDefTuple::new_type(*id).into()),
422          ),
423        }
424      }
425      Some(')') => {
426        let mut broken_type = None;
427        let defs = def
428          .trim_matches(|c| c == '(' || c == ')')
429          .split_terminator(',')
430          .filter_map(|s| {
431            let s = match broken_type.take() {
432              Some(s1) => format!("{}, {}", s1, s),
433              None => s.to_string(),
434            }
435            .trim()
436            .to_string();
437            // Check for broken type.
438            let left = s.chars().filter(|c| *c == '<').count();
439            let right = s.chars().filter(|c| *c == '>').count();
440            if left != right {
441              broken_type = Some(s);
442              return None;
443            }
444            if s != "" {
445              Some(s)
446            } else {
447              None
448            }
449          })
450          .try_fold(Vec::new(), |mut vec, val| -> Result<_> {
451            let type_id = self.parse_type(&val)?;
452            vec.push(type_id);
453            Ok(vec)
454          })?;
455        // Handle tuples.
456        Ok(Some(TypeDefTuple::new(defs).into()))
457      }
458      Some(']') => {
459        let (slice_ty, slice_len) = def
460          .trim_matches(|c| c == '[' || c == ']')
461          .split_once(';')
462          .and_then(|(ty, len)| {
463            // parse slice length.
464            len.trim().parse::<usize>().ok().map(|l| (ty.trim(), l))
465          })
466          .ok_or_else(|| parse_error!("Failed to parse slice: {}", def))?;
467        // Handle slices.
468        let slice_ref = self.parse_type(slice_ty)?;
469        Ok(Some(TypeDefArray::new(slice_len as u32, slice_ref).into()))
470      }
471      _ => Ok(None),
472    }
473  }
474
475  fn get_next_id(&mut self) -> TypeId {
476    let id = self.next_id;
477    self.next_id.inc();
478    id
479  }
480
481  fn new_type(&mut self, ty: Type) -> TypeId {
482    let id = self.get_next_id();
483    self.types.insert(id, ty);
484    id
485  }
486
487  pub fn get_type(&self, id: TypeId) -> Option<&Type> {
488    self.types.get(&id)
489  }
490
491  pub fn resolve(&mut self, name: &str) -> TypeRef {
492    let id = if let Some(id) = self.name_to_id.get(name) {
493      *id
494    } else if let Some(prim) = Self::is_primitive(name) {
495      let id = self.new_type(Type::new("", prim.into()));
496      self.name_to_id.insert(name.into(), id);
497      id
498    } else {
499      let id = self.get_next_id();
500      self.name_to_id.insert(name.into(), id);
501      id
502    };
503    TypeRef::new(id, self.get_type(id).cloned())
504  }
505
506  pub fn insert_new_type(&mut self, name: &str, ty_id: TypeId) -> TypeId {
507    self.insert_type(name, TypeDef::new_type(ty_id))
508  }
509
510  pub fn insert_type(&mut self, name: &str, type_def: TypeDef) -> TypeId {
511    let ty = Type::new(name, type_def);
512    log::trace!("insert_type: {name} => {ty:?}");
513    self.insert(name, ty)
514  }
515
516  pub fn import_type(&mut self, name: &str, id: TypeId, ty: Type) -> Result<()> {
517    if id.0 >= SCHEMA_TYPE_ID_BASE {
518      Err(Error::SchemaParseFailed(format!(
519        "Imported type ids must be below schema type base: {:?} >= {}",
520        id, SCHEMA_TYPE_ID_BASE
521      )))?;
522    }
523    // insert type.
524    if self.types.insert(id, ty).is_some() {
525      Err(Error::SchemaParseFailed(format!(
526        "Imported type id {:?} already exists",
527        id
528      )))?;
529    }
530
531    if self.name_to_id.get(name).is_some() {
532      self.insert_new_type(name, id);
533    } else {
534      self.name_to_id.insert(name.into(), id);
535    }
536
537    Ok(())
538  }
539
540  pub fn insert(&mut self, name: &str, ty: Type) -> TypeId {
541    if let Some(id) = self.name_to_id.get(name) {
542      // Already exists.  Check if it has a type defined yet.
543      if self.types.contains_key(id) {
544        log::warn!("REDEFINE TYPE: {}", name);
545      } else {
546        self.types.insert(*id, ty);
547      }
548      *id
549    } else {
550      let id = self.new_type(ty);
551      self.name_to_id.insert(name.into(), id);
552      id
553    }
554  }
555
556  /// Dump types.
557  pub fn dump_types(&self) {
558    for (id, ty) in self.types.iter() {
559      log::warn!("Type[{:?}] => {:#?}", id, ty);
560    }
561  }
562
563  /// Dump unresolved types.
564  pub fn dump_unresolved(&self) {
565    for (name, id) in self.name_to_id.iter() {
566      match self.types.get(id) {
567        None => {
568          log::warn!("--------- Unresolved[{:?}]: {}", id, name);
569        }
570        Some(_) => {
571          // Defined type.
572        }
573      }
574    }
575  }
576}
577
578#[cfg(feature = "v14")]
579impl Types {
580  pub fn import_v14_types(&mut self, types: &PortableRegistry) -> Result<()> {
581    for ty in types.types() {
582      let name = get_type_name(ty.ty(), &types, true);
583      log::debug!("import_v14_type: {:?} => {}", ty.id(), name);
584      self.import_type(&name, ty.id(), ty.ty().clone())?;
585    }
586    Ok(())
587  }
588}
589
590#[derive(Clone)]
591pub struct TypeLookup {
592  types: Arc<RwLock<Types>>,
593}
594
595impl TypeLookup {
596  pub fn from_types(types: Types) -> Self {
597    Self {
598      types: Arc::new(RwLock::new(types)),
599    }
600  }
601
602  pub fn parse_named_type(&self, name: &str, def: &str) -> Result<TypeId> {
603    let mut t = self.types.write().unwrap();
604    t.parse_named_type(name, def)
605  }
606
607  pub fn parse_type(&self, def: &str) -> Result<TypeId> {
608    let mut t = self.types.write().unwrap();
609    t.parse_type(def)
610  }
611
612  pub fn get_type(&self, id: TypeId) -> Option<Type> {
613    let t = self.types.read().unwrap();
614    t.get_type(id).cloned()
615  }
616
617  pub fn resolve(&self, name: &str) -> TypeRef {
618    let mut t = self.types.write().unwrap();
619    t.resolve(name)
620  }
621
622  pub fn insert_type(&self, name: &str, type_meta: TypeDef) -> TypeId {
623    let mut t = self.types.write().unwrap();
624    t.insert_type(name, type_meta)
625  }
626
627  pub fn dump_types(&self) {
628    self.types.read().unwrap().dump_types();
629  }
630
631  pub fn dump_unresolved(&self) {
632    self.types.read().unwrap().dump_unresolved();
633  }
634
635  pub fn get_runtime_version(&self) -> RuntimeVersion {
636    self.types.read().unwrap().get_runtime_version()
637  }
638
639  pub fn get_metadata(&self) -> Option<Metadata> {
640    self.types.read().unwrap().get_metadata()
641  }
642}
643
644pub struct InitRegistryFn(Box<dyn Fn(&mut Types) -> Result<()> + Send + Sync + 'static>);
645
646impl InitRegistryFn {
647  pub fn init_types(&self, types: &mut Types) -> Result<()> {
648    self.0(types)
649  }
650}
651
652#[derive(PartialEq, Eq, PartialOrd, Ord)]
653struct SpecVersionKey(String, u32);
654
655impl From<&RuntimeVersion> for SpecVersionKey {
656  fn from(version: &RuntimeVersion) -> Self {
657    Self(version.spec_name.to_string(), version.spec_version)
658  }
659}
660
661pub struct InnerTypesRegistry {
662  block_types: BTreeMap<Option<SpecVersionKey>, TypeLookup>,
663  initializers: Vec<InitRegistryFn>,
664}
665
666impl InnerTypesRegistry {
667  pub fn new() -> Self {
668    Self {
669      block_types: BTreeMap::new(),
670      initializers: Vec::new(),
671    }
672  }
673
674  #[cfg(any(feature = "v12", feature = "v13"))]
675  fn load_custom_types(&self, prefix: &str, spec: u32, types: &mut Types) -> Result<()> {
676    // Load standard substrate types.
677    if !types.try_load_schema(&format!("{}/init_{}.json", prefix, spec)) {
678      types.try_load_schema("./schemas/init_types.json");
679    }
680    // Load custom chain types.
681    if !types.try_load_schema(&format!("{}/{}.json", prefix, spec)) {
682      // fallback.
683      types.try_load_schema("schema.json");
684    }
685
686    Ok(())
687  }
688
689  async fn build_types(
690    &self,
691    client: &Client,
692    version: Option<RuntimeVersion>,
693    hash: Option<BlockHash>,
694  ) -> Result<TypeLookup> {
695    let runtime_version = match version {
696      Some(version) => version,
697      None => client
698        .get_block_runtime_version(hash)
699        .await?
700        .ok_or_else(|| Error::RpcClient(format!("Failed to get block RuntimeVersion")))?,
701    };
702    // build schema path.
703    let spec_name = runtime_version.spec_name.to_string();
704    #[cfg(any(feature = "v12", feature = "v13"))]
705    let spec_version = runtime_version.spec_version;
706    let name = if let Some((spec_name, _chain_type)) = spec_name.split_once("_") {
707      spec_name
708    } else {
709      &spec_name
710    };
711    let schema_prefix = format!("./schemas/{}", name);
712    log::debug!("schema_prefix = {}", schema_prefix);
713
714    let mut types = Types::new(runtime_version);
715
716    // Load chain metadata.
717    let runtime_metadata = client
718      .get_block_metadata(hash)
719      .await?
720      .ok_or_else(|| Error::RpcClient(format!("Failed to get block Metadata")))?;
721
722    // Process chain metadata.
723    let metadata = match runtime_metadata.1 {
724      #[cfg(feature = "v12")]
725      RuntimeMetadata::V12(v12) => {
726        if runtime_metadata.0 != frame_metadata::v12::META_RESERVED {
727          return Err(Error::MetadataParseFailed(format!(
728            "Invalid metadata prefix {}",
729            runtime_metadata.0
730          )));
731        }
732        self.load_custom_types(&schema_prefix, spec_version, &mut types)?;
733
734        Metadata::from_v12_metadata(v12, &mut types)?
735      }
736      #[cfg(feature = "v13")]
737      RuntimeMetadata::V13(v13) => {
738        if runtime_metadata.0 != frame_metadata::v13::META_RESERVED {
739          return Err(Error::MetadataParseFailed(format!(
740            "Invalid metadata prefix {}",
741            runtime_metadata.0
742          )));
743        }
744        self.load_custom_types(&schema_prefix, spec_version, &mut types)?;
745
746        Metadata::from_v13_metadata(v13, &mut types)?
747      }
748      #[cfg(feature = "v14")]
749      RuntimeMetadata::V14(v14) => {
750        if runtime_metadata.0 != frame_metadata::META_RESERVED {
751          return Err(Error::MetadataParseFailed(format!(
752            "Invalid metadata prefix {}",
753            runtime_metadata.0
754          )));
755        }
756
757        Metadata::from_v14_metadata(v14, &mut types)?
758      }
759      _ => {
760        return Err(Error::MetadataParseFailed(format!(
761          "Unsupported metadata version"
762        )));
763      }
764    };
765    types.set_metadata(metadata);
766
767    for init in &self.initializers {
768      init.init_types(&mut types)?;
769    }
770    let lookup = TypeLookup::from_types(types);
771    Ok(lookup)
772  }
773
774  pub async fn get_block_types(
775    &mut self,
776    client: &Client,
777    version: Option<RuntimeVersion>,
778    hash: Option<BlockHash>,
779  ) -> Result<TypeLookup> {
780    let spec_key: Option<SpecVersionKey> = version.as_ref().map(|v| v.into());
781    if let Some(types) = self.block_types.get(&spec_key) {
782      return Ok(types.clone());
783    }
784
785    log::info!(
786      "Spec version not found: load schema/metadata.  RuntimeVersion={:?}",
787      version
788    );
789    // Need to build/initialize new Types.
790    let lookup = self.build_types(client, version, hash).await?;
791    self.block_types.insert(spec_key, lookup.clone());
792    Ok(lookup)
793  }
794
795  pub fn add_init(&mut self, func: InitRegistryFn) {
796    self.initializers.push(func);
797  }
798}
799
800#[derive(Clone)]
801pub struct TypesRegistry(Arc<RwLock<InnerTypesRegistry>>);
802
803impl TypesRegistry {
804  pub fn new() -> Self {
805    Self(Arc::new(RwLock::new(InnerTypesRegistry::new())))
806  }
807
808  pub async fn get_block_types(
809    &self,
810    client: &Client,
811    version: Option<RuntimeVersion>,
812    hash: Option<BlockHash>,
813  ) -> Result<TypeLookup> {
814    let mut inner = self.0.write().unwrap();
815    Ok(inner.get_block_types(client, version, hash).await?)
816  }
817
818  pub fn add_init<F>(&self, func: F)
819  where
820    F: 'static + Send + Sync + Fn(&mut Types) -> Result<()>,
821  {
822    self
823      .0
824      .write()
825      .unwrap()
826      .add_init(InitRegistryFn(Box::new(func)))
827  }
828}