Update to latest frame-metadata changes

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
This commit is contained in:
Alexandru Vasile
2024-09-16 18:06:00 +03:00
parent b13fcd66b8
commit 46bc4f2312
14 changed files with 658 additions and 15 deletions
Generated
+11 -1
View File
@@ -1830,6 +1830,16 @@ dependencies = [
"scale-info",
]
[[package]]
name = "frame-metadata"
version = "16.0.0"
dependencies = [
"cfg-if",
"parity-scale-codec",
"scale-info",
"serde",
]
[[package]]
name = "frame-metadata"
version = "16.0.0"
@@ -5103,7 +5113,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a616fa51350b35326682a472ee8e6ba742fdacb18babac38ecd46b3e05ead869"
dependencies = [
"frame-metadata 16.0.0",
"frame-metadata 16.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-scale-codec",
"scale-info",
]
+1 -1
View File
@@ -78,7 +78,7 @@ darling = "0.20.10"
derive-where = "1.2.7"
either = { version = "1.13.0", default-features = false }
finito = { version = "0.1.0", default-features = false }
frame-metadata = { version = "16.0.0", default-features = false }
frame-metadata = { path = "/home/lexnv/workspace/frame-metadata/frame-metadata", features = ["current", "decode", "unstable"] }
futures = { version = "0.3.30", default-features = false, features = ["std"] }
getrandom = { version = "0.2", default-features = false }
hashbrown = "0.14.5"
+1 -1
View File
@@ -34,7 +34,7 @@ serde = { workspace = true, features = ["derive"] }
color-eyre = { workspace = true }
serde_json = { workspace = true }
hex = { workspace = true }
frame-metadata = { workspace = true }
frame-metadata = { workspace = true, features = ["current", "decode", "unstable"] }
codec = { package = "parity-scale-codec", workspace = true }
scale-info = { workspace = true }
scale-value = { workspace = true }
+1
View File
@@ -41,6 +41,7 @@ pub struct Opts {
}
pub async fn run(opts: Opts, output: &mut impl Write) -> color_eyre::Result<()> {
println!("opts {:?}", opts);
validate_url_security(opts.file_or_url.url.as_ref(), opts.allow_insecure)?;
let bytes = opts.file_or_url.fetch().await?;
let mut metadata = RuntimeMetadataPrefixed::decode(&mut &bytes[..])?;
+3 -1
View File
@@ -122,7 +122,9 @@ impl FileOrUrl {
// Default if neither is provided; fetch from local url
(None, None, version) => {
let url = Url::parse("ws://localhost:9944").expect("Valid URL; qed");
Ok(fetch_metadata_from_url(url, version.unwrap_or_default()).await?)
let version = version.unwrap_or_default();
// println!("Fetching metadata from {url} with version {version:?}");
Ok(fetch_metadata_from_url(url, version).await?)
}
}
}
+113
View File
@@ -0,0 +1,113 @@
// Copyright 2019-2023 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use std::any::Any;
use super::CodegenError;
use heck::{ToSnakeCase as _, ToUpperCamelCase as _};
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
use scale_typegen::typegen::ir::ToTokensWithSettings;
use scale_typegen::{typegen::ir::type_ir::CompositeIRKind, TypeGenerator};
use subxt_metadata::{AssociatedTypeMetadata, PalletMetadata};
/// The name of the system pallet.
const PALLET_SYSTEM: &str = "System";
/// The name of the system pallet block type.
const PALLET_SYSTEM_BLOCK: &str = "Block";
fn handle_block_type(
type_gen: &TypeGenerator,
pallet: &PalletMetadata,
ty: &AssociatedTypeMetadata,
crate_path: &syn::Path,
) -> Option<TokenStream2> {
// Only handle the system pallet block type.
if pallet.name() != PALLET_SYSTEM || ty.name() != PALLET_SYSTEM_BLOCK {
return None;
}
// println!("System pallet, block type: {:?}", ty);
let resolved_ty = type_gen.resolve_type(ty.type_id()).ok()?;
// First generic param is the header of the chain.
let header = resolved_ty.type_params.get(0)?;
// Second generic param is the unchecked extrinsics.
let extrinsics = resolved_ty.type_params.get(1)?;
let extrinsics_ty = type_gen.resolve_type(extrinsics.ty?.id).ok()?;
// Which contains the Address Type as first generic parameter.
let account_id = extrinsics_ty.type_params.get(0)?;
let resolved_account_id = type_gen.resolve_type_path(account_id.ty?.id).ok()?;
let resolved_account_id = resolved_account_id.to_token_stream(type_gen.settings());
let ty_path = type_gen.resolve_type_path(ty.type_id()).ok()?;
let ty = ty_path.to_token_stream(type_gen.settings());
Some(quote! {
pub type Address = #resolved_account_id;
// TODO: add the header type here.
// pub type Header = <#crate_path::system::Block as #crate_path::Block>::Header;
})
}
/// Generate associated types.
pub fn generate_associated_types(
type_gen: &TypeGenerator,
pallet: &PalletMetadata,
crate_path: &syn::Path,
) -> Result<TokenStream2, CodegenError> {
let associated_types = pallet.associated_types();
let collected = associated_types.iter().map(|ty| {
let name = format_ident!("{}", ty.name());
let docs = type_gen.docs_from_scale_info(&ty.docs());
let Ok(ty_path) = type_gen.resolve_type_path(ty.type_id()) else {
// We don't have the information in the type generator to handle this type.
return quote! {};
};
let maybe_block_ty = handle_block_type(type_gen, pallet, ty, crate_path);
let name_str = ty.name();
let ty = ty_path.to_token_stream(type_gen.settings());
let mut maybe_impl = None;
if name_str == "Hashing" {
// Extract hasher name
let ty_path_str = ty.to_string();
if ty_path_str.contains("BlakeTwo256") {
maybe_impl = Some(quote! {
impl #crate_path::config::Hasher for #ty {
type Output = #crate_path::utils::H256;
fn hash(s: &[u8]) -> Self::Output {
let mut bytes = Vec::new();
#crate_path::storage::utils::hash_bytes(s, #crate_path::storage::utils::StorageHasher::Blake2_256, &mut bytes);
let arr: [u8; 32] = bytes.try_into().expect("Invalid hashing output provided");
arr.into()
}
}
});
}
}
quote! {
#docs
pub type #name = #ty;
// Types extracted from the generic parameters of the system pallet block type.
#maybe_block_ty
// Implementation for the hasher type.
#maybe_impl
}
});
Ok(quote! {
#( #collected )*
})
}
+12
View File
@@ -4,6 +4,7 @@
//! Generate code for submitting extrinsics and query storage of a Substrate runtime.
mod associated_types;
mod calls;
mod constants;
mod custom_values;
@@ -171,10 +172,21 @@ impl RuntimeGenerator {
let errors = errors::generate_error_type_alias(&type_gen, pallet)?;
let associated_types =
associated_types::generate_associated_types(&type_gen, pallet, &crate_path)?;
Ok(quote! {
pub mod #mod_name {
use super::root_mod;
use super::#types_mod_ident;
pub mod associated_types {
use super::root_mod;
use super::#types_mod_ident;
#associated_types
}
#errors
#calls
#event
+4
View File
@@ -143,6 +143,8 @@ async fn fetch_metadata(
Decode::decode(&mut &raw_bytes[..])?
};
// println!(" Metadata version: {supported_versions:?}");
// Return the version the user wants if it's supported:
let version = match version {
MetadataVersion::Latest => *supported_versions
@@ -172,6 +174,8 @@ async fn fetch_metadata(
}
};
// println!(" Metadata version: {version}");
let bytes = version.encode();
let version: String = format!("0x{}", hex::encode(&bytes));
+1 -1
View File
@@ -19,7 +19,7 @@ std = ["scale-info/std", "frame-metadata/std"]
[dependencies]
scale-info = { workspace = true, default-features = false }
frame-metadata = { workspace = true, default-features = false, features = ["current", "decode"] }
frame-metadata = { workspace = true, default-features = false, features = ["current", "decode", "unstable"] }
codec = { package = "parity-scale-codec", workspace = true, default-features = false, features = ["derive"] }
sp-crypto-hashing = { workspace = true }
hashbrown = { workspace = true }
+2
View File
@@ -8,6 +8,7 @@ use alloc::string::String;
mod v14;
mod v15;
mod v16;
/// An error emitted if something goes wrong converting [`frame_metadata`]
/// types into [`crate::Metadata`].
@@ -108,6 +109,7 @@ impl TryFrom<frame_metadata::RuntimeMetadataPrefixed> for crate::Metadata {
}
frame_metadata::RuntimeMetadata::V14(m) => m.try_into(),
frame_metadata::RuntimeMetadata::V15(m) => m.try_into(),
frame_metadata::RuntimeMetadata::V16(m) => m.try_into(),
}
}
}
+4
View File
@@ -2,6 +2,9 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
extern crate alloc;
use alloc::vec::Vec;
use super::TryFromError;
use crate::utils::variant_index::VariantIndex;
@@ -66,6 +69,7 @@ mod from_v15 {
error_variant_index,
constants: constants.collect(),
docs: p.docs,
associated_types: Vec::new(),
},
);
}
+458
View File
@@ -0,0 +1,458 @@
// Copyright 2019-2023 Parity Technologies (UK) Ltd.
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
use super::TryFromError;
use crate::utils::variant_index::VariantIndex;
use crate::{
utils::ordered_map::OrderedMap, ArcStr, ConstantMetadata, ExtrinsicMetadata, Metadata,
OuterEnumsMetadata, PalletMetadataInner, RuntimeApiMetadataInner, RuntimeApiMethodMetadata,
RuntimeApiMethodParamMetadata, SignedExtensionMetadata, StorageEntryMetadata,
StorageEntryModifier, StorageEntryType, StorageHasher, StorageMetadata,
};
use alloc::borrow::ToOwned;
use frame_metadata::v16;
use hashbrown::HashMap;
use scale_info::form::PortableForm;
// Converting from V16 metadata into our Subxt repr.
mod from_v16 {
use frame_metadata::v15;
use crate::AssociatedTypeMetadata;
use super::*;
impl TryFrom<v16::RuntimeMetadataV16> for Metadata {
type Error = TryFromError;
fn try_from(m: v16::RuntimeMetadataV16) -> Result<Self, TryFromError> {
let mut pallets = OrderedMap::new();
let mut pallets_by_index = HashMap::new();
for (pos, p) in m.pallets.into_iter().enumerate() {
let name: ArcStr = p.name.into();
let storage = p.storage.map(|s| StorageMetadata {
prefix: s.prefix,
entries: s
.entries
.into_iter()
.map(|s| {
let name: ArcStr = s.name.clone().into();
(name.clone(), from_storage_entry_metadata(name, s))
})
.collect(),
});
let constants = p.constants.into_iter().map(|c| {
let name: ArcStr = c.name.clone().into();
(name.clone(), from_constant_metadata(name, c))
});
let call_variant_index =
VariantIndex::build(p.calls.as_ref().map(|c| c.ty.id), &m.types);
let error_variant_index =
VariantIndex::build(p.error.as_ref().map(|e| e.ty.id), &m.types);
let event_variant_index =
VariantIndex::build(p.event.as_ref().map(|e| e.ty.id), &m.types);
pallets_by_index.insert(p.index, pos);
pallets.push_insert(
name.clone(),
PalletMetadataInner {
name,
index: p.index,
storage,
call_ty: p.calls.map(|c| c.ty.id),
call_variant_index,
event_ty: p.event.map(|e| e.ty.id),
event_variant_index,
error_ty: p.error.map(|e| e.ty.id),
error_variant_index,
constants: constants.collect(),
docs: p.docs,
associated_types: p
.associated_types
.into_iter()
.map(from_associated_type_metadata)
.collect(),
},
);
}
let apis = m.apis.into_iter().map(|api| {
let name: ArcStr = api.name.clone().into();
(name.clone(), from_runtime_api_metadata(name, api))
});
let dispatch_error_ty = m
.types
.types
.iter()
.find(|ty| ty.ty.path.segments == ["sp_runtime", "DispatchError"])
.map(|ty| ty.id);
Ok(Metadata {
types: m.types,
pallets,
pallets_by_index,
extrinsic: from_extrinsic_metadata(m.extrinsic),
runtime_ty: m.ty.id,
dispatch_error_ty,
apis: apis.collect(),
outer_enums: OuterEnumsMetadata {
call_enum_ty: m.outer_enums.call_enum_ty.id,
event_enum_ty: m.outer_enums.event_enum_ty.id,
error_enum_ty: m.outer_enums.error_enum_ty.id,
},
custom: v15::CustomMetadata {
map: Default::default(),
},
})
}
}
fn from_signed_extension_metadata(
value: v16::SignedExtensionMetadata<PortableForm>,
) -> SignedExtensionMetadata {
SignedExtensionMetadata {
identifier: value.identifier,
extra_ty: value.ty.id,
additional_ty: value.additional_signed.id,
}
}
fn from_extrinsic_metadata(value: v16::ExtrinsicMetadata<PortableForm>) -> ExtrinsicMetadata {
ExtrinsicMetadata {
version: value.version,
signed_extensions: value
.signed_extensions
.into_iter()
.map(from_signed_extension_metadata)
.collect(),
address_ty: value.address_ty.id,
call_ty: value.call_ty.id,
signature_ty: value.signature_ty.id,
extra_ty: value.extra_ty.id,
}
}
fn from_storage_hasher(value: v16::StorageHasher) -> StorageHasher {
match value {
v16::StorageHasher::Blake2_128 => StorageHasher::Blake2_128,
v16::StorageHasher::Blake2_256 => StorageHasher::Blake2_256,
v16::StorageHasher::Blake2_128Concat => StorageHasher::Blake2_128Concat,
v16::StorageHasher::Twox128 => StorageHasher::Twox128,
v16::StorageHasher::Twox256 => StorageHasher::Twox256,
v16::StorageHasher::Twox64Concat => StorageHasher::Twox64Concat,
v16::StorageHasher::Identity => StorageHasher::Identity,
}
}
fn from_storage_entry_type(value: v16::StorageEntryType<PortableForm>) -> StorageEntryType {
match value {
v16::StorageEntryType::Plain(ty) => StorageEntryType::Plain(ty.id),
v16::StorageEntryType::Map {
hashers,
key,
value,
} => StorageEntryType::Map {
hashers: hashers.into_iter().map(from_storage_hasher).collect(),
key_ty: key.id,
value_ty: value.id,
},
}
}
fn from_storage_entry_modifier(value: v16::StorageEntryModifier) -> StorageEntryModifier {
match value {
v16::StorageEntryModifier::Optional => StorageEntryModifier::Optional,
v16::StorageEntryModifier::Default => StorageEntryModifier::Default,
}
}
fn from_associated_type_metadata(
value: v16::PalletAssociatedTypeMetadata<PortableForm>,
) -> AssociatedTypeMetadata {
AssociatedTypeMetadata {
name: value.name,
ty: value.ty.id,
docs: value.docs,
}
}
fn from_storage_entry_metadata(
name: ArcStr,
s: v16::StorageEntryMetadata<PortableForm>,
) -> StorageEntryMetadata {
StorageEntryMetadata {
name,
modifier: from_storage_entry_modifier(s.modifier),
entry_type: from_storage_entry_type(s.ty),
default: s.default,
docs: s.docs,
}
}
fn from_constant_metadata(
name: ArcStr,
s: v16::PalletConstantMetadata<PortableForm>,
) -> ConstantMetadata {
ConstantMetadata {
name,
ty: s.ty.id,
value: s.value,
docs: s.docs,
}
}
fn from_runtime_api_metadata(
name: ArcStr,
s: v16::RuntimeApiMetadata<PortableForm>,
) -> RuntimeApiMetadataInner {
RuntimeApiMetadataInner {
name,
docs: s.docs,
methods: s
.methods
.into_iter()
.map(|m| {
let name: ArcStr = m.name.clone().into();
(name.clone(), from_runtime_api_method_metadata(name, m))
})
.collect(),
}
}
fn from_runtime_api_method_metadata(
name: ArcStr,
s: v16::RuntimeApiMethodMetadata<PortableForm>,
) -> RuntimeApiMethodMetadata {
RuntimeApiMethodMetadata {
name,
inputs: s
.inputs
.into_iter()
.map(from_runtime_api_method_param_metadata)
.collect(),
output_ty: s.output.id,
docs: s.docs,
}
}
fn from_runtime_api_method_param_metadata(
s: v16::RuntimeApiMethodParamMetadata<PortableForm>,
) -> RuntimeApiMethodParamMetadata {
RuntimeApiMethodParamMetadata {
name: s.name,
ty: s.ty.id,
}
}
}
// Converting from our metadata repr to v16 metadata.
mod into_v16 {
use crate::AssociatedTypeMetadata;
use super::*;
impl From<Metadata> for v16::RuntimeMetadataV16 {
fn from(m: Metadata) -> Self {
let pallets = m.pallets.into_values().into_iter().map(|p| {
let storage = p.storage.map(|s| v16::PalletStorageMetadata {
prefix: s.prefix,
entries: s
.entries
.into_values()
.into_iter()
.map(from_storage_entry_metadata)
.collect(),
});
v16::PalletMetadata {
name: (*p.name).to_owned(),
calls: p.call_ty.map(|id| v16::PalletCallMetadata {
ty: id.into(),
deprecation_info: v16::DeprecationInfo::NotDeprecated,
}),
event: p.event_ty.map(|id| v16::PalletEventMetadata {
ty: id.into(),
deprecation_info: v16::DeprecationInfo::NotDeprecated,
}),
error: p.error_ty.map(|id| v16::PalletErrorMetadata {
ty: id.into(),
deprecation_info: v16::DeprecationInfo::NotDeprecated,
}),
storage,
constants: p
.constants
.into_values()
.into_iter()
.map(from_constant_metadata)
.collect(),
index: p.index,
docs: p.docs,
associated_types: p
.associated_types
.into_iter()
.map(from_associated_type_metadata)
.collect(),
deprecation_info: v16::DeprecationStatus::NotDeprecated,
}
});
v16::RuntimeMetadataV16 {
types: m.types,
pallets: pallets.collect(),
ty: m.runtime_ty.into(),
extrinsic: from_extrinsic_metadata(m.extrinsic),
apis: m
.apis
.into_values()
.into_iter()
.map(from_runtime_api_metadata)
.collect(),
outer_enums: v16::OuterEnums {
call_enum_ty: m.outer_enums.call_enum_ty.into(),
event_enum_ty: m.outer_enums.event_enum_ty.into(),
error_enum_ty: m.outer_enums.error_enum_ty.into(),
},
custom: v16::CustomMetadata {
map: Default::default(),
},
}
}
}
fn from_associated_type_metadata(
a: AssociatedTypeMetadata,
) -> v16::PalletAssociatedTypeMetadata<PortableForm> {
v16::PalletAssociatedTypeMetadata {
name: a.name,
ty: a.ty.into(),
docs: a.docs,
}
}
fn from_runtime_api_metadata(
r: RuntimeApiMetadataInner,
) -> v16::RuntimeApiMetadata<PortableForm> {
v16::RuntimeApiMetadata {
name: (*r.name).to_owned(),
methods: r
.methods
.into_values()
.into_iter()
.map(from_runtime_api_method_metadata)
.collect(),
docs: r.docs,
deprecation_info: v16::DeprecationStatus::NotDeprecated,
}
}
fn from_runtime_api_method_metadata(
m: RuntimeApiMethodMetadata,
) -> v16::RuntimeApiMethodMetadata<PortableForm> {
v16::RuntimeApiMethodMetadata {
name: (*m.name).to_owned(),
inputs: m
.inputs
.into_iter()
.map(from_runtime_api_method_param_metadata)
.collect(),
output: m.output_ty.into(),
docs: m.docs,
deprecation_info: v16::DeprecationStatus::NotDeprecated,
}
}
fn from_runtime_api_method_param_metadata(
p: RuntimeApiMethodParamMetadata,
) -> v16::RuntimeApiMethodParamMetadata<PortableForm> {
v16::RuntimeApiMethodParamMetadata {
name: p.name,
ty: p.ty.into(),
}
}
fn from_extrinsic_metadata(e: ExtrinsicMetadata) -> v16::ExtrinsicMetadata<PortableForm> {
v16::ExtrinsicMetadata {
version: e.version,
signed_extensions: e
.signed_extensions
.into_iter()
.map(from_signed_extension_metadata)
.collect(),
address_ty: e.address_ty.into(),
call_ty: e.call_ty.into(),
signature_ty: e.signature_ty.into(),
extra_ty: e.extra_ty.into(),
}
}
fn from_signed_extension_metadata(
s: SignedExtensionMetadata,
) -> v16::SignedExtensionMetadata<PortableForm> {
v16::SignedExtensionMetadata {
identifier: s.identifier,
ty: s.extra_ty.into(),
additional_signed: s.additional_ty.into(),
}
}
fn from_constant_metadata(c: ConstantMetadata) -> v16::PalletConstantMetadata<PortableForm> {
v16::PalletConstantMetadata {
name: (*c.name).to_owned(),
ty: c.ty.into(),
value: c.value,
docs: c.docs,
deprecation_info: v16::DeprecationStatus::NotDeprecated,
}
}
fn from_storage_entry_metadata(
s: StorageEntryMetadata,
) -> v16::StorageEntryMetadata<PortableForm> {
v16::StorageEntryMetadata {
docs: s.docs,
default: s.default,
name: (*s.name).to_owned(),
ty: from_storage_entry_type(s.entry_type),
modifier: from_storage_entry_modifier(s.modifier),
deprecation_info: v16::DeprecationStatus::NotDeprecated,
}
}
fn from_storage_entry_modifier(s: StorageEntryModifier) -> v16::StorageEntryModifier {
match s {
StorageEntryModifier::Default => v16::StorageEntryModifier::Default,
StorageEntryModifier::Optional => v16::StorageEntryModifier::Optional,
}
}
fn from_storage_entry_type(s: StorageEntryType) -> v16::StorageEntryType<PortableForm> {
match s {
StorageEntryType::Plain(ty) => v16::StorageEntryType::Plain(ty.into()),
StorageEntryType::Map {
hashers,
key_ty,
value_ty,
} => v16::StorageEntryType::Map {
hashers: hashers.into_iter().map(from_storage_hasher).collect(),
key: key_ty.into(),
value: value_ty.into(),
},
}
}
fn from_storage_hasher(s: StorageHasher) -> v16::StorageHasher {
match s {
StorageHasher::Blake2_128 => v16::StorageHasher::Blake2_128,
StorageHasher::Blake2_256 => v16::StorageHasher::Blake2_256,
StorageHasher::Blake2_128Concat => v16::StorageHasher::Blake2_128Concat,
StorageHasher::Twox128 => v16::StorageHasher::Twox128,
StorageHasher::Twox256 => v16::StorageHasher::Twox256,
StorageHasher::Twox64Concat => v16::StorageHasher::Twox64Concat,
StorageHasher::Identity => v16::StorageHasher::Identity,
}
}
}
+36
View File
@@ -230,6 +230,11 @@ impl<'a> PalletMetadata<'a> {
)
}
/// Return all of the associated types.
pub fn associated_types(&self) -> &'a [AssociatedTypeMetadata] {
&self.inner.associated_types
}
/// Return all of the call variants, if a call type exists.
pub fn call_variants(&self) -> Option<&'a [Variant<PortableForm>]> {
VariantIndex::get(self.inner.call_ty, self.types)
@@ -318,6 +323,36 @@ struct PalletMetadataInner {
constants: OrderedMap<ArcStr, ConstantMetadata>,
/// Pallet documentation.
docs: Vec<String>,
/// Pallet associated types.
associated_types: Vec<AssociatedTypeMetadata>,
}
/// Metadata for an associated type.
#[derive(Debug, Clone)]
pub struct AssociatedTypeMetadata {
/// Name of the associated type.
name: String,
/// Type of the associated type.
ty: u32,
/// Associated type documentation.
docs: Vec<String>,
}
impl AssociatedTypeMetadata {
/// Name of the associated type.
pub fn name(&self) -> &str {
&self.name
}
/// Type id of the associated type.
pub fn type_id(&self) -> u32 {
self.ty
}
/// Associated type documentation.
pub fn docs(&self) -> &[String] {
&self.docs
}
}
/// Metadata for the storage entries in a pallet.
@@ -773,6 +808,7 @@ impl codec::Decode for Metadata {
let metadata = match metadata.1 {
frame_metadata::RuntimeMetadata::V14(md) => md.try_into(),
frame_metadata::RuntimeMetadata::V15(md) => md.try_into(),
frame_metadata::RuntimeMetadata::V16(md) => md.try_into(),
_ => return Err("Cannot try_into() to Metadata: unsupported metadata version".into()),
};
+11 -10
View File
@@ -5,7 +5,10 @@ use subxt_core::config::{Config, DefaultExtrinsicParams};
use subxt_signer::sr25519::dev;
// Generate an interface that we can use from the node's metadata.
#[subxt::subxt(runtime_metadata_insecure_url = "ws://localhost:9999")]
#[subxt::subxt(
runtime_metadata_insecure_url = "ws://localhost:9944",
unstable_metadata
)]
pub mod polkadot {}
// Derives aren't strictly needed, they just make developer life easier.
@@ -14,10 +17,10 @@ pub enum MetadataConfig {}
impl Config for MetadataConfig {
// Extracted from metadata directly:
type Hash = polkadot::custom_types::Hash;
type AccountId = polkadot::custom_types::AccountId;
type AssetId = polkadot::custom_types::AssetId;
type Address = polkadot::custom_types::Address;
type Hash = polkadot::system::associated_types::Hash;
type AccountId = polkadot::system::associated_types::AccountId;
type AssetId = polkadot::assets::associated_types::AssetId;
type Address = polkadot::system::associated_types::Address;
// Present in metadata but this PoC needs to add
// fn specific per name of type to impl the hashing fn.
@@ -25,7 +28,7 @@ impl Config for MetadataConfig {
//
// TODO: Eventually extend this to a DynamicHasher object instead.
// Similar logic already exists for StorageHasher.
type Hasher = polkadot::custom_types::Hashing;
type Hasher = polkadot::system::associated_types::Hashing;
// Present in metadata but this PoC needs to impl the header
// trait to make use of this.
@@ -37,13 +40,11 @@ impl Config for MetadataConfig {
// generated hasher to expose the same information, this is not
// as robust and codgen can be used instead.
// type Header = polkadot::custom_types::Header;
type Header =
SubstrateHeader<polkadot::custom_types::HeaderNumber, polkadot::custom_types::Hashing>;
type Header = SubstrateHeader<u32, polkadot::system::associated_types::Hashing>;
// Same story, present in md but needs subxt::tx::Signer<T>.
// type Signature = polkadot::custom_types::Signature;
type Signature = <SubstrateConfig as Config>::Signature;
// Not exposed in metadata, seems like heavily involved with
// code functionality which cannot safely be expressed in the
// metadata.
@@ -53,7 +54,7 @@ impl Config for MetadataConfig {
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a new API client, configured to talk to nodes.
let api = OnlineClient::<MetadataConfig>::from_insecure_url("ws://localhost:9999").await?;
let api = OnlineClient::<MetadataConfig>::from_insecure_url("ws://localhost:9944").await?;
// Build a balance transfer extrinsic.
let dest = dev::bob().public_key().into();