fuels_programs/calls/
script_call.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use std::{collections::HashSet, fmt::Debug};

use fuel_tx::{ContractId, Output};
use fuels_core::types::{
    bech32::Bech32ContractId,
    errors::{error, Result},
    input::Input,
};
use itertools::chain;

use crate::calls::utils::{generate_contract_inputs, generate_contract_outputs, sealed};

#[derive(Debug, Clone)]
/// Contains all data relevant to a single script call
pub struct ScriptCall {
    pub script_binary: Vec<u8>,
    pub encoded_args: Result<Vec<u8>>,
    pub inputs: Vec<Input>,
    pub outputs: Vec<Output>,
    pub external_contracts: Vec<Bech32ContractId>,
}

impl ScriptCall {
    pub fn with_outputs(mut self, outputs: Vec<Output>) -> Self {
        self.outputs = outputs;
        self
    }

    pub fn with_inputs(mut self, inputs: Vec<Input>) -> Self {
        self.inputs = inputs;
        self
    }

    pub(crate) fn prepare_inputs_outputs(&self) -> Result<(Vec<Input>, Vec<Output>)> {
        let contract_ids: HashSet<ContractId> = self
            .external_contracts
            .iter()
            .map(|bech32| bech32.into())
            .collect();
        let num_of_contracts = contract_ids.len();

        let inputs = chain!(generate_contract_inputs(contract_ids), self.inputs.clone(),).collect();

        // Note the contract_outputs need to come first since the
        // contract_inputs are referencing them via `output_index`. The node
        // will, upon receiving our request, use `output_index` to index the
        // `inputs` array we've sent over.
        let outputs = chain!(
            generate_contract_outputs(num_of_contracts),
            self.outputs.clone(),
        )
        .collect();

        Ok((inputs, outputs))
    }

    pub(crate) fn compute_script_data(&self) -> Result<Vec<u8>> {
        self.encoded_args
            .as_ref()
            .map(|b| b.to_owned())
            .map_err(|e| error!(Codec, "cannot encode script call arguments: {e}"))
    }
}

impl sealed::Sealed for ScriptCall {}