Skip to content

Commit

Permalink
scenario test contract added in feature tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mihaicalinluca committed Apr 11, 2024
1 parent 7d9d68e commit 13e283f
Show file tree
Hide file tree
Showing 35 changed files with 1,429 additions and 0 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,7 @@ members = [
"contracts/feature-tests/exchange-features",
"contracts/feature-tests/exchange-features/meta",

"contracts/feature-tests/scenario-tester",
"contracts/feature-tests/scenario-tester/meta"

]
10 changes: 10 additions & 0 deletions contracts/feature-tests/scenario-tester/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Generated by Cargo
# will have compiled files and executables
/target/
*/target/

# The mxpy output
/output*/

# Mandos test trace
trace*.scen.json
17 changes: 17 additions & 0 deletions contracts/feature-tests/scenario-tester/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "scenario_tester"
version = "0.0.0"
authors = ["Andrei Marinica <andrei.marinica@multiversx.com>"]
edition = "2021"
publish = false

[lib]
path = "src/lib.rs"

[dependencies.multiversx-sc]
version = "0.49.0-alpha.2"
path = "../../../framework/base"

[dev-dependencies.multiversx-sc-scenario]
version = "0.49.0-alpha.2"
path = "../../../framework/scenario"
3 changes: 3 additions & 0 deletions contracts/feature-tests/scenario-tester/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Adder

`Adder` is a simple Smart Contract.
8 changes: 8 additions & 0 deletions contracts/feature-tests/scenario-tester/interact/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Pem files are used for interactions, but shouldn't be committed
*.pem

# Temporary storage of deployed contract address, so we can preserve the context between executions.
state.toml

# Trace file of interactor tooling
interactor_trace.scen.json
22 changes: 22 additions & 0 deletions contracts/feature-tests/scenario-tester/interact/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "basic-interact"
version = "0.0.0"
authors = ["Ovidiu Stinga <ovidiu.stinga@multiversx.com>"]
edition = "2021"
publish = false

[[bin]]
name = "basic-interact"
path = "src/basic_interact.rs"

[dependencies]
clap = { version = "4.4.7", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
toml = "0.8.6"

[dependencies.adder]
path = ".."

[dependencies.multiversx-sc-snippets]
version = "0.49.0-alpha.2"
path = "../../../../framework/snippets"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gateway = 'https://devnet-gateway.multiversx.com'
172 changes: 172 additions & 0 deletions contracts/feature-tests/scenario-tester/interact/src/basic_interact.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
mod basic_interact_cli;
mod basic_interact_config;
mod basic_interact_state;

use adder::adder_proxy;
use basic_interact_config::Config;
use basic_interact_state::State;
use clap::Parser;

use multiversx_sc_snippets::imports::*;

const INTERACTOR_SCENARIO_TRACE_PATH: &str = "interactor_trace.scen.json";

#[tokio::main]
async fn main() {
env_logger::init();

let mut basic_interact = AdderInteract::init().await;

let cli = basic_interact_cli::InteractCli::parse();
match &cli.command {
Some(basic_interact_cli::InteractCliCommand::Add(args)) => {
basic_interact.add(args.value).await;
},
Some(basic_interact_cli::InteractCliCommand::Deploy) => {
basic_interact.deploy().await;
},
Some(basic_interact_cli::InteractCliCommand::Feed) => {
basic_interact.feed_contract_egld().await;
},
Some(basic_interact_cli::InteractCliCommand::MultiDeploy(args)) => {
basic_interact.multi_deploy(&args.count).await;
},
Some(basic_interact_cli::InteractCliCommand::Sum) => {
basic_interact.print_sum().await;
},
None => {},
}
}

#[allow(unused)]
struct AdderInteract {
interactor: Interactor,
wallet_address: Bech32Address,
adder_code: BytesValue,
state: State,
}

impl AdderInteract {
async fn init() -> Self {
let config = Config::load_config();
let mut interactor = Interactor::new(config.gateway())
.await
.with_tracer(INTERACTOR_SCENARIO_TRACE_PATH)
.await;
let wallet_address = interactor.register_wallet(test_wallets::mike());
let adder_code = BytesValue::interpret_from(
"mxsc:../output/adder.mxsc.json",
&InterpreterContext::default(),
);

Self {
interactor,
wallet_address: wallet_address.into(),
adder_code,
state: State::load_state(),
}
}

async fn set_state(&mut self) {
println!("wallet address: {}", &self.wallet_address);
let scenario_raw = retrieve_account_as_scenario_set_state(
Config::load_config().gateway().to_string(),
self.wallet_address.to_bech32_string(),
true,
)
.await;

let scenario = Scenario::interpret_from(scenario_raw, &InterpreterContext::default());

self.interactor.pre_runners.run_scenario(&scenario);
self.interactor.post_runners.run_scenario(&scenario);
}

async fn deploy(&mut self) {
self.set_state().await;

let new_address = self
.interactor
.tx()
.from(&self.wallet_address)
.typed(adder_proxy::AdderProxy)
.init(0u32)
.code(&self.adder_code)
.returns(ReturnsNewBech32Address)
.prepare_async()
.run()
.await;

println!("new address: {new_address}");
self.state.set_adder_address(new_address);
}

async fn multi_deploy(&mut self, count: &u8) {
if *count == 0 {
println!("count must be greater than 0");
return;
}

self.set_state().await;
println!("deploying {count} contracts...");

let mut buffer = self.interactor.homogenous_call_buffer();
for _ in 0..*count {
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(ReturnsNewBech32Address)
});
}

let results = buffer.run().await;
for new_address in results {
println!("new address: {new_address}");

self.state.set_adder_address(new_address);
}
}

