Skip to content

Commit

Permalink
Merge pull request #1533 from multiversx/interactor-multi
Browse files Browse the repository at this point in the history
unified syntax - interactor multi tx
  • Loading branch information
andrei-marinica authored Apr 3, 2024
2 parents 1dccfe4 + 62fafc9 commit 91c3ec0
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 77 deletions.
2 changes: 1 addition & 1 deletion contracts/examples/adder/interact/config.toml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
gateway = 'https://testnet-gateway.multiversx.com'
gateway = 'https://devnet-gateway.multiversx.com'
44 changes: 18 additions & 26 deletions contracts/examples/adder/interact/src/basic_interact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mod basic_interact_cli;
mod basic_interact_config;
mod basic_interact_state;

use adder::{adder_proxy, ProxyTrait};
use adder::adder_proxy;
use basic_interact_config::Config;
use basic_interact_state::State;
use clap::Parser;
Expand All @@ -15,11 +15,11 @@ use multiversx_sc_snippets::{
mandos_system::ScenarioRunner,
num_bigint::BigUint,
scenario_format::interpret_trait::{InterpretableFrom, InterpreterContext},
scenario_model::{BytesValue, ScDeployStep, Scenario},
scenario_model::{BytesValue, Scenario},
standalone::retrieve_account_as_scenario_set_state,
test_wallets, ContractInfo, NumExpr, WithRawTxResponse,
},
tokio, Interactor, InteractorPrepareAsync, StepBuffer,
tokio, Interactor, InteractorPrepareAsync,
};

const INTERACTOR_SCENARIO_TRACE_PATH: &str = "interactor_trace.scen.json";
Expand Down Expand Up @@ -135,33 +135,25 @@ impl AdderInteract {
self.set_state().await;
println!("deploying {count} contracts...");

let mut steps = Vec::new();
let mut buffer = self.interactor.homogenous_call_buffer();
for _ in 0..*count {
let typed_sc_deploy = ScDeployStep::new()
.call(self.state.default_adder().init(0u32))
.from(&self.wallet_address)
.code(&self.adder_code)
.gas_limit("70,000,000");

steps.push(typed_sc_deploy);
buffer.push_tx(|tx| {
tx.from(&self.wallet_address)
.typed(adder_proxy::AdderProxy)
.init(0u32)
.code(&self.adder_code)
.gas(NumExpr("70,000,000"))
.returns(ReturnsNewAddress)
});
}

self.interactor
.multi_sc_exec(StepBuffer::from_sc_deploy_vec(&mut steps))
.await;
let results = buffer.run().await;
for result in results {
let new_address_bech32 = bech32::encode(&result.to_address());
println!("new address: {new_address_bech32}");

for step in steps.iter() {
// warning: multi deploy not yet fully supported
// only works with last deployed address
// will be addressed in future versions
let new_deployed_address = step.response().new_deployed_address.clone();
if let Some(new_address) = new_deployed_address {
let new_address_bech32 = bech32::encode(&new_address);
println!("new address: {new_address_bech32}");
} else {
println!("deploy failed");
return;
}
let new_address_expr = format!("bech32:{new_address_bech32}");
self.state.set_adder_address(&new_address_expr);
}
}

Expand Down
9 changes: 0 additions & 9 deletions contracts/examples/adder/interact/src/basic_interact_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ use std::{
path::Path,
};

/// Default adder address
const DEFAULT_ADDER_ADDRESS: &str =
"0x0000000000000000000000000000000000000000000000000000000000000000";

/// State file
const STATE_FILE: &str = "state.toml";

Expand Down Expand Up @@ -46,11 +42,6 @@ impl State {
.expect("no known adder contract, deploy first"),
)
}

/// Returns the adder contract with default address
pub fn default_adder(&self) -> AdderContract {
AdderContract::new(DEFAULT_ADDER_ADDRESS)
}
}

