feat: add configurable dispatch_error_module for rebranded chains

Add a new `dispatch_error_module` option to the subxt macro and CodegenBuilder
that allows chains with rebranded runtime modules to specify their own path for
the DispatchError type.

By default, subxt generates:
  pub type DispatchError = runtime_types::sp_runtime::DispatchError;

Chains like Kurdistan SDK (Pezkuwi) that rebrand sp_runtime to pezsp_runtime
can now specify:
  dispatch_error_module = "pezsp_runtime"

This generates:
  pub type DispatchError = runtime_types::pezsp_runtime::DispatchError;

Changes:
- codegen/src/lib.rs: Add dispatch_error_module field to CodegenBuilder
- codegen/src/api/mod.rs: Pass dispatch_error_module to generate_runtime
- codegen/src/api/calls.rs: Use configurable module path for DispatchError
- macro/src/lib.rs: Add dispatch_error_module attribute parsing
This commit is contained in:
2025-12-17 10:05:15 +03:00
parent a2080bf1f7
commit 429bb60e8c
4 changed files with 40 additions and 3 deletions
+4 -1
View File
@@ -18,10 +18,12 @@ use subxt_metadata::PalletMetadata;
/// - `type_gen` - [`scale_typegen::TypeGenerator`] that contains settings and all types from the runtime metadata.
/// - `pallet` - Pallet metadata from which the calls are generated.
/// - `crate_path` - The crate path under which the `subxt-core` crate is located, e.g. `::subxt::ext::subxt_core` when using subxt as a dependency.
/// - `dispatch_error_module` - The module path for DispatchError (e.g., "sp_runtime" or "pezsp_runtime").
pub fn generate_calls(
type_gen: &TypeGenerator,
pallet: &PalletMetadata,
crate_path: &syn::Path,
dispatch_error_module: &str,
) -> Result<TokenStream2, CodegenError> {
// Early return if the pallet has no calls.
let Some(call_ty) = pallet.call_ty_id() else {
@@ -115,6 +117,7 @@ pub fn generate_calls(
let docs = type_gen.docs_from_scale_info(&call_ty.docs);
let types_mod_ident = type_gen.types_mod_ident();
let dispatch_error_mod_ident = format_ident!("{}", dispatch_error_module);
Ok(quote! {
#docs
@@ -123,7 +126,7 @@ pub fn generate_calls(
use super::root_mod;
use super::#types_mod_ident;
type DispatchError = #types_mod_ident::sp_runtime::DispatchError;
type DispatchError = #types_mod_ident::#dispatch_error_mod_ident::DispatchError;
pub mod types {
use super::#types_mod_ident;
+4 -2
View File
@@ -118,6 +118,7 @@ impl RuntimeGenerator {
type_substitutes: scale_typegen::TypeSubstitutes,
crate_path: syn::Path,
should_gen_docs: bool,
dispatch_error_module: &str,
) -> Result<TokenStream2, CodegenError> {
let item_mod_attrs = item_mod.attrs.clone();
let item_mod_ir = ir::ItemMod::try_from(item_mod)?;
@@ -130,6 +131,7 @@ impl RuntimeGenerator {
.generate_types_mod()?
.to_token_stream(type_gen.settings());
let types_mod_ident = type_gen.types_mod_ident();
let dispatch_error_mod_ident = format_ident!("{}", dispatch_error_module);
let pallets_with_mod_names = self
.metadata
.pallets()
@@ -161,7 +163,7 @@ impl RuntimeGenerator {
let modules = pallets_with_mod_names
.iter()
.map(|(pallet, mod_name)| {
let calls = calls::generate_calls(&type_gen, pallet, &crate_path)?;
let calls = calls::generate_calls(&type_gen, pallet, &crate_path, dispatch_error_module)?;
let event = events::generate_events(&type_gen, pallet, &crate_path)?;
@@ -268,7 +270,7 @@ impl RuntimeGenerator {
pub static RUNTIME_APIS: [&str; #runtime_api_names_len] = [ #(#runtime_api_names,)* ];
/// The error type that is returned when there is a runtime issue.
pub type DispatchError = #types_mod_ident::sp_runtime::DispatchError;
pub type DispatchError = #types_mod_ident::#dispatch_error_mod_ident::DispatchError;
/// The outer event enum.
pub type Event = #event_path;
+22
View File
@@ -66,6 +66,9 @@ pub struct CodegenBuilder {
attributes_for_type: HashMap<syn::TypePath, Vec<syn::Attribute>>,
derives_for_type_recursive: HashMap<syn::TypePath, Vec<syn::Path>>,
attributes_for_type_recursive: HashMap<syn::TypePath, Vec<syn::Attribute>>,
/// The module path for DispatchError (default: "sp_runtime").
/// This allows chains with rebranded runtime modules to specify their own path.
dispatch_error_module: String,
}
impl Default for CodegenBuilder {
@@ -86,6 +89,7 @@ impl Default for CodegenBuilder {
attributes_for_type: HashMap::new(),
derives_for_type_recursive: HashMap::new(),
attributes_for_type_recursive: HashMap::new(),
dispatch_error_module: "sp_runtime".to_string(),
}
}
}
@@ -130,6 +134,23 @@ impl CodegenBuilder {
self.runtime_types_only = true;
}
/// Set the module path for DispatchError type.
///
/// By default, this is "sp_runtime", which generates code like:
/// `pub type DispatchError = runtime_types::sp_runtime::DispatchError;`
///
/// Chains that have rebranded their runtime modules can use this to specify
/// a different module path. For example, setting this to "pezsp_runtime" would
/// generate: `pub type DispatchError = runtime_types::pezsp_runtime::DispatchError;`
pub fn set_dispatch_error_module(&mut self, module: impl Into<String>) {
self.dispatch_error_module = module.into();
}
/// Get the configured dispatch error module path.
pub fn dispatch_error_module(&self) -> &str {
&self.dispatch_error_module
}
/// 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.
///
@@ -292,6 +313,7 @@ impl CodegenBuilder {
type_substitutes,
crate_path,
should_gen_docs,
&self.dispatch_error_module,
)
}
}
+10
View File
@@ -56,6 +56,11 @@ struct RuntimeMetadataArgs {
no_default_substitutions: bool,
#[darling(default)]
unstable_metadata: darling::util::Flag,
/// The module path for DispatchError (default: "sp_runtime").
/// Chains with rebranded runtime modules can use this to specify their path,
/// e.g., "pezsp_runtime" for Kurdistan SDK.
#[darling(default)]
dispatch_error_module: Option<String>,
#[cfg(feature = "runtime-wasm-path")]
#[darling(default)]
runtime_path: Option<String>,
@@ -170,6 +175,11 @@ fn subxt_inner(args: TokenStream, item_mod: syn::ItemMod) -> Result<TokenStream,
codegen.set_type_substitute(sub.path, sub.with);
}
// Set the dispatch error module path if provided:
if let Some(dispatch_error_module) = args.dispatch_error_module {
codegen.set_dispatch_error_module(dispatch_error_module);
}
let code = codegen
.generate(metadata)
.map_err(|e| e.into_compile_error())?;