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_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 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}