Skip to content

Commit

Permalink
TxResponse refactor part1
Browse files Browse the repository at this point in the history
  • Loading branch information
ovstinga committed Jul 12, 2023
1 parent fe7b406 commit e893b0f
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl<OriginalResult> TypedScCall<OriginalResult> {
OriginalResult: TopEncodeMulti,
RequestedResult: CodecFrom<OriginalResult>,
{
let mut raw_result = self.response().raw_result()?;
let mut raw_result = self.response().out.clone();
Ok(
RequestedResult::multi_decode_or_handle_err(&mut raw_result, PanicErrorHandler)
.unwrap(),
Expand Down
4 changes: 2 additions & 2 deletions framework/scenario/src/scenario/model/step/typed_sc_deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
types::{Address, CodeMetadata},
},
scenario_format::interpret_trait::InterpreterContext,
scenario_model::{TxResponseStatus, TxResponse},
scenario_model::{TxResponse, TxResponseStatus},
};

use crate::scenario::model::{AddressValue, BigUintValue, TxExpect, U64Value};
Expand All @@ -28,7 +28,7 @@ impl<OriginalResult> TypedScDeploy<OriginalResult> {
OriginalResult: TopEncodeMulti,
RequestedResult: CodecFrom<OriginalResult>,
{
let mut raw_result = self.response().raw_result()?;
let mut raw_result = self.response().out.clone();
Ok(
RequestedResult::multi_decode_or_handle_err(&mut raw_result, PanicErrorHandler)
.unwrap(),
Expand Down
189 changes: 92 additions & 97 deletions framework/scenario/src/scenario/model/transaction/tx_response.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
use std::error::Error;
use core::panic;

use crate::{
bech32,
multiversx_sc::types::Address,
scenario_model::{BytesValue, U64Value},
};
use log::info;
use crate::multiversx_sc::types::Address;
use multiversx_chain_vm::tx_mock::TxResult;
use multiversx_sdk::data::transaction::{
ApiLogs, ApiSmartContractResult, Events, TransactionOnNetwork,
Expand All @@ -31,17 +26,6 @@ pub struct TxResponse {
}

impl TxResponse {
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,
..Default::default()
};

response.out = response.raw_result().unwrap();
response.new_deployed_address = response.new_deployed_address().unwrap();
}

pub fn from_tx_result(tx_result: TxResult) -> Self {
TxResponse {
out: tx_result.result_values,
Expand All @@ -53,59 +37,60 @@ impl TxResponse {
}
}

pub fn process_result(&self) -> Result<Vec<Vec<u8>>, TxResponseStatus> {
self.handle_signal_error_event()?;
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,
..Default::default()
};

let first_scr = self.api_scrs.get(0);
if first_scr.is_none() {
return Err(TxResponseStatus {
message: "no smart contract results obtained".to_string(),
});
response.tx_error = response.process_signal_error();
if !response.tx_error.is_success() {
return response;
}

Ok(decode_scr_data_or_panic(first_scr.unwrap().data.as_str()))
}

pub fn raw_result(&self) -> Result<Vec<Vec<u8>>, TxResponseStatus> {
Ok(self.out)
response.process()
}

pub fn new_deployed_address(&self) -> Result<Address, TxResponseStatus> {
self.handle_signal_error_event()?;
self.handle_sc_deploy_event()
fn process(self) -> Self {
self.process_out().process_new_deployed_address()
}

// Returns the token identifier of the newly issued non-fungible token.
pub fn issue_non_fungible_new_token_identifier(&self) -> Result<String, TxResponseStatus> {
self.handle_signal_error_event()?;

let token_identifier_issue_scr: Option<&ApiSmartContractResult> = self
.api_scrs
.iter()
.find(|scr| scr.sender.to_string() == SYSTEM_SC_BECH32 && scr.data.starts_with("@00@"));

if token_identifier_issue_scr.is_none() {
return Err(TxResponseStatus {
message: "no token identifier SCR found".to_string(),
});
fn process_out(mut self) -> Self {
if let Some(first_scr) = self.api_scrs.get(0) {
self.out = decode_scr_data_or_panic(first_scr.data.as_str());
} else {
panic!("no smart contract results obtained")
// self.tx_error.status = 0; // TODO: Add correct status
// self.tx_error.message = "no smart contract results obtained".to_string();
}
self
}

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(TxResponseStatus {
message: format!(
"bad issue token SCR data: {}",
token_identifier_issue_scr.data
),
});
fn process_new_deployed_address(mut self) -> Self {
if let Some(event) = self.find_log(LOG_IDENTIFIER_SC_DEPLOY).cloned() {
// handle topics
if let Some(topics) = event.topics.as_ref() {
if topics.len() != 2 {
self.tx_error.message.push_str(
format!("expected to have 2 topics, found {} instead", topics.len())
.as_str(),
);
}

let address_raw = base64::decode(topics.get(0).unwrap()).unwrap();
let address = Address::from_slice(address_raw.as_slice());
self.new_deployed_address = Some(address);
} else {
self.tx_error.message.push_str("missing topics");
}
}

Ok(String::from_utf8(hex::decode(encoded_tid.unwrap()).unwrap()).unwrap())
self
}

// Finds api logs matching the given log identifier.
pub fn find_log(&self, log_identifier: &str) -> Option<&Events> {
fn find_log(&self, log_identifier: &str) -> Option<&Events> {
if let Some(logs) = &self.api_logs {
logs.events
.iter()
Expand All @@ -115,57 +100,67 @@ impl TxResponse {
}
}

// Handles a signalError event
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();
fn process_signal_error(&self) -> TxResponseStatus {
let mut tx_error = TxResponseStatus::default();

return Err(TxResponseStatus { message: error });
if let Some(event) = self.find_log(LOG_IDENTIFIER_SIGNAL_ERROR) {
tx_error.status = 4;
tx_error.message = "signal error: ".to_string();

if let Some(topics) = event.topics.as_ref() {
if topics.len() != 2 {
tx_error.message.push_str(
format!(" expected to have 2 topics, found {} instead", topics.len())
.as_str(),
);
}

let error_raw = base64::decode(topics.get(1).unwrap()).unwrap();
let error = String::from_utf8(error_raw).unwrap();

tx_error.message.push_str(&error);
} else {
tx_error.message.push_str("missing topics");
}
}
Ok(())

tx_error
}

// Handles a scDeploy event
fn handle_sc_deploy_event(&self) -> Result<Address, TxResponseStatus> {
let event: Option<&Events> = self.find_log(LOG_IDENTIFIER_SC_DEPLOY);
if event.is_none() {
return Err(TxResponseStatus {
message: format!("`{LOG_IDENTIFIER_SC_DEPLOY}` event not found"),
});
pub fn handle_signal_error_event(&self) -> Result<(), TxResponseStatus> {
if !self.tx_error.is_success() {
Err(self.tx_error.clone())
} else {
Ok(())
}
let topics = self.handle_event_topics(event.unwrap(), LOG_IDENTIFIER_SC_DEPLOY)?;
let address_raw = base64::decode(topics.get(0).unwrap()).unwrap();
let address = Address::from_slice(address_raw.as_slice());
}

info!("new address: {}", bech32::encode(&address));
Ok(address)
pub fn new_deployed_address(&self) -> Result<Address, TxResponseStatus> {
if !self.tx_error.is_success() {
Err(self.tx_error.clone())
} else {
Ok(self.new_deployed_address.clone().unwrap())
}
}

// Handles the topics of an event and returns them.
fn handle_event_topics<'a, 'b: 'a>(
&'a self,
event: &'b Events,
log_identifier: &str,
) -> Result<&Vec<String>, TxResponseStatus> {
let option = event.topics.as_ref();
if option.is_none() {
return Err(TxResponseStatus {
message: "missing topics".to_string(),
});
// Returns the token identifier of the newly issued non-fungible token.
pub fn issue_non_fungible_new_token_identifier(&self) -> Result<String, TxResponseStatus> {
let token_identifier_issue_scr: Option<&ApiSmartContractResult> = self
.api_scrs
.iter()
.find(|scr| scr.sender.to_string() == SYSTEM_SC_BECH32 && scr.data.starts_with("@00@"));

if token_identifier_issue_scr.is_none() {
panic!("no token identifier issue SCR found");
}

let topics = option.unwrap();
if topics.len() != 2 {
return Err(TxResponseStatus {
message: format!(
"`{log_identifier}` is expected to have 2 topics, found {}",
topics.len()
),
});
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() {
panic!("no token identifier found in SCR");
}
Ok(topics)

Ok(String::from_utf8(hex::decode(encoded_tid.unwrap()).unwrap()).unwrap())
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[derive(Debug, Default)]
#[derive(Debug, Default, Clone)]
pub struct TxResponseStatus {
pub status: u64,
pub message: String,
Expand Down
2 changes: 1 addition & 1 deletion framework/snippets/src/interactor_sc_deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl Interactor {
let nonce = tx.nonce;
sc_deploy_step.response = Some(TxResponse::from_network_tx(tx));

let deploy_address = sc_deploy_step.response().new_deployed_address().unwrap();
let deploy_address = sc_deploy_step.response().new_deployed_address.clone().unwrap();

let set_state_step = SetStateStep::new().new_address(
addr,
Expand Down

0 comments on commit e893b0f

Please sign in to comment.