multiversx_sc_scenario/scenario/model/step/
sc_deploy_step.rs

1use multiversx_sc::types::H256;
2
3use crate::{
4    api::StaticApi,
5    scenario_format::interpret_trait::{InterpretableFrom, InterpreterContext},
6};
7
8use crate::{
9    scenario::model::{AddressValue, BigUintValue, BytesValue, TxDeploy, TxExpect, U64Value},
10    scenario_model::TxResponse,
11};
12
13use crate::multiversx_sc::types::CodeMetadata;
14
15use super::{convert_call_args, TypedScDeploy};
16
17#[derive(Debug, Clone)]
18pub struct ScDeployStep {
19    pub id: String,
20    pub tx_id: Option<String>,
21    pub explicit_tx_hash: Option<H256>,
22    pub comment: Option<String>,
23    pub tx: Box<TxDeploy>,
24    pub expect: Option<TxExpect>,
25    pub response: Option<TxResponse>,
26}
27
28impl Default for ScDeployStep {
29    fn default() -> Self {
30        Self {
31            id: Default::default(),
32            tx_id: Default::default(),
33            explicit_tx_hash: Default::default(),
34            comment: Default::default(),
35            tx: Default::default(),
36            expect: Some(TxExpect::ok()),
37            response: Default::default(),
38        }
39    }
40}
41
42impl ScDeployStep {
43    pub fn new() -> Self {
44        Self::default()
45    }
46
47    pub fn from<V>(mut self, expr: V) -> Self
48    where
49        AddressValue: From<V>,
50    {
51        self.tx.from = AddressValue::from(expr);
52        self
53    }
54
55    pub fn egld_value<V>(mut self, expr: V) -> Self
56    where
57        BigUintValue: From<V>,
58    {
59        self.tx.egld_value = BigUintValue::from(expr);
60        self
61    }
62
63    pub fn code_metadata(mut self, code_metadata: CodeMetadata) -> Self {
64        self.tx.code_metadata = code_metadata;
65        self
66    }
67
68    pub fn code<V>(mut self, expr: V) -> Self
69    where
70        BytesValue: From<V>,
71    {
72        self.tx.contract_code = BytesValue::from(expr);
73        self
74    }
75
76    #[deprecated(
77        since = "0.42.0",
78        note = "Please use method `code` instead. To ease transition, it is also possible to call it with a tuple like so: `.code((expr, context))`"
79    )]
80    pub fn contract_code(mut self, expr: &str, context: &InterpreterContext) -> Self {
81        self.tx.contract_code = BytesValue::interpret_from(expr, context);
82        self
83    }
84
85    pub fn argument(mut self, expr: &str) -> Self {
86        self.tx.arguments.push(BytesValue::from(expr));
87        self
88    }
89
90    pub fn gas_limit<V>(mut self, value: V) -> Self
91    where
92        U64Value: From<V>,
93    {
94        self.tx.gas_limit = U64Value::from(value);
95        self
96    }
97
98    /// Sets following fields based on the smart contract proxy:
99    /// - "function"
100    /// - "arguments"
101    #[deprecated(
102        since = "0.49.0",
103        note = "Please use the unified transaction syntax instead."
104    )]
105    #[allow(deprecated)]
106    pub fn call<OriginalResult, CD>(mut self, contract_deploy: CD) -> TypedScDeploy<OriginalResult>
107    where
108        CD: Into<multiversx_sc::types::ContractDeploy<StaticApi, OriginalResult>>,
109    {
110        let (_, mandos_args) = process_contract_deploy(contract_deploy.into());
111        for arg in mandos_args {
112            self = self.argument(arg.as_str());
113        }
114        self.into()
115    }
116
117    /// Adds a custom expect section to the tx.
118    pub fn expect(mut self, expect: TxExpect) -> Self {
119        self.expect = Some(expect);
120        self
121    }
122
123    /// Explicitly states that no tx expect section should be added and no checks should be performed.
124    ///
125    /// Note: by default a basic `TxExpect::ok()` is added, which checks that status is 0 and nothing else.
126    pub fn no_expect(mut self) -> Self {
127        self.expect = None;
128        self
129    }
130
131    /// Unwraps the response, if available.
132    pub fn response(&self) -> &TxResponse {
133        self.response
134            .as_ref()
135            .expect("SC deploy response not yet available")
136    }
137
138    pub fn save_response(&mut self, mut tx_response: TxResponse) {
139        if let Some(expect) = &mut self.expect {
140            if expect.build_from_response {
141                expect.update_from_response(&tx_response)
142            }
143        }
144        if tx_response.tx_hash.is_none() {
145            tx_response.tx_hash = self
146                .explicit_tx_hash
147                .as_ref()
148                .map(|vm_hash| vm_hash.as_array().into());
149        }
150        self.response = Some(tx_response);
151    }
152}
153
154impl AsMut<ScDeployStep> for ScDeployStep {
155    fn as_mut(&mut self) -> &mut ScDeployStep {
156        self
157    }
158}
159
160/// Extracts
161/// - (optional) recipient (needed for contract upgrade, not yet used);
162/// - the arguments.
163#[deprecated(
164    since = "0.49.0",
165    note = "Please use the unified transaction syntax instead."
166)]
167#[allow(deprecated)]
168pub(crate) fn process_contract_deploy<OriginalResult>(
169    contract_deploy: multiversx_sc::types::ContractDeploy<StaticApi, OriginalResult>,
170) -> (Option<String>, Vec<String>) {
171    let to_str = contract_deploy
172        .to
173        .as_option()
174        .map(|to| format!("0x{}", hex::encode(to.to_address().as_bytes())));
175    let mandos_args = convert_call_args(&contract_deploy.arg_buffer);
176    (to_str, mandos_args)
177}