From fe7b4065eb4e43d73859126485709290f648c5b0 Mon Sep 17 00:00:00 2001 From: Andrei Marinica Date: Wed, 12 Jul 2023 13:31:06 +0300 Subject: [PATCH] TxResponse refactor prototype --- .../src/scenario/model/step/typed_sc_call.rs | 4 +- .../scenario/model/step/typed_sc_deploy.rs | 4 +- .../{transaction/mod.rs => transaction.rs} | 4 +- .../scenario/model/transaction/tx_response.rs | 62 +++++++++---------- .../model/transaction/tx_response_status.rs | 21 +++++++ .../snippets/src/interactor_multi_sc_exec.rs | 2 +- framework/snippets/src/interactor_sc_call.rs | 2 +- .../snippets/src/interactor_sc_deploy.rs | 2 +- 8 files changed, 61 insertions(+), 40 deletions(-) rename framework/scenario/src/scenario/model/{transaction/mod.rs => transaction.rs} (80%) create mode 100644 framework/scenario/src/scenario/model/transaction/tx_response_status.rs diff --git a/framework/scenario/src/scenario/model/step/typed_sc_call.rs b/framework/scenario/src/scenario/model/step/typed_sc_call.rs index 844d0c4fba..4cf74feaed 100644 --- a/framework/scenario/src/scenario/model/step/typed_sc_call.rs +++ b/framework/scenario/src/scenario/model/step/typed_sc_call.rs @@ -6,7 +6,7 @@ use crate::multiversx_sc::codec::{CodecFrom, TopEncodeMulti}; use crate::{ scenario::model::{AddressValue, U64Value}, - scenario_model::{BigUintValue, BytesValue, TxError, TxExpect, TxResponse}, + scenario_model::{BigUintValue, BytesValue, TxResponseStatus, TxExpect, TxResponse}, }; use super::ScCallStep; @@ -19,7 +19,7 @@ pub struct TypedScCall { } impl TypedScCall { - pub fn result(&self) -> Result + pub fn result(&self) -> Result where OriginalResult: TopEncodeMulti, RequestedResult: CodecFrom, diff --git a/framework/scenario/src/scenario/model/step/typed_sc_deploy.rs b/framework/scenario/src/scenario/model/step/typed_sc_deploy.rs index 49a590aa24..0fb765a58f 100644 --- a/framework/scenario/src/scenario/model/step/typed_sc_deploy.rs +++ b/framework/scenario/src/scenario/model/step/typed_sc_deploy.rs @@ -8,7 +8,7 @@ use crate::{ types::{Address, CodeMetadata}, }, scenario_format::interpret_trait::InterpreterContext, - scenario_model::{TxError, TxResponse}, + scenario_model::{TxResponseStatus, TxResponse}, }; use crate::scenario::model::{AddressValue, BigUintValue, TxExpect, U64Value}; @@ -23,7 +23,7 @@ pub struct TypedScDeploy { } impl TypedScDeploy { - pub fn result(&self) -> Result + pub fn result(&self) -> Result where OriginalResult: TopEncodeMulti, RequestedResult: CodecFrom, diff --git a/framework/scenario/src/scenario/model/transaction/mod.rs b/framework/scenario/src/scenario/model/transaction.rs similarity index 80% rename from framework/scenario/src/scenario/model/transaction/mod.rs rename to framework/scenario/src/scenario/model/transaction.rs index b318f51357..1b1abb0050 100644 --- a/framework/scenario/src/scenario/model/transaction/mod.rs +++ b/framework/scenario/src/scenario/model/transaction.rs @@ -8,6 +8,7 @@ mod tx_expect; mod tx_interpret_util; mod tx_query; mod tx_response; +mod tx_response_status; mod tx_transfer; mod tx_validator_reward; @@ -19,6 +20,7 @@ pub use tx_deploy::*; pub use tx_esdt::*; pub use tx_expect::*; pub use tx_query::*; -pub use tx_response::*; +pub use tx_response::TxResponse; +pub use tx_response_status::TxResponseStatus; pub use tx_transfer::*; pub use tx_validator_reward::*; diff --git a/framework/scenario/src/scenario/model/transaction/tx_response.rs b/framework/scenario/src/scenario/model/transaction/tx_response.rs index 6e893aacdb..d85ce881ff 100644 --- a/framework/scenario/src/scenario/model/transaction/tx_response.rs +++ b/framework/scenario/src/scenario/model/transaction/tx_response.rs @@ -6,36 +6,23 @@ use crate::{ scenario_model::{BytesValue, U64Value}, }; use log::info; +use multiversx_chain_vm::tx_mock::TxResult; use multiversx_sdk::data::transaction::{ ApiLogs, ApiSmartContractResult, Events, TransactionOnNetwork, }; -use super::Log; +use super::{Log, TxResponseStatus}; const LOG_IDENTIFIER_SC_DEPLOY: &str = "SCDeploy"; const LOG_IDENTIFIER_SIGNAL_ERROR: &str = "signalError"; const SYSTEM_SC_BECH32: &str = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"; -#[derive(Debug)] -pub struct TxError { - pub message: String, -} - -impl std::fmt::Display for TxError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "transaction error: {}", self.message) - } -} - -impl Error for TxError {} - #[derive(Debug, Default, Clone)] pub struct TxResponse { pub out: Vec>, - pub new_deployed_address: Address, - pub status: u64, - pub message: Vec, + pub new_deployed_address: Option
, + pub tx_error: TxResponseStatus, pub logs: Vec, pub gas: u64, pub refund: u64, @@ -44,7 +31,7 @@ pub struct TxResponse { } impl TxResponse { - pub fn new(tx: TransactionOnNetwork) -> Self { + pub fn from_network_tx(tx: TransactionOnNetwork) -> Self { let mut response = Self { api_scrs: tx.smart_contract_results.unwrap_or_default(), api_logs: tx.logs, @@ -55,12 +42,23 @@ impl TxResponse { response.new_deployed_address = response.new_deployed_address().unwrap(); } - pub fn process_result(&self) -> Result>, TxError> { + pub fn from_tx_result(tx_result: TxResult) -> Self { + TxResponse { + out: tx_result.result_values, + tx_error: TxResponseStatus { + status: tx_result.result_status, + message: tx_result.result_message, + }, + ..Default::default() + } + } + + pub fn process_result(&self) -> Result>, TxResponseStatus> { self.handle_signal_error_event()?; let first_scr = self.api_scrs.get(0); if first_scr.is_none() { - return Err(TxError { + return Err(TxResponseStatus { message: "no smart contract results obtained".to_string(), }); } @@ -68,17 +66,17 @@ impl TxResponse { Ok(decode_scr_data_or_panic(first_scr.unwrap().data.as_str())) } - pub fn raw_result(&self) -> Result>, TxError> { + pub fn raw_result(&self) -> Result>, TxResponseStatus> { Ok(self.out) } - pub fn new_deployed_address(&self) -> Result { + pub fn new_deployed_address(&self) -> Result { self.handle_signal_error_event()?; self.handle_sc_deploy_event() } // Returns the token identifier of the newly issued non-fungible token. - pub fn issue_non_fungible_new_token_identifier(&self) -> Result { + pub fn issue_non_fungible_new_token_identifier(&self) -> Result { self.handle_signal_error_event()?; let token_identifier_issue_scr: Option<&ApiSmartContractResult> = self @@ -87,7 +85,7 @@ impl TxResponse { .find(|scr| scr.sender.to_string() == SYSTEM_SC_BECH32 && scr.data.starts_with("@00@")); if token_identifier_issue_scr.is_none() { - return Err(TxError { + return Err(TxResponseStatus { message: "no token identifier SCR found".to_string(), }); } @@ -95,7 +93,7 @@ impl TxResponse { let token_identifier_issue_scr = token_identifier_issue_scr.unwrap(); let encoded_tid = token_identifier_issue_scr.data.split('@').nth(2); if encoded_tid.is_none() { - return Err(TxError { + return Err(TxResponseStatus { message: format!( "bad issue token SCR data: {}", token_identifier_issue_scr.data @@ -118,22 +116,22 @@ impl TxResponse { } // Handles a signalError event - pub fn handle_signal_error_event(&self) -> Result<(), TxError> { + pub fn handle_signal_error_event(&self) -> Result<(), TxResponseStatus> { if let Some(event) = self.find_log(LOG_IDENTIFIER_SIGNAL_ERROR) { let topics = self.handle_event_topics(event, LOG_IDENTIFIER_SIGNAL_ERROR)?; let error_raw = base64::decode(topics.get(1).unwrap()).unwrap(); let error = String::from_utf8(error_raw).unwrap(); - return Err(TxError { message: error }); + return Err(TxResponseStatus { message: error }); } Ok(()) } // Handles a scDeploy event - fn handle_sc_deploy_event(&self) -> Result { + fn handle_sc_deploy_event(&self) -> Result { let event: Option<&Events> = self.find_log(LOG_IDENTIFIER_SC_DEPLOY); if event.is_none() { - return Err(TxError { + return Err(TxResponseStatus { message: format!("`{LOG_IDENTIFIER_SC_DEPLOY}` event not found"), }); } @@ -150,17 +148,17 @@ impl TxResponse { &'a self, event: &'b Events, log_identifier: &str, - ) -> Result<&Vec, TxError> { + ) -> Result<&Vec, TxResponseStatus> { let option = event.topics.as_ref(); if option.is_none() { - return Err(TxError { + return Err(TxResponseStatus { message: "missing topics".to_string(), }); } let topics = option.unwrap(); if topics.len() != 2 { - return Err(TxError { + return Err(TxResponseStatus { message: format!( "`{log_identifier}` is expected to have 2 topics, found {}", topics.len() diff --git a/framework/scenario/src/scenario/model/transaction/tx_response_status.rs b/framework/scenario/src/scenario/model/transaction/tx_response_status.rs new file mode 100644 index 0000000000..148f686590 --- /dev/null +++ b/framework/scenario/src/scenario/model/transaction/tx_response_status.rs @@ -0,0 +1,21 @@ +#[derive(Debug, Default)] +pub struct TxResponseStatus { + pub status: u64, + pub message: String, +} + +impl TxResponseStatus { + pub fn is_success(&self) -> bool { + self.status == 0 + } +} + +impl std::fmt::Display for TxResponseStatus { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.is_success() { + write!(f, "transaction successful") + } else { + write!(f, "transaction error: {}", self.message) + } + } +} diff --git a/framework/snippets/src/interactor_multi_sc_exec.rs b/framework/snippets/src/interactor_multi_sc_exec.rs index 28b5cb4737..9d71d83da9 100644 --- a/framework/snippets/src/interactor_multi_sc_exec.rs +++ b/framework/snippets/src/interactor_multi_sc_exec.rs @@ -19,7 +19,7 @@ impl Interactor { let results = self.process_txs(txs).await; for (i, sc_call_step) in buffer.refs.iter_mut().enumerate() { - sc_call_step.set_response(TxResponse::new(results.get(i).unwrap().clone())); + sc_call_step.set_response(TxResponse::from_network_tx(results.get(i).unwrap().clone())); } for step in buffer.refs.iter() { diff --git a/framework/snippets/src/interactor_sc_call.rs b/framework/snippets/src/interactor_sc_call.rs index 6066988062..509ead9b3c 100644 --- a/framework/snippets/src/interactor_sc_call.rs +++ b/framework/snippets/src/interactor_sc_call.rs @@ -17,7 +17,7 @@ impl Interactor { let tx_hash = self.launch_sc_call(sc_call_step).await; let tx = self.retrieve_tx_on_network(tx_hash.clone()).await; - sc_call_step.response = Some(TxResponse::new(tx)); + sc_call_step.response = Some(TxResponse::from_network_tx(tx)); if let Ok(token_identifier) = sc_call_step .response() diff --git a/framework/snippets/src/interactor_sc_deploy.rs b/framework/snippets/src/interactor_sc_deploy.rs index 49f2788cbf..3bcb57eac8 100644 --- a/framework/snippets/src/interactor_sc_deploy.rs +++ b/framework/snippets/src/interactor_sc_deploy.rs @@ -50,7 +50,7 @@ impl Interactor { let addr = sc_deploy_step.tx.from.clone(); let nonce = tx.nonce; - sc_deploy_step.response = Some(TxResponse::new(tx)); + sc_deploy_step.response = Some(TxResponse::from_network_tx(tx)); let deploy_address = sc_deploy_step.response().new_deployed_address().unwrap();