mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 09:21:05 +00:00
Use substrate metadata, introduce builder for client (#4)
* Export Error type * Fix license headers * Remove unnecessary fully qualified associated types * Update to parity-scale-codec, handles decoding errors * rustfmt * Add metadata. * Use metadata for calls. * Refactor generics. * Storage metadata. * Use builders. * Finish making generic. * Fix merge. * Run rustfmt. * Fix merge.
This commit is contained in:
committed by
Andrew Jones
parent
6522bb08d0
commit
19604e8f2e
+162
@@ -0,0 +1,162 @@
|
||||
use parity_scale_codec::Encode;
|
||||
use runtime_metadata::{
|
||||
DecodeDifferent,
|
||||
RuntimeMetadata,
|
||||
RuntimeMetadataPrefixed,
|
||||
StorageEntryModifier,
|
||||
StorageEntryType,
|
||||
StorageHasher,
|
||||
META_RESERVED,
|
||||
};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
convert::TryFrom,
|
||||
};
|
||||
use substrate_primitives::storage::StorageKey;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Metadata {
|
||||
modules: HashMap<String, ModuleMetadata>,
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
pub fn module(&self, name: &str) -> Option<&ModuleMetadata> {
|
||||
self.modules.get(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ModuleMetadata {
|
||||
index: u8,
|
||||
storage: HashMap<String, StorageMetadata>,
|
||||
// calls, event, constants
|
||||
}
|
||||
|
||||
impl ModuleMetadata {
|
||||
pub fn call<T: Encode>(&self, call: T) -> Vec<u8> {
|
||||
let mut bytes = vec![self.index];
|
||||
bytes.extend(call.encode());
|
||||
bytes
|
||||
}
|
||||
|
||||
pub fn storage(&self, key: &str) -> Option<&StorageMetadata> {
|
||||
self.storage.get(key)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StorageMetadata {
|
||||
prefix: String,
|
||||
modifier: StorageEntryModifier,
|
||||
ty: StorageEntryType,
|
||||
default: Vec<u8>,
|
||||
}
|
||||
|
||||
impl StorageMetadata {
|
||||
pub fn map(&self) -> Option<StorageMap> {
|
||||
match &self.ty {
|
||||
StorageEntryType::Map { hasher, .. } => {
|
||||
let prefix = self.prefix.as_bytes().to_vec();
|
||||
let hasher = hasher.to_owned();
|
||||
Some(StorageMap { prefix, hasher })
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct StorageMap {
|
||||
prefix: Vec<u8>,
|
||||
hasher: StorageHasher,
|
||||
}
|
||||
|
||||
impl StorageMap {
|
||||
pub fn key<K: Encode>(&self, key: K) -> StorageKey {
|
||||
let mut bytes = self.prefix.clone();
|
||||
bytes.extend(key.encode());
|
||||
let hash = match self.hasher {
|
||||
StorageHasher::Blake2_128 => {
|
||||
substrate_primitives::blake2_128(&bytes).to_vec()
|
||||
}
|
||||
StorageHasher::Blake2_256 => {
|
||||
substrate_primitives::blake2_256(&bytes).to_vec()
|
||||
}
|
||||
StorageHasher::Twox128 => substrate_primitives::twox_128(&bytes).to_vec(),
|
||||
StorageHasher::Twox256 => substrate_primitives::twox_256(&bytes).to_vec(),
|
||||
StorageHasher::Twox64Concat => substrate_primitives::twox_64(&bytes).to_vec(),
|
||||
};
|
||||
StorageKey(hash)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
InvalidPrefix,
|
||||
InvalidVersion,
|
||||
ExpectedDecoded,
|
||||
}
|
||||
|
||||
impl TryFrom<RuntimeMetadataPrefixed> for Metadata {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(metadata: RuntimeMetadataPrefixed) -> Result<Self, Self::Error> {
|
||||
if metadata.0 != META_RESERVED {
|
||||
Err(Error::InvalidPrefix)?;
|
||||
}
|
||||
let meta = match metadata.1 {
|
||||
RuntimeMetadata::V7(meta) => meta,
|
||||
_ => Err(Error::InvalidVersion)?,
|
||||
};
|
||||
let mut modules = HashMap::new();
|
||||
for (i, module) in convert(meta.modules)?.into_iter().enumerate() {
|
||||
modules.insert(
|
||||
convert(module.name.clone())?,
|
||||
convert_module(i as u8, module)?,
|
||||
);
|
||||
}
|
||||
Ok(Metadata { modules })
|
||||
}
|
||||
}
|
||||
|
||||
fn convert<B: 'static, O: 'static>(dd: DecodeDifferent<B, O>) -> Result<O, Error> {
|
||||
match dd {
|
||||
DecodeDifferent::Decoded(value) => Ok(value),
|
||||
_ => Err(Error::ExpectedDecoded),
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_module(
|
||||
index: u8,
|
||||
module: runtime_metadata::ModuleMetadata,
|
||||
) -> Result<ModuleMetadata, Error> {
|
||||
let mut entries = HashMap::new();
|
||||
if let Some(storage) = module.storage {
|
||||
let storage = convert(storage)?;
|
||||
let prefix = convert(storage.prefix)?;
|
||||
for entry in convert(storage.entries)?.into_iter() {
|
||||
let entry_name = convert(entry.name.clone())?;
|
||||
let entry_prefix = format!("{} {}", prefix, entry_name);
|
||||
let entry = convert_entry(entry_prefix, entry)?;
|
||||
entries.insert(entry_name, entry);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ModuleMetadata {
|
||||
index,
|
||||
storage: entries,
|
||||
})
|
||||
}
|
||||
|
||||
fn convert_entry(
|
||||
prefix: String,
|
||||
entry: runtime_metadata::StorageEntryMetadata,
|
||||
) -> Result<StorageMetadata, Error> {
|
||||
let default = convert(entry.default)?;
|
||||
Ok(StorageMetadata {
|
||||
prefix,
|
||||
modifier: entry.modifier,
|
||||
ty: entry.ty,
|
||||
default,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user