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
30pub 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 let type_ref = self.resolve(&name);
335 match type_ref.ty {
337 None => {
338 log::trace!("Parse Unresolved: name={name}, def={def}");
340 if let Some(type_def) = self.parse(def)? {
341 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 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 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 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 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 len.trim().parse::<usize>().ok().map(|l| (ty.trim(), l))
465 })
466 .ok_or_else(|| parse_error!("Failed to parse slice: {}", def))?;
467 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 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 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 pub fn dump_types(&self) {
558 for (id, ty) in self.types.iter() {
559 log::warn!("Type[{:?}] => {:#?}", id, ty);
560 }
561 }
562
563 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 }
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 if !types.try_load_schema(&format!("{}/init_{}.json", prefix, spec)) {
678 types.try_load_schema("./schemas/init_types.json");
679 }
680 if !types.try_load_schema(&format!("{}/{}.json", prefix, spec)) {
682 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 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 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 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 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}