impl Drop for State {
Expand Down
49 changes: 18 additions & 31 deletions contracts/examples/multisig/interact/src/multisig_interact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,13 @@ impl MultisigInteract {

let board = self.board();

let quorum = Config::load_config().quorum();
let new_address = self
.interactor
.tx()
.from(&self.wallet_address)
.typed(multisig_proxy::MultisigProxy)
.init(&Config::load_config().quorum(), board)
.init(quorum, board)
.code(&self.multisig_code)
.gas(NumExpr("100,000,000"))
.returns(ReturnsNewAddress)
Expand All @@ -189,40 +190,26 @@ impl MultisigInteract {
println!("deploying {count} contracts...");

let board = self.board();
let mut steps = Vec::new();
let quorum = Config::load_config().quorum();
let mut buffer = self.interactor.homogenous_call_buffer();
for _ in 0..*count {
let typed_sc_deploy = ScDeployStep::new()
.call(
self.state
.default_multisig()
.init(Config::load_config().quorum(), board.clone()),
)
.from(&self.wallet_address)
.code(&self.multisig_code)
.gas_limit("70,000,000");

steps.push(typed_sc_deploy);
buffer.push_tx(|tx| {
tx.from(&self.wallet_address)
.typed(multisig_proxy::MultisigProxy)
.init(quorum, board.clone())
.code(&self.multisig_code)
.gas(NumExpr("70,000,000"))
.returns(ReturnsNewAddress)
});
}

self.interactor
.multi_sc_exec(StepBuffer::from_sc_deploy_vec(&mut steps))
.await;
let results = buffer.run().await;
for result in results {
let new_address_bech32 = bech32::encode(&result.to_address());
println!("new address: {new_address_bech32}");

for step in steps.iter() {
// warning: multi deploy not yet fully supported
// only works with last deployed address
// will be addressed in future versions
let new_deployed_address = step.response().new_deployed_address.clone();
if let Some(new_address) = new_deployed_address {
let new_address_bech32 = bech32::encode(&new_address);
println!("new address: {new_address_bech32}");

let new_address_expr = format!("bech32:{new_address_bech32}");
self.state.set_multisig_address(&new_address_expr);
} else {
println!("deploy failed");
return;
}
let new_address_expr = format!("bech32:{new_address_bech32}");
self.state.set_multisig_address(&new_address_expr);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ use std::{
path::Path,
};

/// Default multisig address
const DEFAULT_MULTISIG_ADDRESS: &str =
"0x0000000000000000000000000000000000000000000000000000000000000000";

/// State file
const STATE_FILE: &str = "state.toml";

Expand Down Expand Up @@ -42,11 +38,6 @@ impl State {
pub fn multisig(&self) -> MultisigContract {
MultisigContract::new(self.multisig_address.clone().unwrap())
}

/// Returns the multisig contract with default address
pub fn default_multisig(&self) -> MultisigContract {
MultisigContract::new(DEFAULT_MULTISIG_ADDRESS)
}
}

impl Drop for State {
Expand Down
2 changes: 1 addition & 1 deletion framework/scenario/src/scenario/tx_to_step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ mod tx_to_step_trait;
mod tx_to_step_transfer;

pub use step_annotation::*;
pub use step_wrapper::StepWrapper;
pub use step_wrapper::{StepWithResponse, StepWrapper};
pub use tx_to_step_trait::*;
2 changes: 2 additions & 0 deletions framework/snippets/src/multi.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod homogenous_tx_buffer;
mod interactor_multi_sc_exec;
mod interactor_multi_sc_process;
mod interactor_step;
mod step_buffer;

pub use homogenous_tx_buffer::HomogenousTxBuffer;
pub use interactor_step::InteractorStep;
pub use step_buffer::StepBuffer;
65 changes: 65 additions & 0 deletions framework/snippets/src/multi/homogenous_tx_buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use multiversx_sc_scenario::{
multiversx_sc::{
tuple_util::NestedTupleFlatten,
types::{RHListExec, TxBaseWithEnv},
},
scenario::tx_to_step::{StepWithResponse, StepWrapper, TxToStep},
scenario_model::TxResponse,
ScenarioTxEnvData,
};

use crate::{Interactor, InteractorExecEnv, InteractorStep, StepBuffer};

pub struct HomogenousTxBuffer<'w, Step, RH> {
env: InteractorExecEnv<'w>,
steps: Vec<StepWrapper<ScenarioTxEnvData, Step, RH>>,
}

impl Interactor {
/// Creates a buffer that can hold multiple transactions, and then execute them all at once.
///
/// This buffer holds transactions of the same type (call/deploy) and with identical result handler types.
/// Therefore, after execution, all results will have the same type.
pub fn homogenous_call_buffer<Step, RH>(&mut self) -> HomogenousTxBuffer<'_, Step, RH> {
let data = self.new_env_data();
let env = InteractorExecEnv { world: self, data };
HomogenousTxBuffer {
env,
steps: Vec::new(),
}
}
}

impl<'w, Step, RH> HomogenousTxBuffer<'w, Step, RH>
where
Step: InteractorStep + StepWithResponse,
RH: RHListExec<TxResponse, ScenarioTxEnvData>,
RH::ListReturns: NestedTupleFlatten,
{
pub fn push_tx<Tx, F>(&mut self, f: F) -> &mut Self
where
Tx: TxToStep<Env = ScenarioTxEnvData, Step = Step, RH = RH>,
F: FnOnce(TxBaseWithEnv<ScenarioTxEnvData>) -> Tx,
{
let env = self.env.world.new_env_data();
let tx_base = TxBaseWithEnv::new_with_env(env);
let tx = f(tx_base);

self.steps.push(tx.tx_to_step());

self
}

pub async fn run(mut self) -> Vec<<RH::ListReturns as NestedTupleFlatten>::Unpacked> {
let mut step_buffer = StepBuffer::default();
for step in &mut self.steps {
step_buffer.refs.push(&mut step.step);
}
self.env.world.multi_sc_exec(step_buffer).await;

self.steps
.into_iter()
.map(|step| step.process_result())
.collect()
}
}

0 comments on commit 91c3ec0

Please sign in to comment.