multiversx_chain_vm/host/context/
tx_input.rs

1use num_bigint::BigUint;
2use num_traits::Zero;
3
4use crate::{
5    display_util::*,
6    types::{H256, VMAddress},
7};
8use std::fmt;
9
10use super::{CallType, TxFunctionName};
11
12#[derive(Clone, Debug)]
13pub struct TxInput {
14    pub from: VMAddress,
15    pub to: VMAddress,
16    pub egld_value: BigUint,
17    pub esdt_values: Vec<TxTokenTransfer>,
18    pub func_name: TxFunctionName,
19    pub args: Vec<Vec<u8>>,
20    pub call_type: CallType,
21    pub readonly: bool, // should probably be in TxContext, but it is easier to keep it here, for now
22    pub gas_limit: u64,
23    pub gas_price: u64,
24    pub tx_hash: H256,
25    pub promise_callback_closure_data: Option<Vec<u8>>,
26    pub callback_payments: CallbackPayments,
27}
28
29impl Default for TxInput {
30    fn default() -> Self {
31        TxInput {
32            from: VMAddress::zero(),
33            to: VMAddress::zero(),
34            egld_value: BigUint::zero(),
35            esdt_values: Vec::new(),
36            func_name: TxFunctionName::EMPTY,
37            args: Vec::new(),
38            call_type: CallType::DirectCall,
39            readonly: false,
40            gas_limit: 0,
41            gas_price: 0,
42            tx_hash: H256::zero(),
43            promise_callback_closure_data: None,
44            callback_payments: Default::default(),
45        }
46    }
47}
48
49impl fmt::Display for TxInput {
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        write!(
52            f,
53            "TxInput {{ func: {}, args: {:?}, call_value: {}, esdt_value: {:?}, from: 0x{}, to: 0x{}\n}}",
54            self.func_name.as_str(),
55            self.args,
56            self.egld_value,
57            self.esdt_values,
58            address_hex(&self.from),
59            address_hex(&self.to)
60        )
61    }
62}
63
64impl TxInput {
65    pub fn add_arg(&mut self, arg: Vec<u8>) {
66        self.args.push(arg);
67    }
68
69    pub fn func_name_from_arg_index(&self, arg_index: usize) -> TxFunctionName {
70        if let Some(arg) = self.args.get(arg_index) {
71            arg.into()
72        } else {
73            TxFunctionName::EMPTY
74        }
75    }
76}
77
78/// Models ESDT transfers between accounts.
79#[derive(Clone, Debug, PartialEq, Eq)]
80pub struct TxTokenTransfer {
81    pub token_identifier: Vec<u8>,
82    pub nonce: u64,
83    pub value: BigUint,
84}
85
86/// Signals to the callback that funds have been returned to it, without performing any transfer.
87#[derive(Default, Clone, Debug)]
88pub struct CallbackPayments {
89    pub egld_value: BigUint,
90    pub esdt_values: Vec<TxTokenTransfer>,
91}
92
93impl TxInput {
94    /// The received EGLD can come either from the original caller, or from an async call, during callback.
95    pub fn received_egld(&self) -> &BigUint {
96        if !self.callback_payments.egld_value.is_zero() {
97            &self.callback_payments.egld_value
98        } else {
99            &self.egld_value
100        }
101    }
102
103    /// The received ESDT tokens can come either from the original caller, or from an async call, during callback.
104    pub fn received_esdt(&self) -> &[TxTokenTransfer] {
105        if !self.callback_payments.esdt_values.is_empty() {
106            self.callback_payments.esdt_values.as_slice()
107        } else {
108            self.esdt_values.as_slice()
109        }
110    }
111
112    pub fn get_argument_vec_u8(&self, arg_index: i32) -> Vec<u8> {
113        let arg_idx_usize = arg_index as usize;
114        assert!(arg_idx_usize < self.args.len(), "Tx arg index out of range");
115        self.args[arg_idx_usize].clone()
116    }
117}