diff --git a/cli/src/commands/compatibility.rs b/cli/src/commands/compatibility.rs index 99730334e3..614af7f08b 100644 --- a/cli/src/commands/compatibility.rs +++ b/cli/src/commands/compatibility.rs @@ -77,7 +77,7 @@ async fn handle_pallet_metadata( compatibility .pallet_present .entry(hex_hash) - .or_insert_with(Vec::new) + .or_default() .push(node.to_string()); } None => { @@ -110,7 +110,7 @@ async fn handle_full_metadata( compatibility_map .entry(hex_hash) - .or_insert_with(Vec::new) + .or_default() .push(node.to_string()); } diff --git a/cli/src/commands/diff.rs b/cli/src/commands/diff.rs index 9200e85209..50439ebe93 100644 --- a/cli/src/commands/diff.rs +++ b/cli/src/commands/diff.rs @@ -13,7 +13,6 @@ use scale_info::Variant; use subxt_metadata::{ ConstantMetadata, Metadata, PalletMetadata, RuntimeApiMetadata, StorageEntryMetadata, - StorageEntryType, }; /// Explore the differences between two nodes @@ -220,40 +219,34 @@ impl StorageEntryDiff { metadata_1: &Metadata, metadata_2: &Metadata, ) -> Self { - let value_1_ty_id = match storage_entry_1.entry_type() { - StorageEntryType::Plain(value_ty) | StorageEntryType::Map { value_ty, .. } => value_ty, - }; + let value_1_ty_id = storage_entry_1.entry_type().value_ty(); let value_1_hash = metadata_1 - .type_hash(*value_1_ty_id) + .type_hash(value_1_ty_id) .expect("type should be present"); - let value_2_ty_id = match storage_entry_2.entry_type() { - StorageEntryType::Plain(value_ty) | StorageEntryType::Map { value_ty, .. } => value_ty, - }; + let value_2_ty_id = storage_entry_2.entry_type().value_ty(); let value_2_hash = metadata_1 - .type_hash(*value_2_ty_id) + .type_hash(value_2_ty_id) .expect("type should be present"); let value_different = value_1_hash != value_2_hash; - let key_1_hash = match storage_entry_1.entry_type() { - StorageEntryType::Plain(_) => None, - StorageEntryType::Map { key_ty, .. } => Some(*key_ty), - } - .map(|key_ty| { - metadata_1 - .type_hash(key_ty) - .expect("type should be present") - }) - .unwrap_or_default(); - let key_2_hash = match storage_entry_2.entry_type() { - StorageEntryType::Plain(_) => None, - StorageEntryType::Map { key_ty, .. } => Some(*key_ty), - } - .map(|key_ty| { - metadata_2 - .type_hash(key_ty) - .expect("type should be present") - }) - .unwrap_or_default(); + let key_1_hash = storage_entry_1 + .entry_type() + .key_ty() + .map(|key_ty| { + metadata_1 + .type_hash(key_ty) + .expect("type should be present") + }) + .unwrap_or_default(); + let key_2_hash = storage_entry_2 + .entry_type() + .key_ty() + .map(|key_ty| { + metadata_2 + .type_hash(key_ty) + .expect("type should be present") + }) + .unwrap_or_default(); let key_different = key_1_hash != key_2_hash; StorageEntryDiff { diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index 18609661fb..a336f7fa7c 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -12,21 +12,25 @@ documentation = "https://docs.rs/subxt-codegen" homepage.workspace = true description = "Generate an API for interacting with a substrate node from FRAME metadata" +[features] +default = ["fetch-metadata"] +fetch-metadata = ["dep:jsonrpsee", "dep:tokio", "dep:frame-metadata"] + [dependencies] codec = { package = "parity-scale-codec", workspace = true, features = ["derive"] } -frame-metadata = { workspace = true } +frame-metadata = { workspace = true, optional = true } heck = { workspace = true } proc-macro2 = { workspace = true } quote = { workspace = true } syn = { workspace = true } scale-info = { workspace = true } subxt-metadata = { workspace = true } -jsonrpsee = { workspace = true, features = ["async-client", "client-ws-transport-native-tls", "http-client"] } +jsonrpsee = { workspace = true, features = ["async-client", "client-ws-transport-native-tls", "http-client"], optional = true } hex = { workspace = true } -tokio = { workspace = true, features = ["rt-multi-thread"] } +tokio = { workspace = true, features = ["rt-multi-thread"], optional = true } thiserror = { workspace = true } [dev-dependencies] bitvec = { workspace = true } scale-info = { workspace = true, features = ["bit-vec"] } -pretty_assertions = { workspace = true } +pretty_assertions = { workspace = true } \ No newline at end of file diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs index 7802ba7ea9..1d1897e3d2 100644 --- a/codegen/src/api/mod.rs +++ b/codegen/src/api/mod.rs @@ -20,14 +20,14 @@ use crate::error::CodegenError; use crate::{ ir, types::{CompositeDef, CompositeDefFields, TypeGenerator, TypeSubstitutes}, - utils::{fetch_metadata_bytes_blocking, MetadataVersion, Url}, CratePath, }; + use codec::Decode; use heck::ToSnakeCase as _; use proc_macro2::TokenStream as TokenStream2; use quote::{format_ident, quote}; -use std::{collections::HashMap, fs, io::Read, path, string::ToString}; +use std::{fs, io::Read, path, string::ToString}; use syn::parse_quote; /// Generate the runtime API for interacting with a substrate runtime. @@ -146,7 +146,10 @@ impl GenerateRuntimeApi { /// # Warning /// /// Not recommended to be used in production environments. - pub fn generate_from_url(self, url: Url) -> Result { + #[cfg(feature = "fetch-metadata")] + pub fn generate_from_url(self, url: crate::utils::Url) -> Result { + use crate::utils::{fetch_metadata_bytes_blocking, MetadataVersion, Url}; + fn fetch_metadata(url: Url, version: MetadataVersion) -> Result { let bytes = fetch_metadata_bytes_blocking(url, version)?; Ok(Metadata::decode(&mut &bytes[..])?) @@ -225,49 +228,10 @@ impl RuntimeGenerator { /// /// Supported versions: v14 and v15. pub fn new(mut metadata: Metadata) -> Self { - Self::ensure_unique_type_paths(&mut metadata); + metadata.ensure_unique_type_paths(); RuntimeGenerator { metadata } } - /// Ensure that every unique type we'll be generating or referring to also has a - /// unique path, so that types with matching paths don't end up overwriting each other - /// in the codegen. We ignore any types with generics; Subxt actually endeavours to - /// de-duplicate those into single types with a generic. - fn ensure_unique_type_paths(metadata: &mut Metadata) { - let mut visited_path_counts = HashMap::, usize>::new(); - for ty in metadata.types_mut().types.iter_mut() { - // Ignore types without a path (ie prelude types). - if ty.ty.path.namespace().is_empty() { - continue; - } - - let has_valid_type_params = ty.ty.type_params.iter().any(|tp| tp.ty.is_some()); - - // Ignore types which have generic params that the type generation will use. - // Ordinarily we'd expect that any two types with identical paths must be parameterized - // in order to share the path. However scale-info doesn't understand all forms of generics - // properly I think (eg generics that have associated types that can differ), and so in - // those cases we need to fix the paths for Subxt to generate correct code. - if has_valid_type_params { - continue; - } - - // Count how many times we've seen the same path already. - let visited_count = visited_path_counts - .entry(ty.ty.path.segments.clone()) - .or_default(); - *visited_count += 1; - - // alter the type so that if it's been seen more than once, we append a number to - // its name to ensure that every unique type has a unique path, too. - if *visited_count > 1 { - if let Some(name) = ty.ty.path.segments.last_mut() { - *name = format!("{name}{visited_count}"); - } - } - } - } - /// Generate the API for interacting with a Substrate runtime. /// /// # Arguments diff --git a/codegen/src/api/storage.rs b/codegen/src/api/storage.rs index 4101fd80e8..988679e7a9 100644 --- a/codegen/src/api/storage.rs +++ b/codegen/src/api/storage.rs @@ -96,10 +96,7 @@ fn generate_storage_entry_fns( }; let snake_case_name = storage_entry.name().to_snake_case(); - let storage_entry_ty = match storage_entry.entry_type() { - StorageEntryType::Plain(ty) => *ty, - StorageEntryType::Map { value_ty, .. } => *value_ty, - }; + let storage_entry_ty = storage_entry.entry_type().value_ty(); let storage_entry_value_ty = type_gen.resolve_type_path(storage_entry_ty); let docs = storage_entry.docs(); let docs = should_gen_docs diff --git a/codegen/src/error.rs b/codegen/src/error.rs index f293df2ee6..60437f5de7 100644 --- a/codegen/src/error.rs +++ b/codegen/src/error.rs @@ -8,6 +8,7 @@ use proc_macro2::{Span, TokenStream as TokenStream2}; /// Error returned when the Codegen cannot generate the runtime API. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum CodegenError { /// The given metadata type could not be found. #[error("Could not find type with ID {0} in the type registry; please raise a support issue.")] @@ -82,11 +83,13 @@ impl CodegenError { /// Error attempting to load metadata. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum FetchMetadataError { #[error("Cannot decode hex value: {0}")] DecodeError(#[from] hex::FromHexError), #[error("Cannot scale encode/decode value: {0}")] CodecError(#[from] codec::Error), + #[cfg(feature = "fetch-metadata")] #[error("Request error: {0}")] RequestError(#[from] jsonrpsee::core::Error), #[error("'{0}' not supported, supported URI schemes are http, https, ws or wss.")] @@ -97,6 +100,7 @@ pub enum FetchMetadataError { /// Error attempting to do type substitution. #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum TypeSubstitutionError { /// Substitute "to" type must be an absolute path. #[error("`substitute_type(with = )` must be a path prefixed with 'crate::' or '::'")] diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index be2e27e0d2..5af5a244b9 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -50,10 +50,17 @@ mod error; mod ir; mod types; +#[cfg(feature = "fetch-metadata")] pub mod utils; +#[cfg(all(feature = "web", feature = "fetch-metadata"))] +compile_error!("subxt-codegen: the features 'web' and 'fetch_metadata' cannot be used together."); + pub use self::{ api::{GenerateRuntimeApi, RuntimeGenerator}, error::{CodegenError, TypeSubstitutionError}, - types::{CratePath, Derives, DerivesRegistry, Module, TypeGenerator, TypeSubstitutes}, + types::{ + CratePath, Derives, DerivesRegistry, Module, TypeDefGen, TypeDefParameters, TypeGenerator, + TypeSubstitutes, + }, }; diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index 2e8d1611be..f565fb0460 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -262,6 +262,11 @@ impl<'a> TypeGenerator<'a> { self.derives.default_derives() } + /// Returns the type registry. + pub fn types(&self) -> &PortableRegistry { + self.type_registry + } + /// Returns the derives to be applied to a generated type. pub fn type_derives(&self, ty: &Type) -> Result { let joined_path = ty.path.segments.join("::"); diff --git a/codegen/src/types/type_def.rs b/codegen/src/types/type_def.rs index 25fa02556a..57470abf7f 100644 --- a/codegen/src/types/type_def.rs +++ b/codegen/src/types/type_def.rs @@ -118,6 +118,11 @@ impl TypeDefGen { ty_docs, }) } + + /// are there unused type params? + pub fn has_unused_type_params(&self) -> bool { + self.type_params.has_unused_type_params() + } } impl quote::ToTokens for TypeDefGen { diff --git a/codegen/src/types/type_def_params.rs b/codegen/src/types/type_def_params.rs index 15dc5b6bc2..155029fdd4 100644 --- a/codegen/src/types/type_def_params.rs +++ b/codegen/src/types/type_def_params.rs @@ -60,6 +60,11 @@ impl TypeDefParameters { pub fn params(&self) -> &[TypeParameter] { &self.params } + + /// Returns true if there are any unused type params + pub fn has_unused_type_params(&self) -> bool { + !self.unused.is_empty() + } } impl quote::ToTokens for TypeDefParameters { diff --git a/examples/wasm-example/Cargo.lock b/examples/wasm-example/Cargo.lock index 174decfb19..8a8a3af72d 100644 --- a/examples/wasm-example/Cargo.lock +++ b/examples/wasm-example/Cargo.lock @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.72" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", @@ -859,7 +859,7 @@ dependencies = [ "gloo-render", "gloo-storage", "gloo-timers", - "gloo-utils", + "gloo-utils 0.1.7", "gloo-worker", ] @@ -869,7 +869,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f" dependencies = [ - "gloo-utils", + "gloo-utils 0.1.7", "js-sys", "serde", "wasm-bindgen", @@ -916,7 +916,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfd137a4b629e72b8c949ec56c71ea9bd5491cc66358a0a7787e94875feec71" dependencies = [ "gloo-events", - "gloo-utils", + "gloo-utils 0.1.7", "serde", "serde-wasm-bindgen", "serde_urlencoded", @@ -927,14 +927,15 @@ dependencies = [ [[package]] name = "gloo-net" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9902a044653b26b99f7e3693a42f171312d9be8b26b5697bd1e43ad1f8a35e10" +checksum = "3000ef231a67d5bfee6b35f2c0f6f5c8d45b3381ef5bbbea603690ec4e539762" dependencies = [ "futures-channel", "futures-core", "futures-sink", - "gloo-utils", + "gloo-utils 0.1.7", + "http", "js-sys", "pin-project", "serde", @@ -947,14 +948,14 @@ dependencies = [ [[package]] name = "gloo-net" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3000ef231a67d5bfee6b35f2c0f6f5c8d45b3381ef5bbbea603690ec4e539762" +checksum = "8ac9e8288ae2c632fa9f8657ac70bfe38a1530f345282d7ba66a1f70b72b7dc4" dependencies = [ "futures-channel", "futures-core", "futures-sink", - "gloo-utils", + "gloo-utils 0.2.0", "http", "js-sys", "pin-project", @@ -982,7 +983,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480" dependencies = [ - "gloo-utils", + "gloo-utils 0.1.7", "js-sys", "serde", "serde_json", @@ -1016,6 +1017,19 @@ dependencies = [ "web-sys", ] +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "gloo-worker" version = "0.2.1" @@ -1025,7 +1039,7 @@ dependencies = [ "anymap2", "bincode", "gloo-console", - "gloo-utils", + "gloo-utils 0.1.7", "js-sys", "serde", "wasm-bindgen", @@ -1169,7 +1183,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -1178,10 +1192,11 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" dependencies = [ + "futures-util", "http", "hyper", "log", @@ -1189,7 +1204,6 @@ dependencies = [ "rustls-native-certs", "tokio", "tokio-rustls", - "webpki-roots", ] [[package]] @@ -1198,6 +1212,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "impl-codec" version = "0.6.0" @@ -1306,9 +1330,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.16.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" +checksum = "9ad9b31183a8bcbe843e32ca8554ad2936633548d95a7bb6a8e14c767dea6b05" dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", @@ -1318,18 +1342,15 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.16.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965de52763f2004bc91ac5bcec504192440f0b568a5d621c59d9dbd6f886c3fb" +checksum = "97f2743cad51cc86b0dbfe316309eeb87a9d96a3d7f4dd7a99767c4b5f065335" dependencies = [ - "anyhow", "futures-channel", - "futures-timer", "futures-util", - "gloo-net 0.2.6", + "gloo-net 0.4.0", "http", "jsonrpsee-core", - "jsonrpsee-types", "pin-project", "rustls-native-certs", "soketto", @@ -1338,20 +1359,19 @@ dependencies = [ "tokio-rustls", "tokio-util", "tracing", - "webpki-roots", + "url", ] [[package]] name = "jsonrpsee-core" -version = "0.16.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" +checksum = "35dc957af59ce98373bcdde0c1698060ca6c2d2e9ae357b459c7158b6df33330" dependencies = [ "anyhow", "async-lock", "async-trait", "beef", - "futures-channel", "futures-timer", "futures-util", "hyper", @@ -1367,28 +1387,29 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.16.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc345b0a43c6bc49b947ebeb936e886a419ee3d894421790c969cc56040542ad" +checksum = "0dd865d0072764cb937b0110a92b5f53e995f7101cb346beca03d93a2dea79de" dependencies = [ "async-trait", "hyper", "hyper-rustls", "jsonrpsee-core", "jsonrpsee-types", - "rustc-hash", "serde", "serde_json", "thiserror", "tokio", + "tower", "tracing", + "url", ] [[package]] name = "jsonrpsee-types" -version = "0.16.2" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd522fe1ce3702fd94812965d7bb7a3364b1c9aba743944c5a00529aae80f8c" +checksum = "fa9e25aec855b2a7d3ed90fded6c41e8c3fb72b63f071e1be3f0004eba19b625" dependencies = [ "anyhow", "beef", @@ -1709,9 +1730,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -1824,9 +1845,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -1850,9 +1871,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -1949,14 +1970,14 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.8" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ "log", "ring", + "rustls-webpki", "sct", - "webpki", ] [[package]] @@ -1980,6 +2001,16 @@ dependencies = [ "base64 0.21.2", ] +[[package]] +name = "rustls-webpki" +version = "0.101.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a27e3b59326c16e23d30aeb7a36a24cc0d29e71d68ff611cdfb4a01d013bed" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -2194,9 +2225,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.181" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d3e73c93c3240c0bda063c239298e633114c69a888c3e37ca8bb33f343e9890" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] @@ -2214,9 +2245,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.181" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be02f6cb0cd3a5ec20bbcfbcbd749f57daddb1a0882dc2e46a6c236c90b977ed" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", @@ -2225,9 +2256,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -2416,6 +2447,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "soketto" version = "0.7.1" @@ -2492,13 +2533,13 @@ checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" name = "subxt" version = "0.31.0" dependencies = [ + "async-trait", "base58", "blake2", "derivative", "either", "frame-metadata 16.0.0", "futures", - "getrandom", "hex", "impl-serde", "jsonrpsee", @@ -2612,9 +2653,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] @@ -2641,9 +2682,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", @@ -2676,18 +2717,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.4", "tokio-macros", "windows-sys", ] @@ -2705,13 +2745,12 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.4" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls", "tokio", - "webpki", ] [[package]] @@ -2757,6 +2796,27 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -2770,6 +2830,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2809,7 +2870,6 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", "digest 0.10.7", - "rand", "static_assertions", ] @@ -2831,12 +2891,27 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + [[package]] name = "unicode-ident" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + [[package]] name = "universal-hash" version = "0.4.0" @@ -2853,6 +2928,17 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "version_check" version = "0.9.4" @@ -3009,25 +3095,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - [[package]] name = "winapi" version = "0.3.9" diff --git a/metadata/src/lib.rs b/metadata/src/lib.rs index 2ce1481e5e..b0186cab66 100644 --- a/metadata/src/lib.rs +++ b/metadata/src/lib.rs @@ -166,6 +166,45 @@ impl Metadata { &mut HashMap::new(), )) } + + /// Ensure that every unique type we'll be generating or referring to also has a + /// unique path, so that types with matching paths don't end up overwriting each other + /// in the codegen. We ignore any types with generics; Subxt actually endeavours to + /// de-duplicate those into single types with a generic. + pub fn ensure_unique_type_paths(&mut self) { + let mut visited_path_counts = HashMap::, usize>::new(); + for ty in self.types.types.iter_mut() { + // Ignore types without a path (ie prelude types). + if ty.ty.path.namespace().is_empty() { + continue; + } + + let has_valid_type_params = ty.ty.type_params.iter().any(|tp| tp.ty.is_some()); + + // Ignore types which have generic params that the type generation will use. + // Ordinarily we'd expect that any two types with identical paths must be parameterized + // in order to share the path. However scale-info doesn't understand all forms of generics + // properly I think (eg generics that have associated types that can differ), and so in + // those cases we need to fix the paths for Subxt to generate correct code. + if has_valid_type_params { + continue; + } + + // Count how many times we've seen the same path already. + let visited_count = visited_path_counts + .entry(ty.ty.path.segments.clone()) + .or_default(); + *visited_count += 1; + + // alter the type so that if it's been seen more than once, we append a number to + // its name to ensure that every unique type has a unique path, too. + if *visited_count > 1 { + if let Some(name) = ty.ty.path.segments.last_mut() { + *name = format!("{name}{visited_count}"); + } + } + } + } } /// Metadata for a specific pallet. @@ -395,6 +434,23 @@ pub enum StorageEntryType { }, } +impl StorageEntryType { + /// The type of the value. + pub fn value_ty(&self) -> u32 { + match self { + StorageEntryType::Map { value_ty, .. } | StorageEntryType::Plain(value_ty) => *value_ty, + } + } + + /// The type of the key, can be a tuple with elements for each of the hashers. None for a Plain storage entry. + pub fn key_ty(&self) -> Option { + match self { + StorageEntryType::Map { key_ty, .. } => Some(*key_ty), + StorageEntryType::Plain(_) => None, + } + } +} + /// Hasher used by storage maps. #[derive(Debug, Clone, Copy)] pub enum StorageHasher {