From eb1e7a12bd5ce0e9a20037d7c21b588770a730ce Mon Sep 17 00:00:00 2001 From: emostov <32168567+emostov@users.noreply.github.com> Date: Wed, 16 Dec 2020 22:51:50 -0800 Subject: [PATCH] Enable retrieval of constants from rutnime metadata --- src/metadata.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/metadata.rs b/src/metadata.rs index 18ea8181fb..27b3446cbd 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -70,6 +70,12 @@ pub enum MetadataError { /// Default error. #[error("Failed to decode default: {0}")] DefaultError(CodecError), + /// Failure to decode constant value. + #[error("Failed to decode constant value: {0}")] + ConstantValueError(CodecError), + /// Constant is not in metadata. + #[error("Constant {0} not found")] + ConstantNotFound(&'static str), } /// Runtime metadata. @@ -166,7 +172,7 @@ pub struct ModuleMetadata { index: u8, name: String, storage: HashMap, - // constants + constants: HashMap, } impl ModuleMetadata { @@ -175,6 +181,16 @@ impl ModuleMetadata { .get(key) .ok_or(MetadataError::StorageNotFound(key)) } + + /// Get a constant's metadata by name + pub fn constant( + &self, + key: &'static str, + ) -> Result<&ModuleConstantMetadata, MetadataError> { + self.constants + .get(key) + .ok_or(MetadataError::ConstantNotFound(key)) + } } #[derive(Clone, Debug)] @@ -463,6 +479,36 @@ impl EventArg { } } +#[derive(Clone, Debug)] +pub struct ModuleConstantMetadata { + name: String, + ty: String, + value: Vec, + documentation: Vec, +} + +impl ModuleConstantMetadata { + /// Name + pub fn name(&self) -> &String { + &self.name + } + + /// Constant value (decoded) + pub fn value(&self) -> Result { + Decode::decode(&mut &self.value[..]).map_err(MetadataError::ConstantValueError) + } + + /// Type (as defined in the runtime) + pub fn ty(&self) -> &String { + &self.ty + } + + /// Documentation + pub fn documentation(&self) -> &Vec { + &self.documentation + } +} + #[derive(Debug, thiserror::Error)] pub enum ConversionError { #[error("Invalid prefix")] @@ -493,6 +539,12 @@ impl TryFrom for Metadata { for module in convert(meta.modules)?.into_iter() { let module_name = convert(module.name.clone())?; + let mut constant_map = HashMap::new(); + for constant in convert(module.constants)?.into_iter() { + let constant_meta = convert_constant(constant)?; + constant_map.insert(constant_meta.name.clone(), constant_meta); + } + let mut storage_map = HashMap::new(); if let Some(storage) = module.storage { let storage = convert(storage)?; @@ -513,6 +565,7 @@ impl TryFrom for Metadata { index: module.index, name: module_name.clone(), storage: storage_map, + constants: constant_map, }, ); @@ -607,3 +660,18 @@ fn convert_error( ) -> Result { convert(error.name) } + +fn convert_constant( + constant: frame_metadata::ModuleConstantMetadata, +) -> Result { + let name = convert(constant.name)?; + let ty = convert(constant.ty)?; + let value = convert(constant.value)?; + let documentation = convert(constant.documentation)?; + Ok(ModuleConstantMetadata { + name, + ty, + value, + documentation, + }) +}