diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 2616d28a5b..f8fa1e4da4 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -76,6 +76,10 @@ jobs: - name: Cargo hack; check each feature/crate on its own run: cargo hack --exclude subxt --exclude subxt-signer --exclude subxt-lightclient --exclude-all-features --each-feature check --workspace + # Check the parachain-example code, which isn't a part of the workspace so is otherwise ignored. + - name: Cargo check parachain-example + run: cargo check --manifest-path examples/parachain-example/Cargo.toml + wasm_check: name: Cargo check (WASM) runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index fc4ac0c6c8..0d2497a5eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -329,9 +329,9 @@ checksum = "b9441c6b2fe128a7c2bf680a44c34d0df31ce09e5b7e401fcca3faa483dbc921" [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", @@ -718,9 +718,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", @@ -728,21 +728,21 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.6" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", - "clap_lex 0.5.1", + "clap_lex 0.6.0", "strsim", ] [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -761,9 +761,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "cmake" @@ -2078,9 +2078,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de902baa44bf34a58b1a4906f8b840d7d60dcec5f41fe08b4dbc14cf9efa821c" +checksum = "affdc52f7596ccb2d7645231fc6163bb314630c989b64998f3699a28b4d5d4dc" dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", @@ -2090,9 +2090,9 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58d9851f8f5653e0433a898e9032bde4910b35d625bd9dcf33ef6e36e7c3d456" +checksum = "b5b005c793122d03217da09af68ba9383363caa950b90d3436106df8cabce935" dependencies = [ "futures-channel", "futures-util", @@ -2112,9 +2112,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f45d37af23707750136379f6799e76ebfcf2d425ec4e36d0deb7921da5e65c" +checksum = "da2327ba8df2fdbd5e897e2b5ed25ce7f299d345b9736b6828814c3dbd1fd47b" dependencies = [ "anyhow", "async-lock", @@ -2135,9 +2135,9 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02308562f2e8162a32f8d6c3dc19c29c858d5d478047c886a5c3c25b5f7fa868" +checksum = "5f80c17f62c7653ce767e3d7288b793dfec920f97067ceb189ebdd3570f2bc20" dependencies = [ "async-trait", "hyper", @@ -2155,9 +2155,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.20.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05eaff23af19f10ba6fbb76519bed6da4d3b9bbaef13d39b7c2b6c14e532d27e" +checksum = "5be0be325642e850ed0bdff426674d2e66b2b7117c9be23a7caef68a2902b7d9" dependencies = [ "anyhow", "beef", @@ -3462,9 +3462,9 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] @@ -3480,9 +3480,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", @@ -4243,7 +4243,7 @@ dependencies = [ name = "subxt-cli" version = "0.32.1" dependencies = [ - "clap 4.4.6", + "clap 4.4.7", "color-eyre", "frame-metadata 16.0.0", "hex", @@ -4312,6 +4312,7 @@ name = "subxt-macro" version = "0.32.1" dependencies = [ "darling 0.20.3", + "parity-scale-codec", "proc-macro-error", "subxt-codegen", "syn 2.0.37", @@ -4572,9 +4573,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", diff --git a/Cargo.toml b/Cargo.toml index d3e886e959..a7a37de90b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,12 +37,12 @@ documentation = "https://docs.rs/subxt" homepage = "https://www.parity.io/" [workspace.dependencies] -async-trait = "0.1.73" +async-trait = "0.1.74" assert_matches = "1.5.0" base58 = { version = "0.2.0" } bitvec = { version = "1", default-features = false } blake2 = { version = "0.10.4", default-features = false } -clap = { version = "4.4.6", features = ["derive", "cargo"] } +clap = { version = "4.4.7", features = ["derive", "cargo"] } criterion = "0.4" codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } color-eyre = "0.6.1" @@ -68,7 +68,7 @@ scale-value = "0.12.0" scale-bits = "0.4.0" scale-decode = "0.9.0" scale-encode = "0.5.0" -serde = { version = "1.0.188" } +serde = { version = "1.0.190" } serde_json = { version = "1.0.107" } syn = { version = "2.0.15", features = ["full", "extra-traits"] } thiserror = "1.0.50" @@ -95,7 +95,7 @@ js-sys = "0.3.61" wasm-bindgen-futures = "0.4.19" futures-timer = "3" instant = { version = "0.1.12", default-features = false } -tokio-util = "0.7.9" +tokio-util = "0.7.10" # Substrate crates: sp-core = { version = "21.0.0", default-features = false } diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 68d67c96e9..9b5ef68298 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -17,7 +17,7 @@ name = "subxt" path = "src/main.rs" [dependencies] -subxt-codegen = { workspace = true } +subxt-codegen = { workspace = true, features = ["fetch-metadata"] } subxt-metadata = { workspace = true } subxt = { workspace = true, features = ["native", "jsonrpsee"] } clap = { workspace = true } diff --git a/cli/src/commands/codegen.rs b/cli/src/commands/codegen.rs index 6d05b3e545..2f1a2abef1 100644 --- a/cli/src/commands/codegen.rs +++ b/cli/src/commands/codegen.rs @@ -4,9 +4,9 @@ use crate::utils::FileOrUrl; use clap::Parser as ClapParser; -use color_eyre::eyre; +use codec::Decode; use color_eyre::eyre::eyre; -use subxt_codegen::{DerivesRegistry, GenerateRuntimeApi, TypeSubstitutes, TypeSubstitutionError}; +use subxt_codegen::CodegenBuilder; /// Generate runtime API client code from metadata. /// @@ -132,67 +132,77 @@ fn codegen( no_default_substitutions: bool, output: &mut impl std::io::Write, ) -> color_eyre::Result<()> { - let item_mod = syn::parse_quote!( - pub mod api {} - ); + let mut codegen = CodegenBuilder::new(); - let universal_derives = raw_derives + // Use the provided crate path: + if let Some(crate_path) = crate_path { + let crate_path = + syn::parse_str(&crate_path).map_err(|e| eyre!("Cannot parse crate path: {e}"))?; + codegen.set_subxt_crate_path(crate_path); + } + + // Respect the boolean flags: + if runtime_types_only { + codegen.runtime_types_only() + } + if no_default_derives { + codegen.disable_default_derives() + } + if no_default_substitutions { + codegen.disable_default_substitutes() + } + if no_docs { + codegen.no_docs() + } + + // Configure derives: + let global_derives = raw_derives .iter() .map(|raw| syn::parse_str(raw)) - .collect::, _>>()?; + .collect::, _>>() + .map_err(|e| eyre!("Cannot parse global derives: {e}"))?; + codegen.set_additional_global_derives(global_derives); + + for (ty_str, derive) in derives_for_type { + let ty: syn::TypePath = syn::parse_str(&ty_str) + .map_err(|e| eyre!("Cannot parse derive for type {ty_str}: {e}"))?; + let derive = syn::parse_str(&derive) + .map_err(|e| eyre!("Cannot parse derive for type {ty_str}: {e}"))?; + codegen.add_derives_for_type(ty, std::iter::once(derive)); + } + + // Configure attribtues: let universal_attributes = raw_attributes .iter() .map(|raw| syn::parse_str(raw)) .map(|attr: syn::Result| attr.map(|attr| attr.0)) - .collect::, _>>()?; + .collect::, _>>() + .map_err(|e| eyre!("Cannot parse global attributes: {e}"))?; + codegen.set_additional_global_attributes(universal_attributes); - let crate_path = crate_path.map(Into::into).unwrap_or_default(); - let mut derives = if no_default_derives { - DerivesRegistry::new() - } else { - DerivesRegistry::with_default_derives(&crate_path) - }; - derives.extend_for_all(universal_derives, universal_attributes); - - for (ty, derive) in derives_for_type { - let ty = syn::parse_str(&ty)?; - let derive = syn::parse_str(&derive)?; - derives.extend_for_type(ty, std::iter::once(derive), vec![]); - } - for (ty, attr) in attributes_for_type { - let ty = syn::parse_str(&ty)?; - let attribute: OuterAttribute = syn::parse_str(&attr)?; - derives.extend_for_type(ty, vec![], std::iter::once(attribute.0)); + for (ty_str, attr) in attributes_for_type { + let ty = syn::parse_str(&ty_str) + .map_err(|e| eyre!("Cannot parse attribute for type {ty_str}: {e}"))?; + let attribute: OuterAttribute = syn::parse_str(&attr) + .map_err(|e| eyre!("Cannot parse attribute for type {ty_str}: {e}"))?; + codegen.add_attributes_for_type(ty, std::iter::once(attribute.0)); } - let mut type_substitutes = if no_default_substitutions { - TypeSubstitutes::new() - } else { - TypeSubstitutes::with_default_substitutes(&crate_path) - }; - + // Insert type substitutions: for (from_str, to_str) in substitute_types { - let from: syn::Path = syn::parse_str(&from_str)?; - let to: syn::Path = syn::parse_str(&to_str)?; - let to = to.try_into().map_err(|e: TypeSubstitutionError| { - eyre::eyre!("Cannot parse substitute '{from_str}={to_str}': {e}") - })?; - type_substitutes - .insert(from, to) - .map_err(|e: TypeSubstitutionError| { - eyre::eyre!("Cannot parse substitute '{from_str}={to_str}': {e}") - })?; + let from: syn::Path = syn::parse_str(&from_str) + .map_err(|e| eyre!("Cannot parse type substitution for path {from_str}: {e}"))?; + let to: syn::Path = syn::parse_str(&to_str) + .map_err(|e| eyre!("Cannot parse type substitution for path {from_str}: {e}"))?; + codegen.set_type_substitute(from, to); } - let should_gen_docs = !no_docs; + let metadata = subxt_metadata::Metadata::decode(&mut &*metadata_bytes) + .map_err(|e| eyre!("Cannot decode the provided metadata: {e}"))?; + let code = codegen + .generate(metadata) + .map_err(|e| eyre!("Cannot generate code: {e}"))?; - let runtime_api = GenerateRuntimeApi::new(item_mod, crate_path) - .derives_registry(derives) - .type_substitutes(type_substitutes) - .generate_docs(should_gen_docs) - .runtime_types_only(runtime_types_only) - .generate_from_bytes(metadata_bytes) - .map_err(|code_gen_err| eyre!("{code_gen_err}"))?; - writeln!(output, "{runtime_api}")?; + writeln!(output, "{code}")?; Ok(()) } diff --git a/cli/src/commands/compatibility.rs b/cli/src/commands/compatibility.rs index 614af7f08b..d4264ddd55 100644 --- a/cli/src/commands/compatibility.rs +++ b/cli/src/commands/compatibility.rs @@ -8,7 +8,7 @@ use color_eyre::eyre::WrapErr; use jsonrpsee::client_transport::ws::Url; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use subxt_codegen::utils::MetadataVersion; +use subxt_codegen::fetch_metadata::MetadataVersion; use subxt_metadata::Metadata; /// Verify metadata compatibility between substrate nodes. @@ -128,7 +128,7 @@ async fn fetch_runtime_metadata( url: Url, version: MetadataVersion, ) -> color_eyre::Result { - let bytes = subxt_codegen::utils::fetch_metadata_bytes(url, version).await?; + let bytes = subxt_codegen::fetch_metadata::fetch_metadata_from_url(url, version).await?; let metadata = Metadata::decode(&mut &bytes[..])?; Ok(metadata) } diff --git a/cli/src/utils.rs b/cli/src/utils.rs index f1f788fb64..82f202a92b 100644 --- a/cli/src/utils.rs +++ b/cli/src/utils.rs @@ -8,7 +8,7 @@ use color_eyre::eyre; use std::str::FromStr; use std::{fs, io::Read, path::PathBuf}; -use subxt_codegen::utils::{MetadataVersion, Url}; +use subxt_codegen::fetch_metadata::{fetch_metadata_from_url, MetadataVersion, Url}; pub mod type_description; pub mod type_example; @@ -57,18 +57,13 @@ impl FileOrUrl { eyre::bail!("`--file` is incompatible with `--version`") } // Fetch from --url - (None, Some(uri), version) => Ok(subxt_codegen::utils::fetch_metadata_bytes( - uri.clone(), - version.unwrap_or_default(), - ) - .await?), + (None, Some(uri), version) => { + Ok(fetch_metadata_from_url(uri.clone(), version.unwrap_or_default()).await?) + } // Default if neither is provided; fetch from local url (None, None, version) => { let url = Url::parse("ws://localhost:9944").expect("Valid URL; qed"); - Ok( - subxt_codegen::utils::fetch_metadata_bytes(url, version.unwrap_or_default()) - .await?, - ) + Ok(fetch_metadata_from_url(url, version.unwrap_or_default()).await?) } } } diff --git a/codegen/Cargo.toml b/codegen/Cargo.toml index a48b3d546d..57c985282b 100644 --- a/codegen/Cargo.toml +++ b/codegen/Cargo.toml @@ -13,7 +13,7 @@ homepage.workspace = true description = "Generate an API for interacting with a substrate node from FRAME metadata" [features] -default = ["fetch-metadata"] +default = [] fetch-metadata = ["dep:jsonrpsee", "dep:tokio", "dep:frame-metadata"] web = ["jsonrpsee?/async-wasm-client", "jsonrpsee?/client-web-transport", "getrandom/js"] diff --git a/codegen/src/api/calls.rs b/codegen/src/api/calls.rs index 3d57575eac..74356266e0 100644 --- a/codegen/src/api/calls.rs +++ b/codegen/src/api/calls.rs @@ -3,10 +3,7 @@ // see LICENSE for license details. use super::CodegenError; -use crate::{ - types::{CompositeDefFields, TypeGenerator}, - CratePath, -}; +use crate::types::{CompositeDefFields, TypeGenerator}; use heck::{ToSnakeCase as _, ToUpperCamelCase as _}; use proc_macro2::TokenStream as TokenStream2; use quote::{format_ident, quote}; @@ -25,7 +22,7 @@ pub fn generate_calls( type_gen: &TypeGenerator, pallet: &PalletMetadata, types_mod_ident: &syn::Ident, - crate_path: &CratePath, + crate_path: &syn::Path, should_gen_docs: bool, ) -> Result { // Early return if the pallet has no calls. diff --git a/codegen/src/api/constants.rs b/codegen/src/api/constants.rs index 3a7ad9ed0f..31fa7526c4 100644 --- a/codegen/src/api/constants.rs +++ b/codegen/src/api/constants.rs @@ -2,7 +2,7 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -use crate::{types::TypeGenerator, CratePath}; +use crate::types::TypeGenerator; use heck::ToSnakeCase as _; use proc_macro2::TokenStream as TokenStream2; use quote::{format_ident, quote}; @@ -37,7 +37,7 @@ pub fn generate_constants( type_gen: &TypeGenerator, pallet: &PalletMetadata, types_mod_ident: &syn::Ident, - crate_path: &CratePath, + crate_path: &syn::Path, should_gen_docs: bool, ) -> Result { // Early return if the pallet has no constants. diff --git a/codegen/src/api/custom_values.rs b/codegen/src/api/custom_values.rs index 2a0f297d4b..1ef1381e19 100644 --- a/codegen/src/api/custom_values.rs +++ b/codegen/src/api/custom_values.rs @@ -4,7 +4,7 @@ use std::collections::HashSet; -use crate::{types::TypeGenerator, CratePath}; +use crate::types::TypeGenerator; use heck::ToSnakeCase as _; use subxt_metadata::{CustomValueMetadata, Metadata}; @@ -12,10 +12,10 @@ use proc_macro2::TokenStream as TokenStream2; use quote::{quote, ToTokens}; /// Generate the custom values mod, if there are any custom values in the metadata. Else returns None. -pub fn generate_custom_values<'a>( - metadata: &'a Metadata, - type_gen: &'a TypeGenerator, - crate_path: &'a CratePath, +pub fn generate_custom_values( + metadata: &Metadata, + type_gen: &TypeGenerator, + crate_path: &syn::Path, ) -> TokenStream2 { let mut fn_names_taken = HashSet::new(); let custom = metadata.custom(); @@ -37,7 +37,7 @@ pub fn generate_custom_values<'a>( fn generate_custom_value_fn( custom_value: CustomValueMetadata, type_gen: &TypeGenerator, - crate_path: &CratePath, + crate_path: &syn::Path, fn_names_taken: &mut HashSet, ) -> Option { // names are transformed to snake case to make for good function identifiers. diff --git a/codegen/src/api/events.rs b/codegen/src/api/events.rs index 755f494c65..383ed52694 100644 --- a/codegen/src/api/events.rs +++ b/codegen/src/api/events.rs @@ -2,7 +2,7 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -use crate::{types::TypeGenerator, CratePath}; +use crate::types::TypeGenerator; use proc_macro2::TokenStream as TokenStream2; use quote::quote; use subxt_metadata::PalletMetadata; @@ -42,7 +42,7 @@ pub fn generate_events( type_gen: &TypeGenerator, pallet: &PalletMetadata, types_mod_ident: &syn::Ident, - crate_path: &CratePath, + crate_path: &syn::Path, should_gen_docs: bool, ) -> Result { // Early return if the pallet has no events. diff --git a/codegen/src/api/mod.rs b/codegen/src/api/mod.rs index 1d1897e3d2..640e804203 100644 --- a/codegen/src/api/mod.rs +++ b/codegen/src/api/mod.rs @@ -14,203 +14,19 @@ mod storage; use subxt_metadata::Metadata; -use super::DerivesRegistry; use crate::api::custom_values::generate_custom_values; use crate::error::CodegenError; +use crate::types::DerivesRegistry; use crate::{ ir, types::{CompositeDef, CompositeDefFields, TypeGenerator, TypeSubstitutes}, - CratePath, }; -use codec::Decode; use heck::ToSnakeCase as _; use proc_macro2::TokenStream as TokenStream2; use quote::{format_ident, quote}; -use std::{fs, io::Read, path, string::ToString}; use syn::parse_quote; -/// Generate the runtime API for interacting with a substrate runtime. -pub struct GenerateRuntimeApi { - item_mod: syn::ItemMod, - derives: DerivesRegistry, - type_substitutes: TypeSubstitutes, - crate_path: CratePath, - should_gen_docs: bool, - runtime_types_only: bool, - unstable_metadata: bool, -} - -impl GenerateRuntimeApi { - /// Construct a new [`GenerateRuntimeApi`]. - pub fn new(item_mod: syn::ItemMod, crate_path: CratePath) -> Self { - GenerateRuntimeApi { - item_mod, - derives: DerivesRegistry::new(), - type_substitutes: TypeSubstitutes::new(), - crate_path, - should_gen_docs: false, - runtime_types_only: false, - unstable_metadata: false, - } - } - - /// Provide custom derives for the generated types. - /// - /// Default is no derives. - pub fn derives_registry(mut self, derives: DerivesRegistry) -> Self { - self.derives = derives; - self - } - - /// Provide custom type substitutes. - /// - /// Default is no substitutes. - pub fn type_substitutes(mut self, type_substitutes: TypeSubstitutes) -> Self { - self.type_substitutes = type_substitutes; - self - } - - /// True if the generated API contains the documentation from the metadata. - /// - /// Default: false. - pub fn generate_docs(mut self, should_gen_docs: bool) -> Self { - self.should_gen_docs = should_gen_docs; - self - } - - /// Whether to limit code generation to only runtime types. - /// - /// Default: false. - pub fn runtime_types_only(mut self, runtime_types_only: bool) -> Self { - self.runtime_types_only = runtime_types_only; - self - } - - /// Whether to fetch the unstable metadata first. - /// - /// # Note - /// - /// This takes effect only if the API is generated from URL. - /// - /// Default: false. - pub fn unstable_metadata(mut self, unstable_metadata: bool) -> Self { - self.unstable_metadata = unstable_metadata; - self - } - - /// Generate the runtime API from path. - pub fn generate_from_path

