fuels_programs/calls/
contract_call.rs

1use std::{collections::HashMap, fmt::Debug};
2
3use fuels_core::{
4    constants::DEFAULT_CALL_PARAMS_AMOUNT,
5    error,
6    types::{
7        Address, AssetId, ContractId, Selector, errors::Result, input::Input, output::Output,
8        param_types::ParamType,
9    },
10};
11
12use crate::{assembly::contract_call::ContractCallData, calls::utils::sealed};
13
14#[derive(Debug, Clone)]
15/// Contains all data relevant to a single contract call
16pub struct ContractCall {
17    pub contract_id: ContractId,
18    pub encoded_args: Result<Vec<u8>>,
19    pub encoded_selector: Selector,
20    pub call_parameters: CallParameters,
21    pub external_contracts: Vec<ContractId>,
22    pub output_param: ParamType,
23    pub is_payable: bool,
24    pub custom_assets: HashMap<(AssetId, Option<Address>), u64>,
25    pub inputs: Vec<Input>,
26    pub outputs: Vec<Output>,
27}
28
29impl ContractCall {
30    pub(crate) fn data(&self, base_asset_id: AssetId) -> Result<ContractCallData> {
31        let encoded_args = self
32            .encoded_args
33            .as_ref()
34            .map_err(|e| error!(Codec, "cannot encode contract call arguments: {e}"))?
35            .to_owned();
36
37        Ok(ContractCallData {
38            amount: self.call_parameters.amount(),
39            asset_id: self.call_parameters.asset_id().unwrap_or(base_asset_id),
40            contract_id: self.contract_id,
41            fn_selector_encoded: self.encoded_selector.clone(),
42            encoded_args,
43            gas_forwarded: self.call_parameters.gas_forwarded,
44        })
45    }
46
47    pub fn with_contract_id(self, contract_id: ContractId) -> Self {
48        ContractCall {
49            contract_id,
50            ..self
51        }
52    }
53
54    pub fn with_call_parameters(self, call_parameters: CallParameters) -> ContractCall {
55        ContractCall {
56            call_parameters,
57            ..self
58        }
59    }
60
61    pub fn add_custom_asset(&mut self, asset_id: AssetId, amount: u64, to: Option<Address>) {
62        *self.custom_assets.entry((asset_id, to)).or_default() += amount;
63    }
64
65    /// Add custom outputs to the `ContractCall`.
66    pub fn with_outputs(mut self, outputs: Vec<Output>) -> Self {
67        self.outputs = outputs;
68        self
69    }
70
71    /// Add custom inputs to the `ContractCall`.
72    pub fn with_inputs(mut self, inputs: Vec<Input>) -> Self {
73        self.inputs = inputs;
74        self
75    }
76}
77
78impl sealed::Sealed for ContractCall {}
79
80#[derive(Debug, Clone)]
81pub struct CallParameters {
82    amount: u64,
83    asset_id: Option<AssetId>,
84    gas_forwarded: Option<u64>,
85}
86
87impl CallParameters {
88    pub fn new(amount: u64, asset_id: AssetId, gas_forwarded: u64) -> Self {
89        Self {
90            amount,
91            asset_id: Some(asset_id),
92            gas_forwarded: Some(gas_forwarded),
93        }
94    }
95
96    pub fn with_amount(mut self, amount: u64) -> Self {
97        self.amount = amount;
98        self
99    }
100
101    pub fn amount(&self) -> u64 {
102        self.amount
103    }
104
105    pub fn with_asset_id(mut self, asset_id: AssetId) -> Self {
106        self.asset_id = Some(asset_id);
107        self
108    }
109
110    pub fn asset_id(&self) -> Option<AssetId> {
111        self.asset_id
112    }
113
114    pub fn with_gas_forwarded(mut self, gas_forwarded: u64) -> Self {
115        self.gas_forwarded = Some(gas_forwarded);
116        self
117    }
118
119    pub fn gas_forwarded(&self) -> Option<u64> {
120        self.gas_forwarded
121    }
122}
123
124impl Default for CallParameters {
125    fn default() -> Self {
126        Self {
127            amount: DEFAULT_CALL_PARAMS_AMOUNT,
128            asset_id: None,
129            gas_forwarded: None,
130        }
131    }
132}