fuels_programs/calls/traits/
transaction_tuner.rs

1use fuels_accounts::Account;
2use fuels_core::types::{
3    errors::{error, Result},
4    transaction::{ScriptTransaction, TxPolicies},
5    transaction_builders::{
6        BuildableTransaction, ScriptTransactionBuilder, TransactionBuilder, VariableOutputPolicy,
7    },
8};
9
10use crate::{
11    calls::{
12        utils::{build_tx_from_contract_calls, sealed, transaction_builder_from_contract_calls},
13        ContractCall, ScriptCall,
14    },
15    DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,
16};
17
18#[async_trait::async_trait]
19pub trait TransactionTuner: sealed::Sealed {
20    async fn transaction_builder<T: Account>(
21        &self,
22        tx_policies: TxPolicies,
23        variable_output_policy: VariableOutputPolicy,
24        account: &T,
25    ) -> Result<ScriptTransactionBuilder>;
26
27    async fn build_tx<T: Account>(
28        &self,
29        tx_policies: TxPolicies,
30        variable_output_policy: VariableOutputPolicy,
31        account: &T,
32    ) -> Result<ScriptTransaction>;
33}
34
35#[async_trait::async_trait]
36impl TransactionTuner for ContractCall {
37    async fn transaction_builder<T: Account>(
38        &self,
39        tx_policies: TxPolicies,
40        variable_output_policy: VariableOutputPolicy,
41        account: &T,
42    ) -> Result<ScriptTransactionBuilder> {
43        transaction_builder_from_contract_calls(
44            std::slice::from_ref(self),
45            tx_policies,
46            variable_output_policy,
47            account,
48        )
49        .await
50    }
51
52    async fn build_tx<T: Account>(
53        &self,
54        tx_policies: TxPolicies,
55        variable_output_policy: VariableOutputPolicy,
56        account: &T,
57    ) -> Result<ScriptTransaction> {
58        build_tx_from_contract_calls(
59            std::slice::from_ref(self),
60            tx_policies,
61            variable_output_policy,
62            account,
63        )
64        .await
65    }
66}
67
68#[async_trait::async_trait]
69impl TransactionTuner for ScriptCall {
70    async fn transaction_builder<T: Account>(
71        &self,
72        tx_policies: TxPolicies,
73        variable_output_policy: VariableOutputPolicy,
74        _account: &T,
75    ) -> Result<ScriptTransactionBuilder> {
76        let (inputs, outputs) = self.prepare_inputs_outputs()?;
77
78        Ok(ScriptTransactionBuilder::default()
79            .with_variable_output_policy(variable_output_policy)
80            .with_tx_policies(tx_policies)
81            .with_script(self.script_binary.clone())
82            .with_script_data(self.compute_script_data()?)
83            .with_inputs(inputs)
84            .with_outputs(outputs)
85            .with_gas_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE)
86            .with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE))
87    }
88
89    async fn build_tx<T: Account>(
90        &self,
91        tx_policies: TxPolicies,
92        variable_output_policy: VariableOutputPolicy,
93        account: &T,
94    ) -> Result<ScriptTransaction> {
95        let mut tb = self
96            .transaction_builder(tx_policies, variable_output_policy, account)
97            .await?;
98
99        account.add_witnesses(&mut tb)?;
100        account.adjust_for_fee(&mut tb, 0).await?;
101
102        tb.build(account.try_provider()?).await
103    }
104}
105
106impl sealed::Sealed for Vec<ContractCall> {}
107
108#[async_trait::async_trait]
109impl TransactionTuner for Vec<ContractCall> {
110    async fn transaction_builder<T: Account>(
111        &self,
112        tx_policies: TxPolicies,
113        variable_output_policy: VariableOutputPolicy,
114        account: &T,
115    ) -> Result<ScriptTransactionBuilder> {
116        validate_contract_calls(self)?;
117
118        transaction_builder_from_contract_calls(self, tx_policies, variable_output_policy, account)
119            .await
120    }
121
122    /// Returns the script that executes the contract calls
123    async fn build_tx<T: Account>(
124        &self,
125        tx_policies: TxPolicies,
126        variable_output_policy: VariableOutputPolicy,
127        account: &T,
128    ) -> Result<ScriptTransaction> {
129        validate_contract_calls(self)?;
130
131        build_tx_from_contract_calls(self, tx_policies, variable_output_policy, account).await
132    }
133}
134
135fn validate_contract_calls(calls: &[ContractCall]) -> Result<()> {
136    if calls.is_empty() {
137        return Err(error!(
138            Other,
139            "no calls added. Have you used '.add_calls()'?"
140        ));
141    }
142
143    Ok(())
144}