async fn feed_contract_egld(&mut self) {
self.interactor
.tx()
.from(&self.wallet_address)
.to(self.state.current_adder_address())
.egld(NumExpr("0,050000000000000000"))
.prepare_async()
.run()
.await;
}

async fn add(&mut self, value: u64) {
self.interactor
.tx()
.from(&self.wallet_address)
.to(self.state.current_adder_address())
.typed(adder_proxy::AdderProxy)
.add(value)
.prepare_async()
.run()
.await;

println!("successfully performed add");
}

async fn print_sum(&mut self) {
let sum = self
.interactor
.query()
.to(self.state.current_adder_address())
.typed(adder_proxy::AdderProxy)
.sum()
.returns(ReturnsResultConv::<RustBigUint>::new())
.prepare_async()
.run()
.await;

println!("sum: {sum}");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use clap::{Args, Parser, Subcommand};

/// Adder Interact CLI
#[derive(Default, PartialEq, Eq, Debug, Parser)]
#[command(version, about)]
#[command(propagate_version = true)]
pub struct InteractCli {
#[command(subcommand)]
pub command: Option<InteractCliCommand>,
}

/// Adder Interact CLI Commands
#[derive(Clone, PartialEq, Eq, Debug, Subcommand)]
pub enum InteractCliCommand {
#[command(name = "add", about = "Add value")]
Add(AddArgs),
#[command(name = "deploy", about = "Deploy contract")]
Deploy,
#[command(name = "feed", about = "Feed contract EGLD")]
Feed,
#[command(name = "multi-deploy", about = "Multiple deploy contracts")]
MultiDeploy(MultiDeployArgs),
#[command(name = "sum", about = "Print sum")]
Sum,
}

#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
pub struct AddArgs {
/// The value to add
#[arg(short = 'v', long = "value", verbatim_doc_comment)]
pub value: u64,
}

#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
pub struct MultiDeployArgs {
/// The number of contracts to deploy
#[arg(short = 'c', long = "count", verbatim_doc_comment)]
pub count: u8,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use serde::Deserialize;
use std::io::Read;

/// Config file
const CONFIG_FILE: &str = "config.toml";

/// Adder Interact configuration
#[derive(Debug, Deserialize)]
pub struct Config {
gateway: String,
}

impl Config {
// Deserializes config from file
pub fn load_config() -> Self {
let mut file = std::fs::File::open(CONFIG_FILE).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
toml::from_str(&content).unwrap()
}

// Returns the gateway
pub fn gateway(&self) -> &str {
&self.gateway
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use multiversx_sc_snippets::imports::*;
use serde::{Deserialize, Serialize};
use std::{
io::{Read, Write},
path::Path,
};

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

/// Multisig Interact state
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct State {
adder_address: Option<Bech32Address>,
}

impl State {
// Deserializes state from file
pub fn load_state() -> Self {
if Path::new(STATE_FILE).exists() {
let mut file = std::fs::File::open(STATE_FILE).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
toml::from_str(&content).unwrap()
} else {
Self::default()
}
}

/// Sets the adder address
pub fn set_adder_address(&mut self, address: Bech32Address) {
self.adder_address = Some(address);
}

/// Returns the adder contract
pub fn current_adder_address(&self) -> &Bech32Address {
self.adder_address
.as_ref()
.expect("no known adder contract, deploy first")
}
}

impl Drop for State {
// Serializes state to file
fn drop(&mut self) {
let mut file = std::fs::File::create(STATE_FILE).unwrap();
file.write_all(toml::to_string(self).unwrap().as_bytes())
.unwrap();
}
}
Loading

0 comments on commit 13e283f

Please sign in to comment.