use super::u8_map::U8Map;
use super::{Metadata, MetadataCalls, MetadataError, MetadataExtrinsic, MetadataPalletCalls, MetadataPalletStorage};
use frame_metadata::RuntimeMetadataV14;
pub fn decode(meta: RuntimeMetadataV14) -> Result<Metadata, MetadataError> {
let registry = meta.types;
let mut pallet_calls_by_index = U8Map::new();
let mut pallet_storage = Vec::new();
let extrinsic =
MetadataExtrinsic { version: meta.extrinsic.version, signed_extensions: meta.extrinsic.signed_extensions };
for pallet in meta.pallets {
let calls = pallet
.calls
.map(|call_md| {
let calls_type_id = call_md.ty;
let calls_type = registry
.resolve(calls_type_id.id())
.ok_or_else(|| MetadataError::TypeNotFound(calls_type_id.id()))?;
let calls_type_def = calls_type.type_def();
let calls_variant = match calls_type_def {
scale_info::TypeDef::Variant(variant) => variant,
_ => {
return Err(MetadataError::ExpectedVariantType { got: format!("{:?}", calls_type_def) });
}
};
let call_variant_indexes =
calls_variant.variants().iter().enumerate().map(|(idx, v)| (v.index(), idx)).collect();
Ok(MetadataCalls { calls_type_id, call_variant_indexes })
})
.transpose()?;
pallet_calls_by_index.insert(pallet.index, MetadataPalletCalls { name: pallet.name, calls });
if let Some(storage_metadata) = pallet.storage {
pallet_storage.push(MetadataPalletStorage {
prefix: storage_metadata.prefix,
storage_entries: storage_metadata.entries.into(),
});
}
}
Ok(Metadata { pallet_calls_by_index, pallet_storage: pallet_storage.into(), extrinsic, types: registry })
}