From 0440bfaadca98f827e347e3e2162dbe1456dbd93 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 2 May 2024 12:03:46 +0000 Subject: [PATCH 1/9] codegen: Export custom types from md to separate module Signed-off-by: Alexandru Vasile --- codegen/src/api/custom_values.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/codegen/src/api/custom_values.rs b/codegen/src/api/custom_values.rs index dd577d6e74..e567900ab0 100644 --- a/codegen/src/api/custom_values.rs +++ b/codegen/src/api/custom_values.rs @@ -19,6 +19,17 @@ pub fn generate_custom_values( ) -> TokenStream2 { let mut fn_names_taken = HashSet::new(); let custom = metadata.custom(); + let custom_types = custom.iter().map(|custom| { + let name = custom.name(); + let Ok(ty) = type_gen.resolve_type_path(custom.type_id()) else { + return quote! {}; + }; + let ty = ty.to_token_stream(type_gen.settings()); + quote! { + type #name = #ty; + } + }); + let custom_values_fns = custom.iter().filter_map(|custom_value| { generate_custom_value_fn(custom_value, type_gen, crate_path, &mut fn_names_taken) }); @@ -29,6 +40,10 @@ pub fn generate_custom_values( impl CustomValuesApi { #(#custom_values_fns)* } + + pub mod custom_types { + #(#custom_types)* + } } } From 7c73b6d32c9b6ca2440595bf21a389d3bfdf3451 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 2 May 2024 12:04:04 +0000 Subject: [PATCH 2/9] config: Add config notes about extracted values Signed-off-by: Alexandru Vasile --- core/src/config/polkadot.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/core/src/config/polkadot.rs b/core/src/config/polkadot.rs index 7f4e3a88f9..160c25a2df 100644 --- a/core/src/config/polkadot.rs +++ b/core/src/config/polkadot.rs @@ -17,14 +17,22 @@ pub use primitive_types::{H256, U256}; pub enum PolkadotConfig {} impl Config for PolkadotConfig { - type Hash = ::Hash; - type AccountId = ::AccountId; - type Address = MultiAddress; - type Signature = ::Signature; - type Hasher = ::Hasher; - type Header = ::Header; + // coming from: System::Config + type Hash = ::Hash; // Done + type AccountId = ::AccountId; // Done + type Hasher = ::Hasher; // Done + + // coming from ::Extrinsic type + type Address = MultiAddress; // Done + type Signature = ::Signature; // Done + + // coming from ::Header type + type Header = ::Header; // Done + type ExtrinsicParams = PolkadotExtrinsicParams; - type AssetId = u32; + + // coming from Assets::Config (interested in foreign Assets specifically) + type AssetId = u32; // Done } /// A struct representing the signed extra and additional parameters required From 21bbdc4855b51614272af79ce817b21430e868e7 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 2 May 2024 12:09:09 +0000 Subject: [PATCH 3/9] codegen: Use quote::idents instead of &str for naming types Signed-off-by: Alexandru Vasile --- codegen/src/api/custom_values.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/codegen/src/api/custom_values.rs b/codegen/src/api/custom_values.rs index e567900ab0..0b0815fab5 100644 --- a/codegen/src/api/custom_values.rs +++ b/codegen/src/api/custom_values.rs @@ -9,7 +9,7 @@ use std::collections::HashSet; use subxt_metadata::{CustomValueMetadata, Metadata}; use proc_macro2::TokenStream as TokenStream2; -use quote::quote; +use quote::{format_ident, quote}; /// Generate the custom values mod, if there are any custom values in the metadata. Else returns None. pub fn generate_custom_values( @@ -20,7 +20,8 @@ pub fn generate_custom_values( let mut fn_names_taken = HashSet::new(); let custom = metadata.custom(); let custom_types = custom.iter().map(|custom| { - let name = custom.name(); + let name = format_ident!("{}", custom.name()); + let Ok(ty) = type_gen.resolve_type_path(custom.type_id()) else { return quote! {}; }; From df101a1ae9fa7e91d905950845e435ea56ecb541 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 2 May 2024 12:34:58 +0000 Subject: [PATCH 4/9] codegen: Make super types available for custom ty Signed-off-by: Alexandru Vasile --- codegen/src/api/custom_values.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/codegen/src/api/custom_values.rs b/codegen/src/api/custom_values.rs index 0b0815fab5..ef6929a454 100644 --- a/codegen/src/api/custom_values.rs +++ b/codegen/src/api/custom_values.rs @@ -27,7 +27,7 @@ pub fn generate_custom_values( }; let ty = ty.to_token_stream(type_gen.settings()); quote! { - type #name = #ty; + pub type #name = #ty; } }); @@ -43,6 +43,8 @@ pub fn generate_custom_values( } pub mod custom_types { + pub use super::*; + #(#custom_types)* } } From a1434a9764707e205852b6755bf7cb6eeb88ba74 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Thu, 2 May 2024 12:35:42 +0000 Subject: [PATCH 5/9] example: Create an example Config out of the MetadataConfig Signed-off-by: Alexandru Vasile --- subxt/examples/metadata_config.rs | 63 +++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 subxt/examples/metadata_config.rs diff --git a/subxt/examples/metadata_config.rs b/subxt/examples/metadata_config.rs new file mode 100644 index 0000000000..2d1dc9ec98 --- /dev/null +++ b/subxt/examples/metadata_config.rs @@ -0,0 +1,63 @@ +#![allow(missing_docs)] +use subxt::{OnlineClient, SubstrateConfig}; +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")] +pub mod polkadot {} + +// Derives aren't strictly needed, they just make developer life easier. +#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] +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; + + // Present in metadata but this PoC needs to add + // fn specific per name of type to impl the hashing fn. + type Hasher = ::Hasher; + // Present in metadata but this PoC needs to impl the header + // trait to make use of this. + type Header = ::Header; + // Same story, present in md but needs subxt::tx::Signer. + // type Signature = polkadot::custom_types::Signature; + type Signature = ::Signature; + + // Not exposed in metadata, seems like heavily involved with + // code functionality which cannot safely be expressed in the + // metadata. + type ExtrinsicParams = DefaultExtrinsicParams; +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Create a new API client, configured to talk to nodes. + let api = OnlineClient::::from_insecure_url("ws://localhost:9999").await?; + + // Build a balance transfer extrinsic. + let dest = dev::bob().public_key().into(); + let balance_transfer_tx = polkadot::tx().balances().transfer_allow_death(dest, 10_000); + + // Submit the balance transfer extrinsic from Alice, and wait for it to be successful + // and in a finalized block. We get back the extrinsic events if all is well. + let from = dev::alice(); + let events = api + .tx() + .sign_and_submit_then_watch_default(&balance_transfer_tx, &from) + .await? + .wait_for_finalized_success() + .await?; + + // Find a Transfer event and print it. + let transfer_event = events.find_first::()?; + if let Some(event) = transfer_event { + println!("Balance transfer success: {event:?}"); + } + + Ok(()) +} From 609b701d4d1e60e4f6e85e2082e0c1a7d51e2306 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 8 May 2024 08:34:52 +0000 Subject: [PATCH 6/9] config: Handle hasher and header Signed-off-by: Alexandru Vasile --- codegen/src/api/custom_values.rs | 108 ++++++++++++++++++++++++++++-- core/src/storage/mod.rs | 2 +- core/src/storage/utils.rs | 3 +- subxt/examples/metadata_config.rs | 20 +++++- 4 files changed, 125 insertions(+), 8 deletions(-) diff --git a/codegen/src/api/custom_values.rs b/codegen/src/api/custom_values.rs index ef6929a454..315a008f4c 100644 --- a/codegen/src/api/custom_values.rs +++ b/codegen/src/api/custom_values.rs @@ -3,9 +3,10 @@ // see LICENSE for license details. use heck::ToSnakeCase as _; +use scale_info::{TypeDef, TypeDefComposite}; use scale_typegen::typegen::ir::ToTokensWithSettings; use scale_typegen::TypeGenerator; -use std::collections::HashSet; +use std::{any::Any, collections::HashSet}; use subxt_metadata::{CustomValueMetadata, Metadata}; use proc_macro2::TokenStream as TokenStream2; @@ -20,14 +21,113 @@ pub fn generate_custom_values( let mut fn_names_taken = HashSet::new(); let custom = metadata.custom(); let custom_types = custom.iter().map(|custom| { - let name = format_ident!("{}", custom.name()); + let name_str = custom.name(); - let Ok(ty) = type_gen.resolve_type_path(custom.type_id()) else { + let name = format_ident!("{}", name_str); + + let Ok(ty_path) = type_gen.resolve_type_path(custom.type_id()) else { return quote! {}; }; - let ty = ty.to_token_stream(type_gen.settings()); + let ty = ty_path.to_token_stream(type_gen.settings()); + + let mut maybe_impl = None; + let mut extra = 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() + } + } + }); + } + } + + if name_str == "Header" { + // Extract header number from the provided type. + let Ok(ty_res) = type_gen.resolve_type(custom.type_id()) else { + return quote! {}; + }; + + let TypeDef::Composite(composite) = &ty_res.type_def else { + return quote! {}; + }; + + // Sanity check for the number type. + let number_ty = composite.fields.iter().find_map( + |field| if let Some(n) = &field.name { + if n == "number" { + Some(field.ty.id) + } else { + None + } + } else { + None + } + ); + + if let Some(num) = number_ty { + + let Ok(ty_path) = type_gen.resolve_type_path(num) else { + return quote! {}; + }; + + if !ty_path.is_compact() { + let ty = ty_path.to_token_stream(type_gen.settings()); + + extra = Some(quote! { + pub type HeaderNumber = #ty; + }); + } else { + // Ty is compact. + let Ok(ty_res) = type_gen.resolve_type(num) else { + return quote! {}; + }; + + let TypeDef::Compact(compact) = &ty_res.type_def else { + return quote! {}; + }; + let compact_ty_id = compact.type_param.id; + + let Ok(ty_path) = type_gen.resolve_type_path(compact_ty_id) else { + return quote! {}; + }; + let ty = ty_path.to_token_stream(type_gen.settings()); + + extra = Some(quote! { + pub type HeaderNumber = #ty; + }); + } + + + maybe_impl = Some(quote! { + impl #crate_path::config::Header for #ty { + type Number = HeaderNumber; + type Hasher = Hashing; + + // If we got to this point, the `number` field exists on the header + // structure. + fn number(&self) -> Self::Number { + self.number + } + } + }); + } + } + quote! { pub type #name = #ty; + + #maybe_impl + #extra } }); diff --git a/core/src/storage/mod.rs b/core/src/storage/mod.rs index c11957a665..a019ce82ab 100644 --- a/core/src/storage/mod.rs +++ b/core/src/storage/mod.rs @@ -42,7 +42,7 @@ //! ``` mod storage_key; -mod utils; +pub mod utils; pub mod address; diff --git a/core/src/storage/utils.rs b/core/src/storage/utils.rs index dc5d10ace4..6a891c455e 100644 --- a/core/src/storage/utils.rs +++ b/core/src/storage/utils.rs @@ -11,7 +11,8 @@ use crate::error::{Error, MetadataError}; use crate::metadata::Metadata; use alloc::borrow::ToOwned; use alloc::vec::Vec; -use subxt_metadata::{PalletMetadata, StorageEntryMetadata, StorageHasher}; +pub use subxt_metadata::StorageHasher; +use subxt_metadata::{PalletMetadata, StorageEntryMetadata}; /// Return the root of a given [`Address`]: hash the pallet name and entry name /// and append those bytes to the output. diff --git a/subxt/examples/metadata_config.rs b/subxt/examples/metadata_config.rs index 2d1dc9ec98..ca3b3850b2 100644 --- a/subxt/examples/metadata_config.rs +++ b/subxt/examples/metadata_config.rs @@ -1,5 +1,6 @@ #![allow(missing_docs)] use subxt::{OnlineClient, SubstrateConfig}; +use subxt_core::config::substrate::SubstrateHeader; use subxt_core::config::{Config, DefaultExtrinsicParams}; use subxt_signer::sr25519::dev; @@ -20,10 +21,25 @@ impl Config for MetadataConfig { // Present in metadata but this PoC needs to add // fn specific per name of type to impl the hashing fn. - type Hasher = ::Hasher; + // type Hasher = ::Hasher; + // + // TODO: Eventually extend this to a DynamicHasher object instead. + // Similar logic already exists for StorageHasher. + type Hasher = polkadot::custom_types::Hashing; + // Present in metadata but this PoC needs to impl the header // trait to make use of this. - type Header = ::Header; + // type Header = ::Header; + + // The metadata header type must implement `Deserialize`, which + // must be manually implemented for the Digest logs of the header. + // An alternative is to extract the header number and use the + // 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; + // Same story, present in md but needs subxt::tx::Signer. // type Signature = polkadot::custom_types::Signature; type Signature = ::Signature; From 46bc4f23125ee1a2049e34295db0d960f5398d1c Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 16 Sep 2024 18:06:00 +0300 Subject: [PATCH 7/9] Update to latest frame-metadata changes Signed-off-by: Alexandru Vasile --- Cargo.lock | 12 +- Cargo.toml | 2 +- cli/Cargo.toml | 2 +- cli/src/commands/metadata.rs | 1 + cli/src/utils.rs | 4 +- codegen/src/api/associated_types.rs | 113 +++++++ codegen/src/api/mod.rs | 12 + codegen/src/fetch_metadata.rs | 4 + metadata/Cargo.toml | 2 +- metadata/src/from_into/mod.rs | 2 + metadata/src/from_into/v15.rs | 4 + metadata/src/from_into/v16.rs | 458 ++++++++++++++++++++++++++++ metadata/src/lib.rs | 36 +++ subxt/examples/metadata_config.rs | 21 +- 14 files changed, 658 insertions(+), 15 deletions(-) create mode 100644 codegen/src/api/associated_types.rs create mode 100644 metadata/src/from_into/v16.rs diff --git a/Cargo.lock b/Cargo.lock index 56902d35cd..1fe8d12457 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", ] diff --git a/Cargo.toml b/Cargo.toml index 9803a00183..dabba45830 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index d6392da894..c4bc640fec 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -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 } diff --git a/cli/src/commands/metadata.rs b/cli/src/commands/metadata.rs index 292ca1c7a5..0263416f9c 100644 --- a/cli/src/commands/metadata.rs +++ b/cli/src/commands/metadata.rs @@ -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[..])?; diff --git a/cli/src/utils.rs b/cli/src/utils.rs index 624d5256ae..e4cce6b314 100644 --- a/cli/src/utils.rs +++ b/cli/src/utils.rs @@ -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?) } } } diff --git a/codegen/src/api/associated_types.rs b/codegen/src/api/associated_types.rs new file mode 100644 index 0000000000..8e0a086ce3 --- /dev/null +++ b/codegen/src/api/associated_types.rs @@ -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 { + // 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 { + 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 )* + }) +} diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs index 7a8e8eee2f..9553e43916 100644 --- a/codegen/src/api/mod.rs +++ b/codegen/src/api/mod.rs @@ -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 diff --git a/codegen/src/fetch_metadata.rs b/codegen/src/fetch_metadata.rs index ee7c554013..7b485f43d4 100644 --- a/codegen/src/fetch_metadata.rs +++ b/codegen/src/fetch_metadata.rs @@ -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)); diff --git a/metadata/Cargo.toml b/metadata/Cargo.toml index 0ad5316100..bdc8edb93f 100644 --- a/metadata/Cargo.toml +++ b/metadata/Cargo.toml @@ -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 } diff --git a/metadata/src/from_into/mod.rs b/metadata/src/from_into/mod.rs index 13bb2f40c2..12d54c87a5 100644 --- a/metadata/src/from_into/mod.rs +++ b/metadata/src/from_into/mod.rs @@ -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 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(), } } } diff --git a/metadata/src/from_into/v15.rs b/metadata/src/from_into/v15.rs index 37e4336543..026d854409 100644 --- a/metadata/src/from_into/v15.rs +++ b/metadata/src/from_into/v15.rs @@ -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(), }, ); } diff --git a/metadata/src/from_into/v16.rs b/metadata/src/from_into/v16.rs new file mode 100644 index 0000000000..6455778385 --- /dev/null +++ b/metadata/src/from_into/v16.rs @@ -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 for Metadata { + type Error = TryFromError; + fn try_from(m: v16::RuntimeMetadataV16) -> Result { + 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, + ) -> SignedExtensionMetadata { + SignedExtensionMetadata { + identifier: value.identifier, + extra_ty: value.ty.id, + additional_ty: value.additional_signed.id, + } + } + + fn from_extrinsic_metadata(value: v16::ExtrinsicMetadata) -> 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) -> 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, + ) -> AssociatedTypeMetadata { + AssociatedTypeMetadata { + name: value.name, + ty: value.ty.id, + docs: value.docs, + } + } + + fn from_storage_entry_metadata( + name: ArcStr, + s: v16::StorageEntryMetadata, + ) -> 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, + ) -> ConstantMetadata { + ConstantMetadata { + name, + ty: s.ty.id, + value: s.value, + docs: s.docs, + } + } + + fn from_runtime_api_metadata( + name: ArcStr, + s: v16::RuntimeApiMetadata, + ) -> 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, + ) -> 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, + ) -> 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 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 { + v16::PalletAssociatedTypeMetadata { + name: a.name, + ty: a.ty.into(), + docs: a.docs, + } + } + + fn from_runtime_api_metadata( + r: RuntimeApiMetadataInner, + ) -> v16::RuntimeApiMetadata { + 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 { + 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 { + v16::RuntimeApiMethodParamMetadata { + name: p.name, + ty: p.ty.into(), + } + } + + fn from_extrinsic_metadata(e: ExtrinsicMetadata) -> v16::ExtrinsicMetadata { + 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 { + v16::SignedExtensionMetadata { + identifier: s.identifier, + ty: s.extra_ty.into(), + additional_signed: s.additional_ty.into(), + } + } + + fn from_constant_metadata(c: ConstantMetadata) -> v16::PalletConstantMetadata { + 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 { + 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 { + 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, + } + } +} diff --git a/metadata/src/lib.rs b/metadata/src/lib.rs index fb86ddcbef..b273ee6535 100644 --- a/metadata/src/lib.rs +++ b/metadata/src/lib.rs @@ -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]> { VariantIndex::get(self.inner.call_ty, self.types) @@ -318,6 +323,36 @@ struct PalletMetadataInner { constants: OrderedMap, /// Pallet documentation. docs: Vec, + /// Pallet associated types. + associated_types: Vec, +} + +/// 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, +} + +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()), }; diff --git a/subxt/examples/metadata_config.rs b/subxt/examples/metadata_config.rs index ca3b3850b2..37ff32b202 100644 --- a/subxt/examples/metadata_config.rs +++ b/subxt/examples/metadata_config.rs @@ -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; + type Header = SubstrateHeader; // Same story, present in md but needs subxt::tx::Signer. // type Signature = polkadot::custom_types::Signature; type Signature = ::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> { // Create a new API client, configured to talk to nodes. - let api = OnlineClient::::from_insecure_url("ws://localhost:9999").await?; + let api = OnlineClient::::from_insecure_url("ws://localhost:9944").await?; // Build a balance transfer extrinsic. let dest = dev::bob().public_key().into(); From d35454679bfca952e61617172ca07472372c0029 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 16 Sep 2024 19:14:31 +0300 Subject: [PATCH 8/9] metadata: Handle new format of v16 Signed-off-by: Alexandru Vasile --- metadata/src/from_into/v16.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/metadata/src/from_into/v16.rs b/metadata/src/from_into/v16.rs index 6455778385..85b6b00bfa 100644 --- a/metadata/src/from_into/v16.rs +++ b/metadata/src/from_into/v16.rs @@ -12,6 +12,7 @@ use crate::{ StorageEntryModifier, StorageEntryType, StorageHasher, StorageMetadata, }; use alloc::borrow::ToOwned; +use alloc::vec; use frame_metadata::v16; use hashbrown::HashMap; use scale_info::form::PortableForm; @@ -96,7 +97,7 @@ mod from_v16 { pallets, pallets_by_index, extrinsic: from_extrinsic_metadata(m.extrinsic), - runtime_ty: m.ty.id, + runtime_ty: 0, dispatch_error_ty, apis: apis.collect(), outer_enums: OuterEnumsMetadata { @@ -112,7 +113,7 @@ mod from_v16 { } fn from_signed_extension_metadata( - value: v16::SignedExtensionMetadata, + value: v16::TransactionExtensionMetadata, ) -> SignedExtensionMetadata { SignedExtensionMetadata { identifier: value.identifier, @@ -123,9 +124,9 @@ mod from_v16 { fn from_extrinsic_metadata(value: v16::ExtrinsicMetadata) -> ExtrinsicMetadata { ExtrinsicMetadata { - version: value.version, + version: value.versions[0], signed_extensions: value - .signed_extensions + .transaction_extensions .into_iter() .map(from_signed_extension_metadata) .collect(), @@ -303,7 +304,6 @@ mod into_v16 { v16::RuntimeMetadataV16 { types: m.types, pallets: pallets.collect(), - ty: m.runtime_ty.into(), extrinsic: from_extrinsic_metadata(m.extrinsic), apis: m .apis @@ -376,8 +376,8 @@ mod into_v16 { fn from_extrinsic_metadata(e: ExtrinsicMetadata) -> v16::ExtrinsicMetadata { v16::ExtrinsicMetadata { - version: e.version, - signed_extensions: e + versions: vec![e.version], + transaction_extensions: e .signed_extensions .into_iter() .map(from_signed_extension_metadata) @@ -391,8 +391,8 @@ mod into_v16 { fn from_signed_extension_metadata( s: SignedExtensionMetadata, - ) -> v16::SignedExtensionMetadata { - v16::SignedExtensionMetadata { + ) -> v16::TransactionExtensionMetadata { + v16::TransactionExtensionMetadata { identifier: s.identifier, ty: s.extra_ty.into(), additional_signed: s.additional_ty.into(), From 59b9d10e8fed4a85ee784e21aabc0f39699b2ac4 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Mon, 16 Sep 2024 19:16:23 +0300 Subject: [PATCH 9/9] cargo: Update frame-metadata to git dep Signed-off-by: Alexandru Vasile --- Cargo.lock | 21 +++++++++++---------- Cargo.toml | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1fe8d12457..3ea56157b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1833,6 +1833,8 @@ dependencies = [ [[package]] name = "frame-metadata" version = "16.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" dependencies = [ "cfg-if", "parity-scale-codec", @@ -1843,8 +1845,7 @@ dependencies = [ [[package]] name = "frame-metadata" version = "16.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cf1549fba25a6fcac22785b61698317d958e96cac72a59102ea45b9ae64692" +source = "git+https://github.com/paritytech/frame-metadata.git?branch=lexnv/metadata-v16-associated-types#ede6a4dda012a101e46eea7a44a410a13b46867f" dependencies = [ "cfg-if", "parity-scale-codec", @@ -1993,7 +1994,7 @@ dependencies = [ name = "generate-custom-metadata" version = "0.37.0" dependencies = [ - "frame-metadata 16.0.0", + "frame-metadata 16.0.0 (git+https://github.com/paritytech/frame-metadata.git?branch=lexnv/metadata-v16-associated-types)", "parity-scale-codec", "scale-info", ] @@ -2535,7 +2536,7 @@ version = "0.37.0" dependencies = [ "assert_matches", "cfg_aliases", - "frame-metadata 16.0.0", + "frame-metadata 16.0.0 (git+https://github.com/paritytech/frame-metadata.git?branch=lexnv/metadata-v16-associated-types)", "futures", "hex", "parity-scale-codec", @@ -5615,7 +5616,7 @@ dependencies = [ "derive-where", "either", "finito", - "frame-metadata 16.0.0", + "frame-metadata 16.0.0 (git+https://github.com/paritytech/frame-metadata.git?branch=lexnv/metadata-v16-associated-types)", "futures", "getrandom", "hex", @@ -5658,7 +5659,7 @@ version = "0.37.0" dependencies = [ "clap 4.5.17", "color-eyre", - "frame-metadata 16.0.0", + "frame-metadata 16.0.0 (git+https://github.com/paritytech/frame-metadata.git?branch=lexnv/metadata-v16-associated-types)", "heck 0.5.0", "hex", "indoc", @@ -5685,7 +5686,7 @@ dependencies = [ name = "subxt-codegen" version = "0.37.0" dependencies = [ - "frame-metadata 16.0.0", + "frame-metadata 16.0.0 (git+https://github.com/paritytech/frame-metadata.git?branch=lexnv/metadata-v16-associated-types)", "getrandom", "heck 0.5.0", "hex", @@ -5710,7 +5711,7 @@ dependencies = [ "bitvec", "blake2", "derive-where", - "frame-metadata 16.0.0", + "frame-metadata 16.0.0 (git+https://github.com/paritytech/frame-metadata.git?branch=lexnv/metadata-v16-associated-types)", "hashbrown 0.14.5", "hex", "impl-serde", @@ -5784,7 +5785,7 @@ dependencies = [ "assert_matches", "bitvec", "criterion", - "frame-metadata 16.0.0", + "frame-metadata 16.0.0 (git+https://github.com/paritytech/frame-metadata.git?branch=lexnv/metadata-v16-associated-types)", "hashbrown 0.14.5", "parity-scale-codec", "scale-info", @@ -6316,7 +6317,7 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" name = "ui-tests" version = "0.37.0" dependencies = [ - "frame-metadata 16.0.0", + "frame-metadata 16.0.0 (git+https://github.com/paritytech/frame-metadata.git?branch=lexnv/metadata-v16-associated-types)", "generate-custom-metadata", "hex", "parity-scale-codec", diff --git a/Cargo.toml b/Cargo.toml index dabba45830..25b864a9a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 = { path = "/home/lexnv/workspace/frame-metadata/frame-metadata", features = ["current", "decode", "unstable"] } +frame-metadata = { git = "https://github.com/paritytech/frame-metadata.git", branch = "lexnv/metadata-v16-associated-types" ,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"