fuels_programs/calls/
script_call.rs

1use std::{collections::HashSet, fmt::Debug};
2
3use fuels_core::types::{
4    ContractId,
5    errors::{Result, error},
6    input::Input,
7    output::Output,
8};
9use itertools::chain;
10
11use crate::calls::utils::{generate_contract_inputs, generate_contract_outputs, sealed};
12
13#[derive(Debug, Clone)]
14/// Contains all data relevant to a single script call
15pub struct ScriptCall {
16    pub script_binary: Vec<u8>,
17    pub encoded_args: Result<Vec<u8>>,
18    pub inputs: Vec<Input>,
19    pub outputs: Vec<Output>,
20    pub external_contracts: Vec<ContractId>,
21}
22
23impl ScriptCall {
24    /// Add custom outputs to the `ScriptCall`.
25    pub fn with_outputs(mut self, outputs: Vec<Output>) -> Self {
26        self.outputs = outputs;
27        self
28    }
29
30    /// Add custom inputs to the `ScriptCall`.
31    pub fn with_inputs(mut self, inputs: Vec<Input>) -> Self {
32        self.inputs = inputs;
33        self
34    }
35
36    pub(crate) fn prepare_inputs_outputs(&self) -> Result<(Vec<Input>, Vec<Output>)> {
37        let contract_ids: HashSet<ContractId> = self.external_contracts.iter().copied().collect();
38        let num_of_contracts = contract_ids.len();
39
40        let inputs = chain!(
41            self.inputs.clone(),
42            generate_contract_inputs(contract_ids, self.outputs.len())
43        )
44        .collect();
45
46        // Note the contract_outputs are placed after the custom outputs and
47        // the contract_inputs are referencing them via `output_index`. The
48        // node will, upon receiving our request, use `output_index` to index
49        // the `inputs` array we've sent over.
50        let outputs = chain!(
51            self.outputs.clone(),
52            generate_contract_outputs(num_of_contracts, self.inputs.len()),
53        )
54        .collect();
55
56        Ok((inputs, outputs))
57    }
58
59    pub(crate) fn compute_script_data(&self) -> Result<Vec<u8>> {
60        self.encoded_args
61            .as_ref()
62            .map(|b| b.to_owned())
63            .map_err(|e| error!(Codec, "cannot encode script call arguments: {e}"))
64    }
65}
66
67impl sealed::Sealed for ScriptCall {}