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}