Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying the subxt crate path for generated code #664

Merged
merged 12 commits into from
Sep 27, 2022
22 changes: 17 additions & 5 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ enum Command {
/// Additional derives
#[structopt(long = "derive")]
derives: Vec<String>,
/// The `subxt` crate access path in the generated code.
/// Defaults to `::subxt`.
#[structopt(short = "crate")]
crate_path: Option<String>,
},
/// Verify metadata compatibility between substrate nodes.
Compatibility {
Expand Down Expand Up @@ -136,7 +140,12 @@ async fn main() -> color_eyre::Result<()> {
}
}
}
Command::Codegen { url, file, derives } => {
Command::Codegen {
url,
file,
derives,
crate_path,
} => {
if let Some(file) = file.as_ref() {
if url.is_some() {
eyre::bail!("specify one of `--url` or `--file` but not both")
Expand All @@ -145,7 +154,7 @@ async fn main() -> color_eyre::Result<()> {
let mut file = fs::File::open(file)?;
let mut bytes = Vec::new();
file.read_to_end(&mut bytes)?;
codegen(&mut &bytes[..], derives)?;
codegen(&mut &bytes[..], derives, crate_path)?;
return Ok(())
}

Expand All @@ -155,7 +164,7 @@ async fn main() -> color_eyre::Result<()> {
.expect("default url is valid")
});
let (_, bytes) = fetch_metadata(&url).await?;
codegen(&mut &bytes[..], derives)?;
codegen(&mut &bytes[..], derives, crate_path)?;
Ok(())
}
Command::Compatibility { nodes, pallet } => {
Expand Down Expand Up @@ -296,6 +305,7 @@ async fn fetch_metadata(url: &Uri) -> color_eyre::Result<(String, Vec<u8>)> {
fn codegen<I: Input>(
encoded: &mut I,
raw_derives: Vec<String>,
crate_path: Option<String>,
) -> color_eyre::Result<()> {
let metadata = <RuntimeMetadataPrefixed as Decode>::decode(encoded)?;
let generator = subxt_codegen::RuntimeGenerator::new(metadata);
Expand All @@ -307,10 +317,12 @@ fn codegen<I: Input>(
.iter()
.map(|raw| syn::parse_str(raw))
.collect::<Result<Vec<_>, _>>()?;
let mut derives = DerivesRegistry::default();

let crate_path = crate_path.map(Into::into).unwrap_or_default();
let mut derives = DerivesRegistry::new(&crate_path);
derives.extend_for_all(p.into_iter());

let runtime_api = generator.generate_runtime(item_mod, derives);
let runtime_api = generator.generate_runtime(item_mod, derives, crate_path);
println!("{}", runtime_api);
Ok(())
}
16 changes: 11 additions & 5 deletions codegen/src/api/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.

use crate::types::{
CompositeDefFields,
TypeGenerator,
use crate::{
types::{
CompositeDefFields,
TypeGenerator,
},
CratePath,
};
use frame_metadata::{
v14::RuntimeMetadataV14,
Expand Down Expand Up @@ -36,6 +39,7 @@ pub fn generate_calls(
type_gen: &TypeGenerator,
pallet: &PalletMetadata<PortableForm>,
types_mod_ident: &syn::Ident,
crate_path: &CratePath,
) -> TokenStream2 {
// Early return if the pallet has no calls.
let call = if let Some(ref calls) = pallet.calls {
Expand All @@ -49,6 +53,7 @@ pub fn generate_calls(
call.ty.id(),
|name| name.to_upper_camel_case().into(),
"Call",
crate_path,
);
let (call_structs, call_fns): (Vec<_>, Vec<_>) = struct_defs
.iter_mut()
Expand Down Expand Up @@ -98,13 +103,14 @@ pub fn generate_calls(
let call_struct = quote! {
#struct_def
};

let client_fn = quote! {
#docs
pub fn #fn_name(
&self,
#( #call_fn_args, )*
) -> ::subxt::tx::StaticTxPayload<#struct_name> {
::subxt::tx::StaticTxPayload::new(
) -> #crate_path::tx::StaticTxPayload<#struct_name> {
#crate_path::tx::StaticTxPayload::new(
#pallet_name,
#call_name,
#struct_name { #( #call_args, )* },
Expand Down
10 changes: 7 additions & 3 deletions codegen/src/api/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// 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::TypeGenerator,
CratePath,
};
use frame_metadata::{
v14::RuntimeMetadataV14,
PalletMetadata,
Expand Down Expand Up @@ -44,6 +47,7 @@ pub fn generate_constants(
type_gen: &TypeGenerator,
pallet: &PalletMetadata<PortableForm>,
types_mod_ident: &syn::Ident,
crate_path: &CratePath,
) -> TokenStream2 {
// Early return if the pallet has no constants.
if pallet.constants.is_empty() {
Expand All @@ -63,8 +67,8 @@ pub fn generate_constants(

quote! {
#( #[doc = #docs ] )*
pub fn #fn_name(&self) -> ::subxt::constants::StaticConstantAddress<::subxt::metadata::DecodeStaticType<#return_ty>> {
::subxt::constants::StaticConstantAddress::new(
pub fn #fn_name(&self) -> #crate_path::constants::StaticConstantAddress<#crate_path::metadata::DecodeStaticType<#return_ty>> {
#crate_path::constants::StaticConstantAddress::new(
#pallet_name,
#constant_name,
[#(#constant_hash,)*]
Expand Down
9 changes: 7 additions & 2 deletions codegen/src/api/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// 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::TypeGenerator,
CratePath,
};
use frame_metadata::PalletMetadata;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
Expand Down Expand Up @@ -41,6 +44,7 @@ pub fn generate_events(
type_gen: &TypeGenerator,
pallet: &PalletMetadata<PortableForm>,
types_mod_ident: &syn::Ident,
crate_path: &CratePath,
) -> TokenStream2 {
// Early return if the pallet has no events.
let event = if let Some(ref event) = pallet.event {
Expand All @@ -54,6 +58,7 @@ pub fn generate_events(
event.ty.id(),
|name| name.into(),
"Event",
crate_path,
);
let event_structs = struct_defs.iter().map(|(variant_name, struct_def)| {
let pallet_name = &pallet.name;
Expand All @@ -63,7 +68,7 @@ pub fn generate_events(
quote! {
#struct_def

impl ::subxt::events::StaticEvent for #event_struct {
impl #crate_path::events::StaticEvent for #event_struct {
const PALLET: &'static str = #pallet_name;
const EVENT: &'static str = #event_name;
}
Expand Down
40 changes: 27 additions & 13 deletions codegen/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::{
CompositeDefFields,
TypeGenerator,
},
CratePath,
};
use codec::Decode;
use frame_metadata::{
Expand Down Expand Up @@ -55,6 +56,7 @@ pub fn generate_runtime_api<P>(
item_mod: syn::ItemMod,
path: P,
derives: DerivesRegistry,
crate_path: CratePath,
) -> TokenStream2
where
P: AsRef<path::Path>,
Expand All @@ -71,7 +73,7 @@ where
.unwrap_or_else(|e| abort_call_site!("Failed to decode metadata: {}", e));

let generator = RuntimeGenerator::new(metadata);
generator.generate_runtime(item_mod, derives)
generator.generate_runtime(item_mod, derives, crate_path)
}

/// Create the API for interacting with a Substrate runtime.
Expand Down Expand Up @@ -101,6 +103,7 @@ impl RuntimeGenerator {
&self,
item_mod: syn::ItemMod,
derives: DerivesRegistry,
crate_path: CratePath,
) -> TokenStream2 {
let item_mod_ir = ir::ItemMod::from(item_mod);
let default_derives = derives.default_derives();
Expand All @@ -109,41 +112,41 @@ impl RuntimeGenerator {
let mut type_substitutes = [
(
"bitvec::order::Lsb0",
parse_quote!(::subxt::ext::bitvec::order::Lsb0),
parse_quote!(#crate_path::ext::bitvec::order::Lsb0),
),
(
"bitvec::order::Msb0",
parse_quote!(::subxt::ext::bitvec::order::Msb0),
parse_quote!(#crate_path::ext::bitvec::order::Msb0),
),
(
"sp_core::crypto::AccountId32",
parse_quote!(::subxt::ext::sp_core::crypto::AccountId32),
parse_quote!(#crate_path::ext::sp_core::crypto::AccountId32),
),
(
"primitive_types::H160",
parse_quote!(::subxt::ext::sp_core::H160),
parse_quote!(#crate_path::ext::sp_core::H160),
),
(
"primitive_types::H256",
parse_quote!(::subxt::ext::sp_core::H256),
parse_quote!(#crate_path::ext::sp_core::H256),
),
(
"primitive_types::H512",
parse_quote!(::subxt::ext::sp_core::H512),
parse_quote!(#crate_path::ext::sp_core::H512),
),
(
"sp_runtime::multiaddress::MultiAddress",
parse_quote!(::subxt::ext::sp_runtime::MultiAddress),
parse_quote!(#crate_path::ext::sp_runtime::MultiAddress),
),
(
"frame_support::traits::misc::WrapperKeepOpaque",
parse_quote!(::subxt::utils::WrapperKeepOpaque),
parse_quote!(#crate_path::utils::WrapperKeepOpaque),
),
// BTreeMap and BTreeSet impose an `Ord` constraint on their key types. This
// can cause an issue with generated code that doesn't impl `Ord` by default.
// Decoding them to Vec by default (KeyedVec is just an alias for Vec with
// suitable type params) avoids these issues.
("BTreeMap", parse_quote!(::subxt::utils::KeyedVec)),
("BTreeMap", parse_quote!(#crate_path::utils::KeyedVec)),
("BTreeSet", parse_quote!(::std::vec::Vec)),
]
.iter()
Expand All @@ -161,6 +164,7 @@ impl RuntimeGenerator {
"runtime_types",
type_substitutes,
derives.clone(),
crate_path.clone(),
);
let types_mod = type_gen.generate_types_mod();
let types_mod_ident = types_mod.ident();
Expand Down Expand Up @@ -190,23 +194,31 @@ impl RuntimeGenerator {
let metadata_hash = get_metadata_per_pallet_hash(&self.metadata, &pallet_names);

let modules = pallets_with_mod_names.iter().map(|(pallet, mod_name)| {
let calls =
calls::generate_calls(&self.metadata, &type_gen, pallet, types_mod_ident);
let calls = calls::generate_calls(
&self.metadata,
&type_gen,
pallet,
types_mod_ident,
&crate_path,
);

let event = events::generate_events(&type_gen, pallet, types_mod_ident);
let event =
events::generate_events(&type_gen, pallet, types_mod_ident, &crate_path);

let storage_mod = storage::generate_storage(
&self.metadata,
&type_gen,
pallet,
types_mod_ident,
&crate_path,
);

let constants_mod = constants::generate_constants(
&self.metadata,
&type_gen,
pallet,
types_mod_ident,
&crate_path,
);

quote! {
Expand Down Expand Up @@ -338,6 +350,7 @@ pub fn generate_structs_from_variants<'a, F>(
type_id: u32,
variant_to_struct_name: F,
error_message_type_name: &str,
crate_path: &CratePath,
) -> Vec<(String, CompositeDef)>
where
F: Fn(&str) -> std::borrow::Cow<str>,
Expand All @@ -363,6 +376,7 @@ where
Some(parse_quote!(pub)),
type_gen,
var.docs(),
crate_path,
);
(var.name().to_string(), struct_def)
})
Expand Down
Loading