Skip to main content

subxt/
config.rs

1// Copyright 2019-2026 Parity Technologies (UK) Ltd.
2// This file is dual-licensed as Apache-2.0 or GPL-3.0.
3// see LICENSE for license details.
4
5//! This module provides a [`Config`] type, which provides a way to configure Subxt to work with a
6//! specific chain.
7//!
8//! - A generic [`SubstrateConfig`] implementation is provided that will work against modern
9//!   blocks with most Substrate based chains automatically, and can be configured to work with
10//!   historic blocks.
11//! - A [`PolkadotConfig`] implementation is provided which is specialized towards the Polkadot
12//!   Relay Chain, and comes pre-configured to work against historic Polkadot RC blocks.
13//!
14//! # Creating custom configuration
15//!
16//! Some chains require this configuration to be customized. In many cases, you can perform most
17//! interactions on these chains using the default [`SubstrateConfig`], but may need small
18//! customizations to enable all interactions to work properly.
19//!
20//! ## Asset Hub
21//!
22//! One chain that needs custom configuration to completely work is Asset Hub. For the most part
23//! you can just use [`SubstrateConfig`], but if you want to add a tip to a transaction in anything
24//! other than DOT, you'll need to change the [`Config::AssetId`] property to allow for this.
25//! This involves creating a new [`Config`] instance for Asset Hub, which looks like this:
26//!
27//! ```rust,no_run
28#![doc = include_str ! ("../examples/config_assethub.rs")]
29//! ```
30//!
31//! ## Ethereum based chains
32//!
33//! If you're interacting with an Ethereum based chain, you'll need to configure Subxt to work with
34//! 20 byte account IDs instead of the default 32 byte ones, and a corresponding `Signature` type.
35//! This would look something like this:
36//!
37//! ```rust,no_run
38#![doc = include_str ! ("../examples/config_eth.rs")]
39//! ```
40//!
41//! # Other chains
42//!
43//! If you find that [`SubstrateConfig`] doesn't work, and neither of the above is applicable, then
44//! the next step is to look at how the runtime for the chain you'd like to interact with is
45//! configured. Please open an issue in the Subxt repository and we can help to narrow down what
46//! the problem might be.
47
48mod default_transaction_extensions;
49mod transaction_extension_traits;
50
51pub mod polkadot;
52pub mod substrate;
53pub mod transaction_extensions;
54
55use crate::metadata::{ArcMetadata, Metadata};
56use codec::{Decode, Encode};
57use core::fmt::Debug;
58use scale_decode::DecodeAsType;
59use scale_encode::EncodeAsType;
60use scale_info_legacy::TypeRegistrySet;
61use serde::{Serialize, de::DeserializeOwned};
62use std::{fmt::Display, marker::PhantomData};
63use subxt_rpcs::RpcConfig;
64
65pub use default_transaction_extensions::{
66    DefaultExtrinsicParams, DefaultExtrinsicParamsBuilder, DefaultTransactionExtensions,
67    KnownDefaultExtrinsicParams, KnownDefaultTransactionExtensions,
68};
69pub use polkadot::{PolkadotConfig, PolkadotExtrinsicParams, PolkadotExtrinsicParamsBuilder};
70pub use substrate::{SubstrateConfig, SubstrateExtrinsicParams, SubstrateExtrinsicParamsBuilder};
71pub use transaction_extension_traits::{ClientState, TransactionExtension, TransactionExtensions};
72
73/// Configuration for a given chain and the runtimes within. This consists of the
74/// type information needed to work at the head of the chain (namely submitting
75/// transactions), as well as functionality which we might wish to customize for a
76/// given chain.
77pub trait Config: Clone + Debug + Sized + Send + Sync + 'static {
78    /// The account ID type; required for constructing extrinsics.
79    type AccountId: Debug + Clone + Encode + EncodeAsType + DecodeAsType + Serialize + Send;
80
81    /// The address type; required for constructing extrinsics.
82    type Address: Debug + EncodeAsType + From<Self::AccountId>;
83
84    /// The signature type.
85    type Signature: Debug + Clone + EncodeAsType + DecodeAsType + Send;
86
87    /// The block header.
88    type Header: Header;
89
90    /// This type defines the extrinsic extra and additional parameters.
91    type TransactionExtensions: TransactionExtensions<Self>;
92
93    /// This is used to identify an asset in the `ChargeAssetTxPayment` signed extension.
94    type AssetId: AssetId;
95
96    /// The hashing system (algorithm) being used in the runtime (e.g. Blake2).
97    /// This is created on demand with the relevant metadata for a given block, and
98    /// can then be used to hash things at that block.
99    type Hasher: Hasher;
100
101    /// The starting hash for the chain we're connecting to. This is required for constructing transactions.
102    ///
103    /// If not provided by the config implementation, it will be obtained from the chain in the case of the
104    /// [`crate::client::OnlineClient`]. It must be provided to construct transactions via the
105    /// [`crate::client::OfflineClient`], else an error will be returned.
106    fn genesis_hash(&self) -> Option<HashFor<Self>> {
107        None
108    }
109
110    /// Return a tuple of the spec version and then transaction version for a given block number, if available.
111    ///
112    /// The [`crate::client::OnlineClient`] will look this up on chain if it's not available here,
113    /// but the [`crate::client::OfflineClient`] will error if this is not available for the required block number.
114    fn spec_and_transaction_version_for_block_number(
115        &self,
116        _block_number: u64,
117    ) -> Option<(u32, u32)> {
118        None
119    }
120
121    /// Return the metadata for a given spec version, if available.
122    ///
123    /// The [`crate::client::OnlineClient`] will look this up on chain if it's not available here, and then
124    /// call [`Config::set_metadata_for_spec_version`] to give the configuration the opportunity to cache it.
125    /// The [`crate::client::OfflineClient`] will error if this is not available for the required spec version.
126    fn metadata_for_spec_version(&self, _spec_version: u32) -> Option<ArcMetadata> {
127        None
128    }
129
130    /// Set some metadata for a given spec version. the [`crate::client::OnlineClient`] will call this if it has
131    /// to retrieve metadata from the chain, to give this the opportunity to cache it. The configuration can
132    /// do nothing if it prefers.
133    fn set_metadata_for_spec_version(&self, _spec_version: u32, _metadata: ArcMetadata) {}
134
135    /// Return legacy types (ie types to use with Runtimes that return pre-V14 metadata) for a given spec version.
136    /// If this returns `None`, [`subxt`](crate) will return an error if type definitions are needed to access some older
137    /// block.
138    ///
139    /// This doesn't need to live for long; it will be used to translate any older metadata returned from the node
140    /// into our [`Metadata`] type, which will then be used.
141    fn legacy_types_for_spec_version<'this>(
142        &'this self,
143        _spec_version: u32,
144    ) -> Option<TypeRegistrySet<'this>> {
145        None
146    }
147}
148
149/// `RpcConfigFor<Config>` can be used anywhere which requires an implementation of [`subxt_rpcs::RpcConfig`].
150/// This is only needed at the type level, and so there is no way to construct this.
151pub struct RpcConfigFor<T> {
152    marker: PhantomData<T>,
153}
154
155impl<T: Config> RpcConfig for RpcConfigFor<T> {
156    type Hash = HashFor<T>;
157    type Header = T::Header;
158    type AccountId = T::AccountId;
159}
160
161/// Given some [`Config`], this returns the type of hash used.
162pub type HashFor<T> = <<T as Config>::Hasher as Hasher>::Hash;
163
164/// given some [`Config`], this return the other params needed for its `ExtrinsicParams`.
165pub type ParamsFor<T> = <<T as Config>::TransactionExtensions as TransactionExtensions<T>>::Params;
166
167/// AssetId types must conform to this trait.
168pub trait AssetId: Debug + Clone + Encode + DecodeAsType + EncodeAsType + Send {}
169impl<T> AssetId for T where T: Debug + Clone + Encode + DecodeAsType + EncodeAsType + Send {}
170
171/// Block hash types must conform to this trait.
172pub trait Hash:
173    Debug
174    + Display
175    + Copy
176    + Send
177    + Sync
178    + Decode
179    + AsRef<[u8]>
180    + Serialize
181    + DeserializeOwned
182    + Encode
183    + PartialEq
184    + Eq
185    + core::hash::Hash
186{
187}
188impl<T> Hash for T where
189    T: Debug
190        + Display
191        + Copy
192        + Send
193        + Sync
194        + Decode
195        + AsRef<[u8]>
196        + Serialize
197        + DeserializeOwned
198        + Encode
199        + PartialEq
200        + Eq
201        + core::hash::Hash
202{
203}
204
205/// This represents the hasher used by a node to hash things like block headers
206/// and extrinsics.
207pub trait Hasher: Debug + Clone + Send + Sync + 'static {
208    /// The type of hash produced by this hasher.
209    type Hash: Hash;
210
211    /// Construct a new hasher.
212    fn new(metadata: &Metadata) -> Self;
213
214    /// Hash some bytes to the given output type.
215    fn hash(&self, s: &[u8]) -> Self::Hash;
216}
217
218/// This represents the block header type used by a node.
219pub trait Header: Sized + Encode + Decode + Debug + Sync + Send + DeserializeOwned + Clone {
220    /// Return the block number of this header.
221    fn number(&self) -> u64;
222}