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_with_tb, 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        tb: ScriptTransactionBuilder,
30        account: &T,
31    ) -> Result<ScriptTransaction>;
32}
33
34#[async_trait::async_trait]
35impl TransactionTuner for ContractCall {
36    async fn transaction_builder<T: Account>(
37        &self,
38        tx_policies: TxPolicies,
39        variable_output_policy: VariableOutputPolicy,
40        account: &T,
41    ) -> Result<ScriptTransactionBuilder> {
42        transaction_builder_from_contract_calls(
43            std::slice::from_ref(self),
44            tx_policies,
45            variable_output_policy,
46            account,
47        )
48        .await
49    }
50
51    async fn build_tx<T: Account>(
52        &self,
53        tb: ScriptTransactionBuilder,
54        account: &T,
55    ) -> Result<ScriptTransaction> {
56        build_with_tb(std::slice::from_ref(self), tb, account).await
57    }
58}
59
60#[async_trait::async_trait]
61impl TransactionTuner for ScriptCall {
62    async fn transaction_builder<T: Account>(
63        &self,
64        tx_policies: TxPolicies,
65        variable_output_policy: VariableOutputPolicy,
66        _account: &T,
67    ) -> Result<ScriptTransactionBuilder> {
68        let (inputs, outputs) = self.prepare_inputs_outputs()?;
69
70        Ok(ScriptTransactionBuilder::default()
71            .with_variable_output_policy(variable_output_policy)
72            .with_tx_policies(tx_policies)
73            .with_script(self.script_binary.clone())
74            .with_script_data(self.compute_script_data()?)
75            .with_inputs(inputs)
76            .with_outputs(outputs)
77            .with_gas_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE)
78            .with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE))
79    }
80
81    async fn build_tx<T: Account>(
82        &self,
83        mut tb: ScriptTransactionBuilder,
84        account: &T,
85    ) -> Result<ScriptTransaction> {
86        account.add_witnesses(&mut tb)?;
87        account.adjust_for_fee(&mut tb, 0).await?;
88
89        tb.build(account.try_provider()?).await
90    }
91}
92
93impl sealed::Sealed for Vec<ContractCall> {}
94
95#[async_trait::async_trait]
96impl TransactionTuner for Vec<ContractCall> {
97    async fn transaction_builder<T: Account>(
98        &self,
99        tx_policies: TxPolicies,
100        variable_output_policy: VariableOutputPolicy,
101        account: &T,
102    ) -> Result<ScriptTransactionBuilder> {
103        validate_contract_calls(self)?;
104
105        transaction_builder_from_contract_calls(self, tx_policies, variable_output_policy, account)
106            .await
107    }
108
109    /// Returns the script that executes the contract calls
110    async fn build_tx<T: Account>(
111        &self,
112        tb: ScriptTransactionBuilder,
113        account: &T,
114    ) -> Result<ScriptTransaction> {
115        validate_contract_calls(self)?;
116
117        build_with_tb(self, tb, account).await
118    }
119}
120
121fn validate_contract_calls(calls: &[ContractCall]) -> Result<()> {
122    if calls.is_empty() {
123        return Err(error!(
124            Other,
125            "no calls added. Have you used '.add_calls()'?"
126        ));
127    }
128
129    Ok(())
130}