(self, path: P) -> Result - where - P: AsRef, - { - let to_err = |err| CodegenError::Io(path.as_ref().to_string_lossy().into(), err); - - let mut file = fs::File::open(&path).map_err(to_err)?; - let mut bytes = Vec::new(); - file.read_to_end(&mut bytes).map_err(to_err)?; - - let metadata = Metadata::decode(&mut &bytes[..])?; - - generate_runtime_api_with_metadata( - self.item_mod, - metadata, - self.derives, - self.type_substitutes, - self.crate_path, - self.should_gen_docs, - self.runtime_types_only, - ) - } - - /// Generate the runtime API from the provided metadata bytes. - pub fn generate_from_bytes(self, bytes: &[u8]) -> Result { - let metadata = Metadata::decode(&mut &bytes[..])?; - - generate_runtime_api_with_metadata( - self.item_mod, - metadata, - self.derives, - self.type_substitutes, - self.crate_path, - self.should_gen_docs, - self.runtime_types_only, - ) - } - - /// Generate the runtime API from URL. - /// - /// The metadata will be downloaded from a node at the provided URL. - /// This function blocks while retrieving the metadata. - /// - /// # Warning - /// - /// Not recommended to be used in production environments. - #[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[..])?) - } - - let metadata = self - .unstable_metadata - .then(|| fetch_metadata(url.clone(), MetadataVersion::Unstable).ok()) - .flatten(); - - let metadata = if let Some(unstable) = metadata { - unstable - } else { - match fetch_metadata(url.clone(), MetadataVersion::Version(15)) { - Ok(metadata) => metadata, - Err(_) => fetch_metadata(url, MetadataVersion::Version(14))?, - } - }; - - generate_runtime_api_with_metadata( - self.item_mod, - metadata, - self.derives, - self.type_substitutes, - self.crate_path, - self.should_gen_docs, - self.runtime_types_only, - ) - } -} - -/// Generates the API for interacting with a substrate runtime, using the `subxt::Metadata`. -fn generate_runtime_api_with_metadata( - item_mod: syn::ItemMod, - metadata: Metadata, - derives: DerivesRegistry, - type_substitutes: TypeSubstitutes, - crate_path: CratePath, - should_gen_docs: bool, - runtime_types_only: bool, -) -> Result { - let generator = RuntimeGenerator::new(metadata); - if runtime_types_only { - generator.generate_runtime_types( - item_mod, - derives, - type_substitutes, - crate_path, - should_gen_docs, - ) - } else { - generator.generate_runtime( - item_mod, - derives, - type_substitutes, - crate_path, - should_gen_docs, - ) - } -} - /// Create the API for interacting with a Substrate runtime. pub struct RuntimeGenerator { metadata: Metadata, @@ -246,7 +62,7 @@ impl RuntimeGenerator { item_mod: syn::ItemMod, derives: DerivesRegistry, type_substitutes: TypeSubstitutes, - crate_path: CratePath, + crate_path: syn::Path, should_gen_docs: bool, ) -> Result { let item_mod_attrs = item_mod.attrs.clone(); @@ -300,7 +116,7 @@ impl RuntimeGenerator { item_mod: syn::ItemMod, derives: DerivesRegistry, type_substitutes: TypeSubstitutes, - crate_path: CratePath, + crate_path: syn::Path, should_gen_docs: bool, ) -> Result { let item_mod_attrs = item_mod.attrs.clone(); @@ -545,7 +361,7 @@ pub fn generate_structs_from_variants( type_id: u32, variant_to_struct_name: F, error_message_type_name: &str, - crate_path: &CratePath, + crate_path: &syn::Path, should_gen_docs: bool, ) -> Result, CodegenError> where diff --git a/codegen/src/api/runtime_apis.rs b/codegen/src/api/runtime_apis.rs index bc363a2cf2..ea864903ff 100644 --- a/codegen/src/api/runtime_apis.rs +++ b/codegen/src/api/runtime_apis.rs @@ -2,7 +2,7 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -use crate::{types::TypeGenerator, CodegenError, CratePath}; +use crate::{types::TypeGenerator, CodegenError}; use heck::ToSnakeCase as _; use heck::ToUpperCamelCase as _; use subxt_metadata::{Metadata, RuntimeApiMetadata}; @@ -15,7 +15,7 @@ fn generate_runtime_api( api: RuntimeApiMetadata, type_gen: &TypeGenerator, types_mod_ident: &syn::Ident, - crate_path: &CratePath, + crate_path: &syn::Path, should_gen_docs: bool, ) -> Result<(TokenStream2, TokenStream2), CodegenError> { // Trait name must remain as is (upper case) to identity the runtime call. @@ -130,7 +130,7 @@ pub fn generate_runtime_apis( metadata: &Metadata, type_gen: &TypeGenerator, types_mod_ident: &syn::Ident, - crate_path: &CratePath, + crate_path: &syn::Path, should_gen_docs: bool, ) -> Result { let runtime_fns: Vec<_> = metadata diff --git a/codegen/src/api/storage.rs b/codegen/src/api/storage.rs index 988679e7a9..f012f9ed56 100644 --- a/codegen/src/api/storage.rs +++ b/codegen/src/api/storage.rs @@ -2,8 +2,8 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. +use crate::types::TypeGenerator; use crate::types::TypePath; -use crate::{types::TypeGenerator, CratePath}; use heck::ToSnakeCase as _; use proc_macro2::{Ident, TokenStream as TokenStream2, TokenStream}; use quote::{format_ident, quote}; @@ -27,7 +27,7 @@ pub fn generate_storage( type_gen: &TypeGenerator, pallet: &PalletMetadata, types_mod_ident: &syn::Ident, - crate_path: &CratePath, + crate_path: &syn::Path, should_gen_docs: bool, ) -> Result { let Some(storage) = pallet.storage() else { @@ -59,7 +59,7 @@ fn generate_storage_entry_fns( type_gen: &TypeGenerator, pallet: &PalletMetadata, storage_entry: &StorageEntryMetadata, - crate_path: &CratePath, + crate_path: &syn::Path, should_gen_docs: bool, ) -> Result { let keys: Vec<(Ident, TypePath)> = match storage_entry.entry_type() { @@ -269,7 +269,7 @@ mod tests { item_mod, Default::default(), Default::default(), - "::subxt_path".into(), + syn::parse_str("::subxt_path").unwrap(), false, ) .expect("should be able to generate runtime"); diff --git a/codegen/src/error.rs b/codegen/src/error.rs index 60437f5de7..5b4dc90fa4 100644 --- a/codegen/src/error.rs +++ b/codegen/src/error.rs @@ -16,9 +16,6 @@ pub enum CodegenError { /// Cannot fetch the metadata bytes. #[error("Failed to fetch metadata, make sure that you're pointing at a node which is providing substrate-based metadata: {0}")] Fetch(#[from] FetchMetadataError), - /// Failed IO for the metadata file. - #[error("Failed IO for {0}, make sure that you are providing the correct file path for metadata: {1}")] - Io(String, std::io::Error), /// Cannot decode the metadata bytes. #[error("Could not decode metadata, only V14 and V15 metadata are supported: {0}")] Decode(#[from] codec::Error), @@ -85,15 +82,23 @@ impl CodegenError { #[derive(Debug, thiserror::Error)] #[non_exhaustive] pub enum FetchMetadataError { + /// Error decoding from a hex value. #[error("Cannot decode hex value: {0}")] DecodeError(#[from] hex::FromHexError), + /// Some SCALE codec error. #[error("Cannot scale encode/decode value: {0}")] CodecError(#[from] codec::Error), + /// JSON-RPC error fetching metadata. #[cfg(feature = "fetch-metadata")] #[error("Request error: {0}")] RequestError(#[from] jsonrpsee::core::Error), + /// Failed IO when fetching from a file. + #[error("Failed IO for {0}, make sure that you are providing the correct file path for metadata: {1}")] + Io(String, std::io::Error), + /// URL scheme is not http, https, ws or wss. #[error("'{0}' not supported, supported URI schemes are http, https, ws or wss.")] InvalidScheme(String), + /// Some other error. #[error("Other error: {0}")] Other(String), } diff --git a/codegen/src/utils/fetch_metadata.rs b/codegen/src/fetch_metadata.rs similarity index 90% rename from codegen/src/utils/fetch_metadata.rs rename to codegen/src/fetch_metadata.rs index 66689b37c7..c32377c085 100644 --- a/codegen/src/utils/fetch_metadata.rs +++ b/codegen/src/fetch_metadata.rs @@ -2,17 +2,22 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. +//! Helper methods for fetching metadata from a file or URL. + use crate::error::FetchMetadataError; use codec::{Decode, Encode}; use jsonrpsee::{ async_client::ClientBuilder, - client_transport::ws::{Url, WsTransportClientBuilder}, + client_transport::ws::WsTransportClientBuilder, core::{client::ClientT, Error}, http_client::HttpClientBuilder, rpc_params, }; use std::time::Duration; +// Part of the public interface: +pub use jsonrpsee::client_transport::ws::Url; + /// The metadata version that is fetched from the node. #[derive(Default, Debug, Clone, Copy)] pub enum MetadataVersion { @@ -44,20 +49,24 @@ impl std::str::FromStr for MetadataVersion { } } +/// Fetch metadata from a file. +pub fn fetch_metadata_from_file_blocking( + path: &std::path::Path, +) -> Result, FetchMetadataError> { + use std::io::Read; + let to_err = |err| FetchMetadataError::Io(path.to_string_lossy().into(), err); + let mut file = std::fs::File::open(path).map_err(to_err)?; + let mut bytes = Vec::new(); + file.read_to_end(&mut bytes).map_err(to_err)?; + Ok(bytes) +} + /// Returns the metadata bytes from the provided URL, blocking the current thread. -pub fn fetch_metadata_bytes_blocking( +pub fn fetch_metadata_from_url_blocking( url: Url, version: MetadataVersion, ) -> Result, FetchMetadataError> { - tokio_block_on(fetch_metadata_bytes(url, version)) -} - -/// Returns the raw, 0x prefixed metadata hex from the provided URL, blocking the current thread. -pub fn fetch_metadata_hex_blocking( - url: Url, - version: MetadataVersion, -) -> Result { - tokio_block_on(fetch_metadata_hex(url, version)) + tokio_block_on(fetch_metadata_from_url(url, version)) } // Block on some tokio runtime for sync contexts @@ -70,7 +79,7 @@ fn tokio_block_on>(fut: Fut) -> T { } /// Returns the metadata bytes from the provided URL. -pub async fn fetch_metadata_bytes( +pub async fn fetch_metadata_from_url( url: Url, version: MetadataVersion, ) -> Result, FetchMetadataError> { @@ -83,16 +92,6 @@ pub async fn fetch_metadata_bytes( Ok(bytes) } -/// Returns the raw, 0x prefixed metadata hex from the provided URL. -pub async fn fetch_metadata_hex( - url: Url, - version: MetadataVersion, -) -> Result { - let bytes = fetch_metadata_bytes(url, version).await?; - let hex_data = format!("0x{}", hex::encode(bytes)); - Ok(hex_data) -} - async fn fetch_metadata_ws( url: Url, version: MetadataVersion, diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 8171c2ee49..e319b1aaff 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -2,65 +2,267 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -//! Library to generate an API for a Substrate runtime from its metadata. -//! -//! ## Generated Structure -//! -//! The API generator logic: -//! - At the root there is the `item_mod` provided (ie `pub mod api {}`) -//! - Pallets are represented by a child module (ie `pub mod PalletName {}`) of the root -//! - Each pallet exposes as child modules (if applicable): -//! - Calls (`pub mod calls {}`) -//! - Events (`pub mod events {}`) -//! - Storage (`pub mod storage {}`) -//! - Constants (`pub mod constants {}`) -//! -//! ## Example -//! -//! ```no_run -//! use std::fs; -//! use codec::Decode; -//! use subxt_metadata::Metadata; -//! use subxt_codegen::{CratePath, DerivesRegistry, TypeSubstitutes}; -//! -//! let encoded = fs::read("../artifacts/polkadot_metadata_full.scale").unwrap(); -//! -//! // Runtime metadata obtained from a node. -//! let metadata = Metadata::decode(&mut &*encoded).unwrap(); -//! // Module under which the API is generated. -//! let item_mod = syn::parse_quote!( -//! pub mod api {} -//! ); -//! // Default module derivatives. -//! let mut derives = DerivesRegistry::with_default_derives(&CratePath::default()); -//! // Default type substitutes. -//! let substs = TypeSubstitutes::with_default_substitutes(&CratePath::default()); -//! // Generate the Runtime API. -//! let generator = subxt_codegen::RuntimeGenerator::new(metadata); -//! // Include metadata documentation in the Runtime API. -//! let generate_docs = true; -//! let runtime_api = generator.generate_runtime(item_mod, derives, substs, CratePath::default(), generate_docs).unwrap(); -//! println!("{}", runtime_api); -//! ``` +//! Generate a type safe Subxt interface for a Substrate runtime from its metadata. +//! This is used by the `#[subxt]` macro and `subxt codegen` CLI command, but can also +//! be used directly if preferable. #![deny(unused_crate_dependencies, missing_docs)] mod api; -mod error; mod ir; mod types; +pub mod error; + +// These should probably be in a separate crate; they are used by the +// macro and CLI tool, so they only live here because this is a common +// crate that both depend on. #[cfg(feature = "fetch-metadata")] -pub mod utils; +pub mod fetch_metadata; #[cfg(feature = "web")] use getrandom as _; -pub use self::{ - api::{GenerateRuntimeApi, RuntimeGenerator}, - error::{CodegenError, TypeSubstitutionError}, - types::{ - CratePath, Derives, DerivesRegistry, Module, TypeDefGen, TypeDefParameters, TypeGenerator, - TypeSubstitutes, - }, -}; +use api::RuntimeGenerator; +use proc_macro2::TokenStream as TokenStream2; +use std::collections::HashMap; + +// We expose these only because they are currently needed in subxt-explorer. +// Eventually we'll move the type generation stuff out into a separate crate. +#[doc(hidden)] +pub mod __private { + pub use crate::types::{DerivesRegistry, TypeDefGen, TypeGenerator, TypeSubstitutes}; +} + +// Part of the public interface, so expose: +pub use error::CodegenError; +pub use subxt_metadata::Metadata; +pub use syn; + +/// Generate a type safe interface to use with `subxt`. +/// The options exposed here are similar to those exposed via +/// the `#[subxt]` macro or via the `subxt codegen` CLI command. +/// Both use this under the hood. +/// +/// # Example +/// +/// Generating an interface using all of the defaults: +/// +/// ```rust +/// use codec::Decode; +/// use subxt_codegen::{ Metadata, CodegenBuilder }; +/// +/// // Get hold of and decode some metadata: +/// let encoded = std::fs::read("../artifacts/polkadot_metadata_full.scale").unwrap(); +/// let metadata = Metadata::decode(&mut &*encoded).unwrap(); +/// +/// // Generate a TokenStream representing the code for the interface. +/// // This can be converted to a string, displayed as-is or output from a macro. +/// let token_stream = CodegenBuilder::new().generate(metadata); +/// ```` +pub struct CodegenBuilder { + crate_path: syn::Path, + use_default_derives: bool, + use_default_substitutions: bool, + generate_docs: bool, + runtime_types_only: bool, + item_mod: syn::ItemMod, + extra_global_derives: Vec, + extra_global_attributes: Vec, + type_substitutes: HashMap, + derives_for_type: HashMap>, + attributes_for_type: HashMap>, +} + +impl Default for CodegenBuilder { + fn default() -> Self { + CodegenBuilder { + crate_path: syn::parse_quote!(::subxt), + use_default_derives: true, + use_default_substitutions: true, + generate_docs: true, + runtime_types_only: false, + item_mod: syn::parse_quote!( + pub mod api {} + ), + extra_global_derives: Vec::new(), + extra_global_attributes: Vec::new(), + type_substitutes: HashMap::new(), + derives_for_type: HashMap::new(), + attributes_for_type: HashMap::new(), + } + } +} + +impl CodegenBuilder { + /// Construct a builder to configure and generate a type-safe interface for Subxt. + pub fn new() -> Self { + CodegenBuilder::default() + } + + /// Disable the default derives that are applied to all types. + /// + /// # Warning + /// + /// This is not recommended, and is highly likely to break some part of the + /// generated interface. Expect compile errors. + pub fn disable_default_derives(&mut self) { + self.use_default_derives = false; + } + + /// Disable the default type substitutions that are applied to the generated + /// code. + /// + /// # Warning + /// + /// This is not recommended, and is highly likely to break some part of the + /// generated interface. Expect compile errors. + pub fn disable_default_substitutes(&mut self) { + self.use_default_substitutions = false; + } + + /// Disable the output of doc comments associated with the generated types and + /// methods. This can reduce the generated code size at the expense of losing + /// documentation. + pub fn no_docs(&mut self) { + self.generate_docs = false; + } + + /// Only generate the types, and don't generate the rest of the Subxt specific + /// interface. + pub fn runtime_types_only(&mut self) { + self.runtime_types_only = true; + } + + /// Set the additional derives that will be applied to all types. By default, + /// a set of derives required for Subxt are automatically added for all types. + /// + /// # Warning + /// + /// Invalid derives, or derives that cannot be applied to _all_ of the generated + /// types (taking into account that some types are substituted for hand written ones + /// that we cannot add extra derives for) will lead to compile errors in the + /// generated code. + pub fn set_additional_global_derives(&mut self, derives: Vec) { + self.extra_global_derives = derives; + } + + /// Set the additional attributes that will be applied to all types. By default, + /// a set of attributes required for Subxt are automatically added for all types. + /// + /// # Warning + /// + /// Invalid attributes can very easily lead to compile errors in the generated code. + pub fn set_additional_global_attributes(&mut self, attributes: Vec) { + self.extra_global_attributes = attributes; + } + + /// Set additional derives for a specific type at the path given. + /// + /// # Warning + /// + /// For composite types, you may also need to set the same additional derives on all of + /// the contained types as well to avoid compile errors in the generated code. + pub fn add_derives_for_type( + &mut self, + ty: syn::TypePath, + derives: impl IntoIterator, + ) { + self.derives_for_type.entry(ty).or_default().extend(derives); + } + + /// Set additional attributes for a specific type at the path given. + /// + /// # Warning + /// + /// For composite types, you may also need to consider contained types and whether they need + /// similar attributes setting. + pub fn add_attributes_for_type( + &mut self, + ty: syn::TypePath, + attributes: impl IntoIterator, + ) { + self.attributes_for_type + .entry(ty) + .or_default() + .extend(attributes); + } + + /// Substitute a type at the given path with some type at the second path. During codegen, + /// we will avoid generating the type at the first path given, and instead point any references + /// to that type to the second path given. + /// + /// The substituted type will need to implement the relevant traits to be compatible with the + /// original, and it will need to SCALE encode and SCALE decode in a compatible way. + pub fn set_type_substitute(&mut self, ty: syn::Path, with: syn::Path) { + self.type_substitutes.insert(ty, with); + } + + /// By default, all of the code is generated inside a module `pub mod api {}`. We decorate + /// this module with a few attributes to reduce compile warnings and things. You can provide a + /// target module here, allowing you to add additional attributes or inner code items (with the + /// warning that duplicate identifiers will lead to compile errors). + pub fn set_target_module(&mut self, item_mod: syn::ItemMod) { + self.item_mod = item_mod; + } + + /// Set the path to the `subxt` crate. By default, we expect it to be at `::subxt`. + pub fn set_subxt_crate_path(&mut self, crate_path: syn::Path) { + self.crate_path = crate_path; + } + + /// Generate an interface, assuming that the default path to the `subxt` crate is `::subxt`. + /// If the `subxt` crate is not available as a top level dependency, use `generate` and provide + /// a valid path to the `subxt¦ crate. + pub fn generate(self, metadata: Metadata) -> Result { + let crate_path = self.crate_path; + + let mut derives_registry = if self.use_default_derives { + types::DerivesRegistry::with_default_derives(&crate_path) + } else { + types::DerivesRegistry::new() + }; + + derives_registry.extend_for_all(self.extra_global_derives, self.extra_global_attributes); + + for (ty, derives) in self.derives_for_type { + derives_registry.extend_for_type(ty, derives, vec![]); + } + for (ty, attributes) in self.attributes_for_type { + derives_registry.extend_for_type(ty, vec![], attributes); + } + + let mut type_substitutes = if self.use_default_substitutions { + types::TypeSubstitutes::with_default_substitutes(&crate_path) + } else { + types::TypeSubstitutes::new() + }; + + for (from, with) in self.type_substitutes { + let abs_path = with.try_into()?; + type_substitutes.insert(from, abs_path)?; + } + + let item_mod = self.item_mod; + let generator = RuntimeGenerator::new(metadata); + let should_gen_docs = self.generate_docs; + + if self.runtime_types_only { + generator.generate_runtime_types( + item_mod, + derives_registry, + type_substitutes, + crate_path, + should_gen_docs, + ) + } else { + generator.generate_runtime( + item_mod, + derives_registry, + type_substitutes, + crate_path, + should_gen_docs, + ) + } + } +} diff --git a/codegen/src/types/composite_def.rs b/codegen/src/types/composite_def.rs index ca63aea78f..37787df083 100644 --- a/codegen/src/types/composite_def.rs +++ b/codegen/src/types/composite_def.rs @@ -4,7 +4,7 @@ use crate::error::CodegenError; -use super::{CratePath, Derives, Field, TypeDefParameters, TypeGenerator, TypeParameter, TypePath}; +use super::{Derives, Field, TypeDefParameters, TypeGenerator, TypeParameter, TypePath}; use proc_macro2::TokenStream; use quote::{format_ident, quote}; use scale_info::{form::PortableForm, Type, TypeDef, TypeDefPrimitive}; @@ -36,7 +36,7 @@ impl CompositeDef { field_visibility: Option, type_gen: &TypeGenerator, docs: &[String], - crate_path: &CratePath, + crate_path: &syn::Path, ) -> Result { let mut derives = type_gen.type_derives(ty)?; let fields: Vec<_> = fields_def.field_types().collect(); diff --git a/codegen/src/types/derives.rs b/codegen/src/types/derives.rs index 61a89f1b5b..429591ed8a 100644 --- a/codegen/src/types/derives.rs +++ b/codegen/src/types/derives.rs @@ -2,7 +2,6 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -use crate::CratePath; use syn::{parse_quote, Path}; use std::collections::{HashMap, HashSet}; @@ -35,7 +34,7 @@ impl DerivesRegistry { /// /// The `crate_path` denotes the `subxt` crate access path in the /// generated code. - pub fn with_default_derives(crate_path: &CratePath) -> Self { + pub fn with_default_derives(crate_path: &syn::Path) -> Self { Self { default_derives: Derives::with_defaults(crate_path), specific_type_derives: Default::default(), @@ -117,7 +116,7 @@ impl Derives { /// Creates a new instance of `Derives` with the `crate_path` prepended /// to the set of default derives that reside in `subxt`. - pub fn with_defaults(crate_path: &CratePath) -> Self { + pub fn with_defaults(crate_path: &syn::Path) -> Self { let mut derives = HashSet::new(); let mut attributes = HashSet::new(); @@ -148,7 +147,7 @@ impl Derives { } /// Add `#crate_path::ext::codec::CompactAs` to the derives. - pub fn insert_codec_compact_as(&mut self, crate_path: &CratePath) { + pub fn insert_codec_compact_as(&mut self, crate_path: &syn::Path) { self.insert_derive(parse_quote!(#crate_path::ext::codec::CompactAs)); } diff --git a/codegen/src/types/mod.rs b/codegen/src/types/mod.rs index f565fb0460..4d1738f1e0 100644 --- a/codegen/src/types/mod.rs +++ b/codegen/src/types/mod.rs @@ -41,7 +41,7 @@ pub struct TypeGenerator<'a> { /// Set of derives with which to annotate generated types. derives: DerivesRegistry, /// The `subxt` crate access path in the generated code. - crate_path: CratePath, + crate_path: syn::Path, /// True if codegen should generate the documentation for the API. should_gen_docs: bool, } @@ -53,7 +53,7 @@ impl<'a> TypeGenerator<'a> { root_mod: &'static str, type_substitutes: TypeSubstitutes, derives: DerivesRegistry, - crate_path: CratePath, + crate_path: syn::Path, should_gen_docs: bool, ) -> Self { let root_mod_ident = Ident::new(root_mod, Span::call_site()); @@ -334,55 +334,3 @@ impl Module { &self.root_mod } } - -/// A newtype wrapper which stores the path to the Subxt crate. -#[derive(Debug, Clone)] -pub struct CratePath(syn::Path); - -impl CratePath { - /// Create a new `CratePath` from a `syn::Path`. - pub fn new(path: syn::Path) -> Self { - Self(path) - } -} - -impl Default for CratePath { - fn default() -> Self { - Self(syn::parse_quote!(::subxt)) - } -} - -impl From for CratePath { - fn from(path: syn::Path) -> Self { - CratePath::new(path) - } -} - -impl ToTokens for CratePath { - fn to_tokens(&self, tokens: &mut TokenStream) { - self.0.to_tokens(tokens) - } -} - -impl From<&str> for CratePath { - fn from(crate_path: &str) -> Self { - Self(syn::parse_str(crate_path).unwrap_or_else(|err| { - panic!("failed converting {crate_path:?} to `syn::Path`: {err:?}"); - })) - } -} - -impl From for CratePath { - fn from(crate_path: String) -> Self { - CratePath::from(crate_path.as_str()) - } -} - -impl From> for CratePath { - fn from(maybe_crate_path: Option) -> Self { - match maybe_crate_path { - None => CratePath::default(), - Some(crate_path) => crate_path.into(), - } - } -} diff --git a/codegen/src/types/substitutes.rs b/codegen/src/types/substitutes.rs index 740de95cc0..c2639c3736 100644 --- a/codegen/src/types/substitutes.rs +++ b/codegen/src/types/substitutes.rs @@ -2,7 +2,7 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -use crate::{error::TypeSubstitutionError, CratePath}; +use crate::error::TypeSubstitutionError; use std::{borrow::Borrow, collections::HashMap}; use syn::{parse_quote, spanned::Spanned as _}; @@ -55,7 +55,7 @@ impl TypeSubstitutes { /// /// The `crate_path` denotes the `subxt` crate access path in the /// generated code. - pub fn with_default_substitutes(crate_path: &CratePath) -> Self { + pub fn with_default_substitutes(crate_path: &syn::Path) -> Self { // Some hardcoded default type substitutes, can be overridden by user let defaults = [ ( diff --git a/codegen/src/types/tests.rs b/codegen/src/types/tests.rs index e1f4caddc5..7aa91e21e1 100644 --- a/codegen/src/types/tests.rs +++ b/codegen/src/types/tests.rs @@ -34,7 +34,7 @@ fn generate_struct_with_primitives() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -86,7 +86,7 @@ fn generate_struct_with_a_struct_field() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -140,7 +140,7 @@ fn generate_tuple_struct() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -231,7 +231,7 @@ fn derive_compact_as_for_uint_wrapper_structs() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -328,7 +328,7 @@ fn generate_enum() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -392,7 +392,7 @@ fn compact_fields() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -460,7 +460,7 @@ fn compact_generic_parameter() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -507,7 +507,7 @@ fn generate_array_field() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -550,7 +550,7 @@ fn option_fields() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -596,7 +596,7 @@ fn box_fields_struct() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -642,7 +642,7 @@ fn box_fields_enum() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -688,7 +688,7 @@ fn range_fields() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -738,7 +738,7 @@ fn generics() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -795,7 +795,7 @@ fn generics_nested() { registry.register_type(&meta_type::>()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -852,7 +852,7 @@ fn generate_bitvec() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -911,7 +911,7 @@ fn generics_with_alias_adds_phantom_data_marker() { registry.register_type(&meta_type::>()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -982,7 +982,7 @@ fn modules() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -1051,7 +1051,7 @@ fn dont_force_struct_names_camel_case() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", @@ -1094,7 +1094,7 @@ fn apply_user_defined_derives_for_all_types() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); // configure derives let mut derives = DerivesRegistry::with_default_derives(&crate_path); derives.extend_for_all( @@ -1156,7 +1156,7 @@ fn apply_user_defined_derives_for_specific_types() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); // configure derives let mut derives = DerivesRegistry::with_default_derives(&crate_path); // for all types @@ -1233,7 +1233,7 @@ fn opt_out_from_default_derives() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); // configure derives let mut derives = DerivesRegistry::new(); derives.extend_for_all( @@ -1293,7 +1293,7 @@ fn opt_out_from_default_substitutes() { registry.register_type(&meta_type::()); let portable_types: PortableRegistry = registry.into(); - let crate_path = "::subxt_path".into(); + let crate_path = syn::parse_str("::subxt_path").unwrap(); let type_gen = TypeGenerator::new( &portable_types, "root", diff --git a/codegen/src/types/type_def.rs b/codegen/src/types/type_def.rs index 57470abf7f..b257c90308 100644 --- a/codegen/src/types/type_def.rs +++ b/codegen/src/types/type_def.rs @@ -5,8 +5,7 @@ use crate::error::CodegenError; use super::{ - CompositeDef, CompositeDefFields, CratePath, Derives, TypeDefParameters, TypeGenerator, - TypeParameter, + CompositeDef, CompositeDefFields, Derives, TypeDefParameters, TypeGenerator, TypeParameter, }; use proc_macro2::TokenStream; use quote::{format_ident, quote}; @@ -34,7 +33,7 @@ impl TypeDefGen { pub fn from_type( ty: &Type, type_gen: &TypeGenerator, - crate_path: &CratePath, + crate_path: &syn::Path, should_gen_docs: bool, ) -> Result { let derives = type_gen.type_derives(ty)?; diff --git a/codegen/src/types/type_path.rs b/codegen/src/types/type_path.rs index 9dafb62b5f..044ee2df6e 100644 --- a/codegen/src/types/type_path.rs +++ b/codegen/src/types/type_path.rs @@ -2,8 +2,6 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -use crate::CratePath; - use proc_macro2::{Ident, TokenStream}; use quote::format_ident; use scale_info::{form::PortableForm, Path, TypeDefPrimitive}; @@ -121,12 +119,12 @@ pub enum TypePathType { Compact { inner: Box, is_field: bool, - crate_path: CratePath, + crate_path: syn::Path, }, BitVec { bit_order_type: Box, bit_store_type: Box, - crate_path: CratePath, + crate_path: syn::Path, }, } diff --git a/codegen/src/utils/mod.rs b/codegen/src/utils/mod.rs deleted file mode 100644 index af5c00c2ad..0000000000 --- a/codegen/src/utils/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -//! Utilities to help with fetching and decoding metadata. - -mod fetch_metadata; - -// easy access to this type needed for fetching metadata: -pub use jsonrpsee::client_transport::ws::Url; - -pub use fetch_metadata::{ - fetch_metadata_bytes, fetch_metadata_bytes_blocking, fetch_metadata_hex, - fetch_metadata_hex_blocking, MetadataVersion, -}; diff --git a/examples/parachain-example/Cargo.lock b/examples/parachain-example/Cargo.lock index f82ebc79f3..8cde25b366 100644 --- a/examples/parachain-example/Cargo.lock +++ b/examples/parachain-example/Cargo.lock @@ -210,7 +210,7 @@ dependencies = [ "polling", "rustix 0.37.20", "slab", - "socket2", + "socket2 0.4.9", "waker-fn", ] @@ -261,13 +261,13 @@ checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -517,9 +517,12 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -781,12 +784,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core 0.20.1", - "darling_macro 0.20.1", + "darling_core 0.20.3", + "darling_macro 0.20.3", ] [[package]] @@ -805,16 +808,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -830,13 +833,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core 0.20.1", + "darling_core 0.20.3", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -962,9 +965,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "environmental" @@ -1160,7 +1163,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -1440,7 +1443,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -1449,10 +1452,11 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.2" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ + "futures-util", "http", "hyper", "log", @@ -1460,7 +1464,6 @@ dependencies = [ "rustls-native-certs", "tokio", "tokio-rustls", - "webpki-roots", ] [[package]] @@ -1619,9 +1622,9 @@ dependencies = [ [[package]] name = "jsonrpsee" -version = "0.16.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" +checksum = "affdc52f7596ccb2d7645231fc6163bb314630c989b64998f3699a28b4d5d4dc" dependencies = [ "jsonrpsee-client-transport", "jsonrpsee-core", @@ -1631,14 +1634,13 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.16.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965de52763f2004bc91ac5bcec504192440f0b568a5d621c59d9dbd6f886c3fb" +checksum = "b5b005c793122d03217da09af68ba9383363caa950b90d3436106df8cabce935" dependencies = [ "futures-util", "http", "jsonrpsee-core", - "jsonrpsee-types", "pin-project", "rustls-native-certs", "soketto", @@ -1647,20 +1649,19 @@ dependencies = [ "tokio-rustls", "tokio-util", "tracing", - "webpki-roots", + "url", ] [[package]] name = "jsonrpsee-core" -version = "0.16.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" +checksum = "da2327ba8df2fdbd5e897e2b5ed25ce7f299d345b9736b6828814c3dbd1fd47b" dependencies = [ "anyhow", "async-lock", "async-trait", "beef", - "futures-channel", "futures-timer", "futures-util", "hyper", @@ -1675,28 +1676,29 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.16.2" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc345b0a43c6bc49b947ebeb936e886a419ee3d894421790c969cc56040542ad" +checksum = "5f80c17f62c7653ce767e3d7288b793dfec920f97067ceb189ebdd3570f2bc20" 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.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd522fe1ce3702fd94812965d7bb7a3364b1c9aba743944c5a00529aae80f8c" +checksum = "5be0be325642e850ed0bdff426674d2e66b2b7117c9be23a7caef68a2902b7d9" dependencies = [ "anyhow", "beef", @@ -1723,9 +1725,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libm" @@ -1841,9 +1843,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memfd" @@ -1865,7 +1867,7 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.32.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" dependencies = [ @@ -2064,8 +2066,8 @@ version = "0.1.0" dependencies = [ "futures", "parity-scale-codec", - "scale-decode", - "scale-encode", + "scale-decode 0.7.0", + "scale-encode 0.3.0", "sp-core", "sp-runtime", "subxt", @@ -2185,14 +2187,14 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -2253,9 +2255,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "primitive-types" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", @@ -2300,9 +2302,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -2318,9 +2320,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -2428,19 +2430,19 @@ checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "regex" -version = "1.9.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.2", - "regex-syntax 0.7.4", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -2454,13 +2456,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.4", + "regex-syntax 0.8.2", ] [[package]] @@ -2471,9 +2473,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "ring" @@ -2485,11 +2487,25 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +dependencies = [ + "cc", + "getrandom 0.2.10", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.48.0", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -2547,14 +2563,14 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.8" +version = "0.21.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" dependencies = [ "log", - "ring", + "ring 0.17.5", + "rustls-webpki", "sct", - "webpki", ] [[package]] @@ -2578,6 +2594,16 @@ dependencies = [ "base64 0.21.2", ] +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring 0.17.5", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.12" @@ -2606,6 +2632,16 @@ name = "scale-bits" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dd7aca73785181cc41f0bbe017263e682b585ca660540ba569133901d013ecf" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "scale-bits" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "036575c29af9b6e4866ffb7fa055dbf623fe7a9cc159b33786de6013a6969d89" dependencies = [ "parity-scale-codec", "scale-info", @@ -2620,13 +2656,28 @@ checksum = "f0459d00b0dbd2e765009924a78ef36b2ff7ba116292d732f00eb0ed8e465d15" dependencies = [ "parity-scale-codec", "primitive-types", - "scale-bits", - "scale-decode-derive", + "scale-bits 0.3.0", + "scale-decode-derive 0.7.0", "scale-info", "smallvec", "thiserror", ] +[[package]] +name = "scale-decode" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7789f5728e4e954aaa20cadcc370b99096fb8645fca3c9333ace44bb18f30095" +dependencies = [ + "derive_more", + "parity-scale-codec", + "primitive-types", + "scale-bits 0.4.0", + "scale-decode-derive 0.9.0", + "scale-info", + "smallvec", +] + [[package]] name = "scale-decode-derive" version = "0.7.0" @@ -2640,6 +2691,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "scale-decode-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27873eb6005868f8cc72dcfe109fae664cf51223d35387bc2f28be4c28d94c47" +dependencies = [ + "darling 0.14.4", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "scale-encode" version = "0.3.0" @@ -2648,13 +2712,28 @@ checksum = "b0401b7cdae8b8aa33725f3611a051358d5b32887ecaa0fda5953a775b2d4d76" dependencies = [ "parity-scale-codec", "primitive-types", - "scale-bits", - "scale-encode-derive", + "scale-bits 0.3.0", + "scale-encode-derive 0.3.0", "scale-info", "smallvec", "thiserror", ] +[[package]] +name = "scale-encode" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d70cb4b29360105483fac1ed567ff95d65224a14dd275b6303ed0a654c78de5" +dependencies = [ + "derive_more", + "parity-scale-codec", + "primitive-types", + "scale-bits 0.4.0", + "scale-encode-derive 0.5.0", + "scale-info", + "smallvec", +] + [[package]] name = "scale-encode-derive" version = "0.3.0" @@ -2669,10 +2748,23 @@ dependencies = [ ] [[package]] -name = "scale-info" -version = "2.9.0" +name = "scale-encode-derive" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" +checksum = "995491f110efdc6bea96d6a746140e32bfceb4ea47510750a5467295a4707a25" +dependencies = [ + "darling 0.14.4", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-info" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" dependencies = [ "bitvec", "cfg-if", @@ -2684,9 +2776,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" +checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -2696,21 +2788,21 @@ dependencies = [ [[package]] name = "scale-value" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2096d36e94ce9bf87d8addb752423b6b19730dc88edd7cc452bb2b90573f7a7" +checksum = "6538d1cc1af9c0baf401c57da8a6d4730ef582db0d330d2efa56ec946b5b0283" dependencies = [ "base58", "blake2", + "derive_more", "either", "frame-metadata 15.1.0", "parity-scale-codec", - "scale-bits", - "scale-decode", - "scale-encode", + "scale-bits 0.4.0", + "scale-decode 0.9.0", + "scale-encode 0.5.0", "scale-info", "serde", - "thiserror", "yap", ] @@ -2781,8 +2873,8 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -2861,9 +2953,9 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "serde" -version = "1.0.171" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" dependencies = [ "serde_derive", ] @@ -2879,20 +2971,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "serde_json" -version = "1.0.100" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -3137,6 +3229,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "soketto" version = "0.7.1" @@ -3249,7 +3351,7 @@ checksum = "c7f531814d2f16995144c74428830ccf7d94ff4a7749632b83ad8199b181140c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -3368,7 +3470,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -3551,8 +3653,9 @@ checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" [[package]] name = "subxt" -version = "0.29.0" +version = "0.32.1" dependencies = [ + "async-trait", "base58", "blake2", "derivative", @@ -3564,16 +3667,14 @@ dependencies = [ "jsonrpsee", "parity-scale-codec", "primitive-types", - "scale-bits", - "scale-decode", - "scale-encode", + "scale-bits 0.4.0", + "scale-decode 0.9.0", + "scale-encode 0.5.0", "scale-info", "scale-value", "serde", "serde_json", - "sp-core", "sp-core-hashing", - "sp-runtime", "subxt-lightclient", "subxt-macro", "subxt-metadata", @@ -3583,7 +3684,7 @@ dependencies = [ [[package]] name = "subxt-codegen" -version = "0.29.0" +version = "0.32.1" dependencies = [ "frame-metadata 16.0.0", "heck", @@ -3594,14 +3695,14 @@ dependencies = [ "quote", "scale-info", "subxt-metadata", - "syn 2.0.25", + "syn 2.0.38", "thiserror", "tokio", ] [[package]] name = "subxt-lightclient" -version = "0.29.0" +version = "0.32.1" dependencies = [ "futures", "futures-util", @@ -3616,17 +3717,17 @@ dependencies = [ [[package]] name = "subxt-macro" -version = "0.29.0" +version = "0.32.1" dependencies = [ - "darling 0.20.1", + "darling 0.20.3", "proc-macro-error", "subxt-codegen", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "subxt-metadata" -version = "0.29.0" +version = "0.32.1" dependencies = [ "frame-metadata 16.0.0", "parity-scale-codec", @@ -3637,7 +3738,7 @@ dependencies = [ [[package]] name = "subxt-signer" -version = "0.29.0" +version = "0.32.1" dependencies = [ "bip39", "hex", @@ -3668,9 +3769,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.25" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -3691,9 +3792,9 @@ checksum = "1b1c7f239eb94671427157bd93b3694320f3668d4e1eff08c7285366fd777fac" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] @@ -3720,13 +3821,13 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] @@ -3784,18 +3885,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] @@ -3808,18 +3908,17 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[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]] @@ -3865,6 +3964,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" @@ -3873,11 +3993,11 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3885,20 +4005,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -4048,6 +4168,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.4.0" @@ -4119,7 +4245,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", "wasm-bindgen-shared", ] @@ -4141,7 +4267,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4345,25 +4471,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" @@ -4562,9 +4669,9 @@ dependencies = [ [[package]] name = "yap" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2a7eb6d82a11e4d0b8e6bda8347169aff4ccd8235d039bba7c47482d977dcf7" +checksum = "ff4524214bc4629eba08d78ceb1d6507070cc0bcbbed23af74e19e6e924a24cf" [[package]] name = "zeroize" @@ -4583,5 +4690,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.38", ] diff --git a/examples/parachain-example/src/main.rs b/examples/parachain-example/src/main.rs index 9b7537d5df..71c774bed8 100644 --- a/examples/parachain-example/src/main.rs +++ b/examples/parachain-example/src/main.rs @@ -1,5 +1,5 @@ use subxt::{ - Config, PolkadotConfig, SubstrateConfig, + PolkadotConfig, utils::{AccountId32, MultiAddress}, OnlineClient, }; @@ -8,19 +8,9 @@ use subxt_signer::sr25519::dev::{self}; #[subxt::subxt(runtime_metadata_path = "statemint_metadata.scale")] pub mod statemint {} -/// Custom config that works with Statemint: -pub enum StatemintConfig {} - -impl Config for StatemintConfig { - type Hash = ::Hash; - type AccountId = ::AccountId; - type Address = ::Address; - type Signature = ::Signature; - type Hasher = ::Hasher; - type Header = ::Header; - type ExtrinsicParams = ::ExtrinsicParams; -} - +// PolkadotConfig or SubstrateConfig will suffice for this example at the moment, +// but PolkadotConfig is a little more correct, having the right `Address` type. +type StatemintConfig = PolkadotConfig; #[tokio::main] pub async fn main() { diff --git a/macro/Cargo.toml b/macro/Cargo.toml index 2845e0f3c0..b374dbf572 100644 --- a/macro/Cargo.toml +++ b/macro/Cargo.toml @@ -20,7 +20,8 @@ web = ["subxt-codegen/web"] proc-macro = true [dependencies] +codec = { package = "parity-scale-codec", workspace = true } darling = { workspace = true } proc-macro-error = { workspace = true } syn = { workspace = true } -subxt-codegen = { workspace = true } +subxt-codegen = { workspace = true, features = ["fetch-metadata"] } diff --git a/macro/src/lib.rs b/macro/src/lib.rs index cde0c28427..d53c15af4e 100644 --- a/macro/src/lib.rs +++ b/macro/src/lib.rs @@ -4,11 +4,15 @@ extern crate proc_macro; +use codec::Decode; use darling::{ast::NestedMeta, FromMeta}; use proc_macro::TokenStream; use proc_macro_error::{abort_call_site, proc_macro_error}; use subxt_codegen::{ - utils::Url, CodegenError, DerivesRegistry, GenerateRuntimeApi, TypeSubstitutes, + fetch_metadata::{ + fetch_metadata_from_file_blocking, fetch_metadata_from_url_blocking, MetadataVersion, Url, + }, + CodegenBuilder, CodegenError, }; use syn::{parse_macro_input, punctuated::Punctuated}; @@ -38,7 +42,7 @@ struct RuntimeMetadataArgs { #[darling(multiple)] substitute_type: Vec, #[darling(default, rename = "crate")] - crate_path: Option, + crate_path: Option, #[darling(default)] generate_docs: darling::util::Flag, #[darling(default)] @@ -85,62 +89,61 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream { Err(e) => return TokenStream::from(e.write_errors()), }; - let crate_path = match args.crate_path { - Some(crate_path) => crate_path.into(), - None => subxt_codegen::CratePath::default(), - }; - let mut derives_registry = if args.no_default_derives { - DerivesRegistry::new() - } else { - DerivesRegistry::with_default_derives(&crate_path) - }; + let mut codegen = CodegenBuilder::new(); - let universal_derives = args.derive_for_all_types.unwrap_or_default(); - let universal_attributes = args.attributes_for_all_types.unwrap_or_default(); - derives_registry.extend_for_all( - universal_derives, - universal_attributes.iter().map(|a| a.0.clone()), + // Use the item module that the macro is on: + codegen.set_target_module(item_mod); + + // Use the provided crate path: + if let Some(crate_path) = args.crate_path { + codegen.set_subxt_crate_path(crate_path) + } + + // Respect the boolean flags: + if args.runtime_types_only { + codegen.runtime_types_only(); + } + if args.no_default_derives { + codegen.disable_default_derives(); + } + if args.no_default_substitutions { + codegen.disable_default_substitutes(); + } + if !args.generate_docs.is_present() { + codegen.no_docs() + } + + // Configure derives: + codegen.set_additional_global_derives( + args.derive_for_all_types + .unwrap_or_default() + .into_iter() + .collect(), ); - - for derives in &args.derive_for_type { - derives_registry.extend_for_type( - derives.path.clone(), - derives.derive.iter().cloned(), - vec![], - ) - } - for attributes in &args.attributes_for_type { - derives_registry.extend_for_type( - attributes.path.clone(), - vec![], - attributes.attributes.iter().map(|a| a.0.clone()), - ) + for d in args.derive_for_type { + codegen.add_derives_for_type(d.path, d.derive.into_iter()); } - let mut type_substitutes = if args.no_default_substitutions { - TypeSubstitutes::new() - } else { - TypeSubstitutes::with_default_substitutes(&crate_path) - }; - let substitute_args_res: Result<(), _> = args.substitute_type.into_iter().try_for_each(|sub| { - sub.with - .try_into() - .and_then(|with| type_substitutes.insert(sub.path, with)) - }); - - if let Err(err) = substitute_args_res { - return CodegenError::from(err).into_compile_error().into(); + // Configure attributes: + codegen.set_additional_global_attributes( + args.attributes_for_all_types + .unwrap_or_default() + .into_iter() + .map(|a| a.0) + .collect(), + ); + for d in args.attributes_for_type { + codegen.add_attributes_for_type(d.path, d.attributes.into_iter().map(|a| a.0)) } - let should_gen_docs = args.generate_docs.is_present(); + // Insert type substitutions: + for sub in args.substitute_type.into_iter() { + codegen.set_type_substitute(sub.path, sub.with); + } + + // Do we want to fetch unstable metadata? This only works if fetching from a URL. let unstable_metadata = args.unstable_metadata.is_present(); - let runtime_api_generator = GenerateRuntimeApi::new(item_mod, crate_path) - .derives_registry(derives_registry) - .type_substitutes(type_substitutes) - .generate_docs(should_gen_docs) - .runtime_types_only(args.runtime_types_only); - match (args.runtime_metadata_path, args.runtime_metadata_url) { (Some(rest_of_path), None) => { if unstable_metadata { @@ -152,20 +155,31 @@ pub fn subxt(args: TokenStream, input: TokenStream) -> TokenStream { let root = std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()); let root_path = std::path::Path::new(&root); let path = root_path.join(rest_of_path); + let generated_code = fetch_metadata_from_file_blocking(&path) + .map_err(CodegenError::from) + .and_then(|b| subxt_codegen::Metadata::decode(&mut &*b).map_err(Into::into)) + .and_then(|m| codegen.generate(m).map_err(Into::into)) + .unwrap_or_else(|e| e.into_compile_error()); - runtime_api_generator - .generate_from_path(path) - .map_or_else(|err| err.into_compile_error().into(), Into::into) + generated_code.into() } (None, Some(url_string)) => { let url = Url::parse(&url_string).unwrap_or_else(|_| { abort_call_site!("Cannot download metadata; invalid url: {}", url_string) }); - runtime_api_generator - .unstable_metadata(unstable_metadata) - .generate_from_url(url) - .map_or_else(|err| err.into_compile_error().into(), Into::into) + let version = match unstable_metadata { + true => MetadataVersion::Unstable, + false => MetadataVersion::Latest, + }; + + let generated_code = fetch_metadata_from_url_blocking(url, version) + .map_err(CodegenError::from) + .and_then(|b| subxt_codegen::Metadata::decode(&mut &*b).map_err(Into::into)) + .and_then(|m| codegen.generate(m).map_err(Into::into)) + .unwrap_or_else(|e| e.into_compile_error()); + + generated_code.into() } (None, None) => { abort_call_site!( diff --git a/subxt/examples/blocks_subscribing.rs b/subxt/examples/blocks_subscribing.rs index 4f06221484..54ab2818e6 100644 --- a/subxt/examples/blocks_subscribing.rs +++ b/subxt/examples/blocks_subscribing.rs @@ -48,6 +48,16 @@ async fn main() -> Result<(), Box> { println!(" {pallet_name}_{event_name}"); println!(" {}", event_values); } + + println!(" Signed Extensions:"); + if let Some(signed_extensions) = ext.signed_extensions() { + for signed_extension in signed_extensions.iter() { + let signed_extension = signed_extension?; + let name = signed_extension.name(); + let value = signed_extension.value()?.to_string(); + println!(" {name}: {value}"); + } + } } } diff --git a/subxt/src/blocks/extrinsic_types.rs b/subxt/src/blocks/extrinsic_types.rs index 2e02dca2b2..8cb9a9c35c 100644 --- a/subxt/src/blocks/extrinsic_types.rs +++ b/subxt/src/blocks/extrinsic_types.rs @@ -349,11 +349,7 @@ where .map(|e| &self.bytes[e.address_start_idx..e.address_end_idx]) } - /// Return only the bytes of the signature for this signed extrinsic. - /// - /// # Note - /// - /// Returns `None` if the extrinsic is not signed. + /// Returns Some(signature_bytes) if the extrinsic was signed otherwise None is returned. pub fn signature_bytes(&self) -> Option<&[u8]> { self.signed_details .as_ref() @@ -696,6 +692,8 @@ impl<'a, T: Config> ExtrinsicSignedExtensions<'a, T> { } /// The nonce of the account that submitted the extrinsic, extracted from the CheckNonce signed extension. + /// + /// Returns `None` if `nonce` was not found or decoding failed. pub fn nonce(&self) -> Option { let nonce = self .iter() @@ -712,7 +710,7 @@ impl<'a, T: Config> ExtrinsicSignedExtension<'a, T> { } /// The name of the signed extension. - pub fn name(&self) -> &str { + pub fn name(&self) -> &'a str { self.identifier } diff --git a/subxt/src/blocks/mod.rs b/subxt/src/blocks/mod.rs index fd06594e60..7cf2501b9d 100644 --- a/subxt/src/blocks/mod.rs +++ b/subxt/src/blocks/mod.rs @@ -13,7 +13,10 @@ pub use crate::backend::BlockRef; pub use block_types::Block; pub use blocks_client::BlocksClient; -pub use extrinsic_types::{ExtrinsicDetails, ExtrinsicEvents, Extrinsics, StaticExtrinsic}; +pub use extrinsic_types::{ + ExtrinsicDetails, ExtrinsicEvents, ExtrinsicSignedExtension, ExtrinsicSignedExtensions, + Extrinsics, StaticExtrinsic, +}; // We get account nonce info in tx_client, too, so re-use the logic: pub(crate) use block_types::get_account_nonce; diff --git a/subxt/src/lib.rs b/subxt/src/lib.rs index ae60494f8d..e2a31f5b4e 100644 --- a/subxt/src/lib.rs +++ b/subxt/src/lib.rs @@ -309,7 +309,7 @@ pub mod ext { /// the metadata first. This is **not recommended** in production code, since the unstable metadata a node is providing is likely /// to be incompatible with Subxt. /// -/// ```rust,no_run +/// ```rust,ignore /// #[subxt::subxt( /// runtime_metadata_url = "wss://rpc.polkadot.io:443", /// unstable_metadata diff --git a/testing/integration-tests/src/full_client/blocks/mod.rs b/testing/integration-tests/src/full_client/blocks/mod.rs index 61fb1f0f2f..f65678160d 100644 --- a/testing/integration-tests/src/full_client/blocks/mod.rs +++ b/testing/integration-tests/src/full_client/blocks/mod.rs @@ -185,7 +185,7 @@ async fn fetch_block_and_decode_extrinsic_details() { .submit_and_watch() .await .unwrap() - .wait_for_in_block() + .wait_for_finalized() .await .unwrap(); @@ -306,7 +306,6 @@ async fn decode_signed_extensions_from_blocks() { assert_eq!(nonce2, nonce2_static); assert_eq!(tip2, 5678); assert_eq!(tip2, tip2_static); - assert_eq!(extensions1.iter().count(), expected_signed_extensions.len()); for (e, expected_name) in extensions1.iter().zip(expected_signed_extensions.iter()) { assert_eq!(e.unwrap().name(), *expected_name); diff --git a/testing/integration-tests/src/full_client/codegen/codegen_tests.rs b/testing/integration-tests/src/full_client/codegen/codegen_tests.rs index f3a00ea654..5722270e24 100644 --- a/testing/integration-tests/src/full_client/codegen/codegen_tests.rs +++ b/testing/integration-tests/src/full_client/codegen/codegen_tests.rs @@ -7,7 +7,7 @@ use frame_metadata::{ RuntimeMetadataPrefixed, }; use scale_info::{meta_type, IntoPortable, PortableRegistry, Registry, TypeInfo}; -use subxt_codegen::{CratePath, DerivesRegistry, RuntimeGenerator, TypeSubstitutes}; +use subxt_codegen::CodegenBuilder; use syn::__private::quote; fn generate_runtime_interface_from_metadata(metadata: RuntimeMetadataPrefixed) -> String { @@ -15,15 +15,10 @@ fn generate_runtime_interface_from_metadata(metadata: RuntimeMetadataPrefixed) - let metadata = metadata .try_into() .expect("frame_metadata should be convertible into Metadata"); - let generator = RuntimeGenerator::new(metadata); - let item_mod = syn::parse_quote!( - pub mod api {} - ); - let crate_path = CratePath::default(); - let derives = DerivesRegistry::with_default_derives(&crate_path); - let type_substitutes = TypeSubstitutes::with_default_substitutes(&crate_path); - generator - .generate_runtime(item_mod, derives, type_substitutes, crate_path, false) + + CodegenBuilder::new() + .no_docs() + .generate(metadata) .expect("API generation must be valid") .to_string() } diff --git a/testing/integration-tests/src/full_client/codegen/documentation.rs b/testing/integration-tests/src/full_client/codegen/documentation.rs index 9eb79c0ecc..8eead47760 100644 --- a/testing/integration-tests/src/full_client/codegen/documentation.rs +++ b/testing/integration-tests/src/full_client/codegen/documentation.rs @@ -4,7 +4,7 @@ use codec::Decode; use regex::Regex; -use subxt_codegen::{CratePath, DerivesRegistry, RuntimeGenerator, TypeSubstitutes}; +use subxt_codegen::{ syn, CodegenBuilder }; use subxt_metadata::Metadata; fn load_test_metadata() -> Metadata { @@ -48,25 +48,18 @@ fn metadata_docs() -> Vec { docs } -fn generate_runtime_interface(crate_path: CratePath, should_gen_docs: bool) -> String { +fn generate_runtime_interface(should_gen_docs: bool) -> String { // Load the runtime metadata downloaded from a node via `test-runtime`. let metadata = load_test_metadata(); - // Generate a runtime interface from the provided metadata. - let generator = RuntimeGenerator::new(metadata); - let item_mod = syn::parse_quote!( - pub mod api {} - ); - let derives = DerivesRegistry::with_default_derives(&crate_path); - let type_substitutes = TypeSubstitutes::with_default_substitutes(&crate_path); - generator - .generate_runtime( - item_mod, - derives, - type_substitutes, - crate_path, - should_gen_docs, - ) + let mut codegen = CodegenBuilder::new(); + + if !should_gen_docs { + codegen.no_docs(); + } + + codegen + .generate(metadata) .expect("API generation must be valid") .to_string() } @@ -74,7 +67,7 @@ fn generate_runtime_interface(crate_path: CratePath, should_gen_docs: bool) -> S fn interface_docs(should_gen_docs: bool) -> Vec { // Generate the runtime interface from the node's metadata. // Note: the API is generated on a single line. - let runtime_api = generate_runtime_interface(CratePath::default(), should_gen_docs); + let runtime_api = generate_runtime_interface(should_gen_docs); // Documentation lines have the following format: // # [ doc = "Upward message is invalid XCM."] @@ -145,18 +138,10 @@ fn check_root_attrs_preserved() { pub mod api {} ); - // Generate a runtime interface from the provided metadata. - let generator = RuntimeGenerator::new(metadata); - let derives = DerivesRegistry::with_default_derives(&CratePath::default()); - let type_substitutes = TypeSubstitutes::with_default_substitutes(&CratePath::default()); - let generated_code = generator - .generate_runtime( - item_mod, - derives, - type_substitutes, - CratePath::default(), - true, - ) + let mut codegen = CodegenBuilder::new(); + codegen.set_target_module(item_mod); + let generated_code = codegen + .generate(metadata) .expect("API generation must be valid") .to_string();