fuels_programs/calls/traits/
transaction_tuner.rs1use 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 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}