subxt_core/config/
default_extrinsic_params.rs

1// Copyright 2019-2024 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
5use crate::config::transaction_extensions::CheckMortalityParams;
6
7use super::{Config, HashFor};
8use super::{ExtrinsicParams, transaction_extensions};
9
10/// The default [`super::ExtrinsicParams`] implementation understands common signed extensions
11/// and how to apply them to a given chain.
12pub type DefaultExtrinsicParams<T> = transaction_extensions::AnyOf<
13    T,
14    (
15        transaction_extensions::VerifySignature<T>,
16        transaction_extensions::CheckSpecVersion,
17        transaction_extensions::CheckTxVersion,
18        transaction_extensions::CheckNonce,
19        transaction_extensions::CheckGenesis<T>,
20        transaction_extensions::CheckMortality<T>,
21        transaction_extensions::ChargeAssetTxPayment<T>,
22        transaction_extensions::ChargeTransactionPayment,
23        transaction_extensions::CheckMetadataHash,
24    ),
25>;
26
27/// A builder that outputs the set of [`super::ExtrinsicParams::Params`] required for
28/// [`DefaultExtrinsicParams`]. This may expose methods that aren't applicable to the current
29/// chain; such values will simply be ignored if so.
30pub struct DefaultExtrinsicParamsBuilder<T: Config> {
31    /// `None` means the tx will be immortal, else it's mortality is described.
32    mortality: transaction_extensions::CheckMortalityParams<T>,
33    /// `None` means the nonce will be automatically set.
34    nonce: Option<u64>,
35    /// `None` means we'll use the native token.
36    tip_of_asset_id: Option<T::AssetId>,
37    tip: u128,
38    tip_of: u128,
39}
40
41impl<T: Config> Default for DefaultExtrinsicParamsBuilder<T> {
42    fn default() -> Self {
43        Self {
44            mortality: CheckMortalityParams::default(),
45            tip: 0,
46            tip_of: 0,
47            tip_of_asset_id: None,
48            nonce: None,
49        }
50    }
51}
52
53impl<T: Config> DefaultExtrinsicParamsBuilder<T> {
54    /// Configure new extrinsic params. We default to providing no tip
55    /// and using an immortal transaction unless otherwise configured
56    pub fn new() -> Self {
57        Default::default()
58    }
59
60    /// Make the transaction immortal, meaning it will never expire. This means that it could, in
61    /// theory, be pending for a long time and only be included many blocks into the future.
62    pub fn immortal(mut self) -> Self {
63        self.mortality = transaction_extensions::CheckMortalityParams::immortal();
64        self
65    }
66
67    /// Make the transaction mortal, given a number of blocks it will be mortal for from
68    /// the current block at the time of submission.
69    ///
70    /// # Warning
71    ///
72    /// This will ultimately return an error if used for creating extrinsic offline, because we need
73    /// additional information in order to set the mortality properly.
74    ///
75    /// When creating offline transactions, you must use [`Self::mortal_from_unchecked`] instead to set
76    /// the mortality. This provides all of the necessary information which we must otherwise be online
77    /// in order to obtain.
78    pub fn mortal(mut self, for_n_blocks: u64) -> Self {
79        self.mortality = transaction_extensions::CheckMortalityParams::mortal(for_n_blocks);
80        self
81    }
82
83    /// Configure a transaction that will be mortal for the number of blocks given, and from the
84    /// block details provided. Prefer to use [`Self::mortal()`] where possible, which prevents
85    /// the block number and hash from being misaligned.
86    pub fn mortal_from_unchecked(
87        mut self,
88        for_n_blocks: u64,
89        from_block_n: u64,
90        from_block_hash: HashFor<T>,
91    ) -> Self {
92        self.mortality = transaction_extensions::CheckMortalityParams::mortal_from_unchecked(
93            for_n_blocks,
94            from_block_n,
95            from_block_hash,
96        );
97        self
98    }
99
100    /// Provide a specific nonce for the submitter of the extrinsic
101    pub fn nonce(mut self, nonce: u64) -> Self {
102        self.nonce = Some(nonce);
103        self
104    }
105
106    /// Provide a tip to the block author in the chain's native token.
107    pub fn tip(mut self, tip: u128) -> Self {
108        self.tip = tip;
109        self.tip_of = tip;
110        self.tip_of_asset_id = None;
111        self
112    }
113
114    /// Provide a tip to the block author using the token denominated by the `asset_id` provided. This
115    /// is not applicable on chains which don't use the `ChargeAssetTxPayment` signed extension; in this
116    /// case, no tip will be given.
117    pub fn tip_of(mut self, tip: u128, asset_id: T::AssetId) -> Self {
118        self.tip = 0;
119        self.tip_of = tip;
120        self.tip_of_asset_id = Some(asset_id);
121        self
122    }
123
124    /// Build the extrinsic parameters.
125    pub fn build(self) -> <DefaultExtrinsicParams<T> as ExtrinsicParams<T>>::Params {
126        let check_mortality_params = self.mortality;
127
128        let charge_asset_tx_params = if let Some(asset_id) = self.tip_of_asset_id {
129            transaction_extensions::ChargeAssetTxPaymentParams::tip_of(self.tip, asset_id)
130        } else {
131            transaction_extensions::ChargeAssetTxPaymentParams::tip(self.tip)
132        };
133
134        let charge_transaction_params =
135            transaction_extensions::ChargeTransactionPaymentParams::tip(self.tip);
136
137        let check_nonce_params = if let Some(nonce) = self.nonce {
138            transaction_extensions::CheckNonceParams::with_nonce(nonce)
139        } else {
140            transaction_extensions::CheckNonceParams::from_chain()
141        };
142
143        (
144            (),
145            (),
146            (),
147            check_nonce_params,
148            (),
149            check_mortality_params,
150            charge_asset_tx_params,
151            charge_transaction_params,
152            (),
153        )
154    }
155}
156
157#[cfg(test)]
158mod test {
159    use super::*;
160
161    fn assert_default<T: Default>(_t: T) {}
162
163    #[test]
164    fn params_are_default() {
165        let params = DefaultExtrinsicParamsBuilder::<crate::config::PolkadotConfig>::new().build();
166        assert_default(params)
167    }
168}