fuels_programs/calls/
contract_call.rs

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