diff --git a/Cargo.lock b/Cargo.lock index 53eb7f184a..d698d92426 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -255,7 +255,7 @@ dependencies = [ ] [[package]] -name = "basic-interact" +name = "basic-interactor" version = "0.0.0" dependencies = [ "adder", diff --git a/Cargo.toml b/Cargo.toml index 216e8f344a..3cc34e3bd4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ members = [ "contracts/examples/adder", "contracts/examples/adder/meta", - "contracts/examples/adder/interact", + "contracts/examples/adder/interactor", "contracts/examples/esdt-transfer-with-fee", "contracts/examples/esdt-transfer-with-fee/meta", "contracts/examples/bonding-curve-contract", diff --git a/contracts/examples/adder/interact/adder-owner.pem b/contracts/examples/adder/interact/adder-owner.pem deleted file mode 100644 index 66f04c2160..0000000000 --- a/contracts/examples/adder/interact/adder-owner.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PRIVATE KEY for erd1s0a83vp2wmsvgphplkn8amkn8tnfd777zlut3e2lazgdzdu6z46qpgx3vz----- -MWIyYTQ3ZmIzMzcxODUxZTE3Njk5N2M0NTNmZDY1ODFkM2U5NjlhYmM1ODMzMTI0 -MjNkYzAyNGI3YzZlNmVlNjgzZmE3OGIwMmE3NmUwYzQwNmUxZmRhNjdlZWVkMzNh -ZTY5NmZiZGUxN2Y4YjhlNTVmZTg5MGQxMzc5YTE1NzQ= ------END PRIVATE KEY for erd1s0a83vp2wmsvgphplkn8amkn8tnfd777zlut3e2lazgdzdu6z46qpgx3vz----- \ No newline at end of file diff --git a/contracts/examples/adder/interact/alice.json b/contracts/examples/adder/interact/alice.json deleted file mode 100644 index 8f1a81514e..0000000000 --- a/contracts/examples/adder/interact/alice.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": 4, - "kind": "secretKey", - "id": "f2c5e236-9039-46cd-8df5-1efcd9466ead", - "address": "0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", - "bech32": "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", - "crypto": { - "ciphertext": "45de5198c6c477725abc17d26c6b5fc88b1ff22a67a8c4784b297d426d351cf5c891a4c92d63e04cf23f602f660b7b606ed1c5293c85ff40216d9e53c9a07c23", - "cipherparams": { - "iv": "d6442fb1d4c49106152baeb3c539ed2c" - }, - "cipher": "aes-128-ctr", - "kdf": "scrypt", - "kdfparams": { - "dklen": 32, - "salt": "dd69d88742b9d27a0438a4554d4180b070d9af224ea8ff8225fdf74c8e272adb", - "n": 4096, - "r": 8, - "p": 1 - }, - "mac": "b277984f71d0e9b4a6597911775c0ee6d598002645b29f22021e595c2725d204" - } -} diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs deleted file mode 100644 index 2acff49ecb..0000000000 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ /dev/null @@ -1,275 +0,0 @@ -mod basic_interact_cli; -mod basic_interact_config; -mod basic_interact_state; - -use crate::basic_interact_state::State; -use adder::adder_proxy; -pub use basic_interact_config::Config; -use clap::Parser; - -use multiversx_sc_snippets::imports::*; - -const INTERACTOR_SCENARIO_TRACE_PATH: &str = "interactor_trace.scen.json"; - -const ADDER_CODE_PATH: MxscPath = MxscPath::new("../output/adder.mxsc.json"); - -pub async fn adder_cli() { - env_logger::init(); - - let config = Config::load_config(); - - let mut basic_interact = AdderInteract::init(config).await; - - let cli = basic_interact_cli::InteractCli::parse(); - match &cli.command { - Some(basic_interact_cli::InteractCliCommand::Add(args)) => { - if args.count == 1 { - basic_interact.add(args.value).await; - } else { - basic_interact.multi_add(args.value, args.count).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) => { - let sum = basic_interact.get_sum().await; - println!("sum: {sum}"); - }, - Some(basic_interact_cli::InteractCliCommand::Upgrade(args)) => { - let owner_address = basic_interact.adder_owner_address.clone(); - basic_interact - .upgrade(args.value, &owner_address, None) - .await - }, - None => {}, - } -} - -#[allow(unused)] -pub struct AdderInteract { - pub interactor: Interactor, - pub adder_owner_address: Bech32Address, - pub wallet_address: Bech32Address, - pub state: State, -} - -impl AdderInteract { - pub async fn init(config: Config) -> Self { - let mut interactor = Interactor::new(config.gateway_uri()) - .await - .use_chain_simulator(config.use_chain_simulator()) - .with_tracer(INTERACTOR_SCENARIO_TRACE_PATH) - .await; - - interactor.set_current_dir_from_workspace("contracts/examples/adder/interact"); - - let adder_owner_address = interactor - .register_wallet(Wallet::from_pem_file("adder-owner.pem").unwrap()) - .await; - // PASSWORD: "alice" - // InsertPassword::Plaintext("alice".to_string()) || InsertPassword::StandardInput - let wallet_address = interactor - .register_wallet( - Wallet::from_keystore_secret( - "alice.json", - InsertPassword::Plaintext("alice".to_string()), - ) - .unwrap(), - ) - .await; - - // generate blocks until ESDTSystemSCAddress is enabled - interactor.generate_blocks_until_epoch(1).await.unwrap(); - - Self { - interactor, - adder_owner_address: adder_owner_address.into(), - wallet_address: wallet_address.into(), - state: State::load_state(), - } - } - - pub async fn set_state(&mut self) { - println!("wallet address: {}", self.wallet_address); - self.interactor - .retrieve_account(&self.adder_owner_address) - .await; - self.interactor.retrieve_account(&self.wallet_address).await; - } - - pub async fn deploy(&mut self) { - // warning: multi deploy not yet fully supported - // only works with last deployed address - - self.set_state().await; - - let new_address = self - .interactor - .tx() - .from(&self.adder_owner_address) - .gas(6_000_000) - .typed(adder_proxy::AdderProxy) - .init(0u32) - .code(ADDER_CODE_PATH) - .code_metadata(CodeMetadata::UPGRADEABLE) - .returns(ReturnsNewBech32Address) - .run() - .await; - - println!("new address: {new_address}"); - self.state.set_adder_address(new_address); - } - - pub async fn multi_deploy(&mut self, count: usize) { - 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(ADDER_CODE_PATH) - .gas(6_000_000) - .returns(ReturnsNewBech32Address) - }); - } - - let results = buffer.run().await; - - // warning: multi deploy not yet fully supported - // only works with last deployed address - - for new_address in results { - println!("new address: {new_address}"); - - self.state.set_adder_address(new_address); - } - } - - pub async fn multi_add(&mut self, value: u32, count: usize) { - self.set_state().await; - println!("calling contract {count} times..."); - - let mut buffer = self.interactor.homogenous_call_buffer(); - for _ in 0..count { - buffer.push_tx(|tx| { - tx.from(&self.wallet_address) - .to(self.state.current_adder_address()) - .typed(adder_proxy::AdderProxy) - .add(value) - .returns(ReturnsGasUsed) - .gas(6_000_000) - }); - } - - let gas_used = buffer.run().await; - let gas_used_sum = gas_used.iter().sum::(); - - println!( - "successfully performed add {count} times, total gas used: {}, avg gas used: {}", - gas_used_sum, - gas_used_sum / count as u64 - ); - } - - pub async fn feed_contract_egld(&mut self) { - self.interactor - .tx() - .from(&self.wallet_address) - .to(self.state.current_adder_address()) - .egld(NumExpr("0,050000000000000000")) - .run() - .await; - } - - pub async fn add(&mut self, value: u32) { - self.interactor - .tx() - .from(&self.wallet_address) - .to(self.state.current_adder_address()) - .gas(6_000_000) - .typed(adder_proxy::AdderProxy) - .add(value) - .run() - .await; - - println!("successfully performed add"); - } - - pub async fn get_sum(&mut self) -> RustBigUint { - self.interactor - .query() - .to(self.state.current_adder_address()) - .typed(adder_proxy::AdderProxy) - .sum() - .returns(ReturnsResultUnmanaged) - .run() - .await - } - - pub async fn upgrade( - &mut self, - new_value: u32, - sender: &Bech32Address, - expected_result: Option<(u64, &str)>, - ) { - match expected_result { - Some((code, msg)) => { - let response = self - .interactor - .tx() - .from(sender) - .to(self.state.current_adder_address()) - .gas(6_000_000) - .typed(adder_proxy::AdderProxy) - .upgrade(new_value) - .code_metadata(CodeMetadata::UPGRADEABLE) - .code(ADDER_CODE_PATH) - .returns(ExpectError(code, msg)) - .run() - .await; - - println!("response: {response:?}"); - }, - None => { - self.interactor - .tx() - .from(sender) - .to(self.state.current_adder_address()) - .gas(6_000_000) - .typed(adder_proxy::AdderProxy) - .upgrade(new_value) - .code_metadata(CodeMetadata::UPGRADEABLE) - .code(ADDER_CODE_PATH) - .run() - .await; - - let sum = self - .interactor - .query() - .to(self.state.current_adder_address()) - .typed(adder_proxy::AdderProxy) - .sum() - .returns(ReturnsResultUnmanaged) - .run() - .await; - - assert_eq!(sum, RustBigUint::from(new_value)); - }, - } - } -} diff --git a/contracts/examples/adder/interact/src/basic_interact_main.rs b/contracts/examples/adder/interact/src/basic_interact_main.rs deleted file mode 100644 index 352cdc8e70..0000000000 --- a/contracts/examples/adder/interact/src/basic_interact_main.rs +++ /dev/null @@ -1,6 +0,0 @@ -extern crate basic_interact; - -#[tokio::main] -pub async fn main() { - basic_interact::adder_cli().await; -} diff --git a/contracts/examples/adder/interact/.gitignore b/contracts/examples/adder/interactor/.gitignore similarity index 68% rename from contracts/examples/adder/interact/.gitignore rename to contracts/examples/adder/interactor/.gitignore index 336fa10df0..88af50ac47 100644 --- a/contracts/examples/adder/interact/.gitignore +++ b/contracts/examples/adder/interactor/.gitignore @@ -1,10 +1,5 @@ # Pem files are used for interactions, but shouldn't be committed *.pem -*.json -!adder-owner.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 diff --git a/contracts/examples/adder/interact/Cargo.toml b/contracts/examples/adder/interactor/Cargo.toml similarity index 78% rename from contracts/examples/adder/interact/Cargo.toml rename to contracts/examples/adder/interactor/Cargo.toml index 6403c6683f..7c9459e74f 100644 --- a/contracts/examples/adder/interact/Cargo.toml +++ b/contracts/examples/adder/interactor/Cargo.toml @@ -1,22 +1,16 @@ [package] -name = "basic-interact" +name = "basic-interactor" version = "0.0.0" authors = ["MultiversX "] edition = "2021" publish = false [[bin]] -name = "basic-interact" -path = "src/basic_interact_main.rs" +name = "basic-interactor" +path = "src/basic_interactor_main.rs" [lib] -path = "src/basic_interact.rs" - -[dependencies] -clap = { version = "4.4.7", features = ["derive"] } -serde = { version = "1.0", features = ["derive"] } -toml = "0.8.6" -tokio = { version = "1.24" } +path = "src/basic_interactor.rs" [dependencies.adder] path = ".." @@ -25,5 +19,11 @@ path = ".." version = "0.54.0" path = "../../../../framework/snippets" +[dependencies] +clap = { version = "4.4.7", features = ["derive"] } +serde = { version = "1.0", features = ["derive"] } +toml = "0.8.6" +tokio = { version = "1.24" } + [features] chain-simulator-tests = [] diff --git a/contracts/examples/adder/interact/config.toml b/contracts/examples/adder/interactor/config.toml similarity index 98% rename from contracts/examples/adder/interact/config.toml rename to contracts/examples/adder/interactor/config.toml index c6f9a97a1d..97acd5a5c6 100644 --- a/contracts/examples/adder/interact/config.toml +++ b/contracts/examples/adder/interactor/config.toml @@ -1,5 +1,7 @@ + # chain_type = 'simulator' # gateway_uri = 'http://localhost:8085' chain_type = 'real' gateway_uri = 'https://devnet-gateway.multiversx.com' + diff --git a/contracts/examples/adder/interactor/src/basic_interactor.rs b/contracts/examples/adder/interactor/src/basic_interactor.rs new file mode 100644 index 0000000000..63d71de11a --- /dev/null +++ b/contracts/examples/adder/interactor/src/basic_interactor.rs @@ -0,0 +1,137 @@ +mod basic_interactor_cli; +mod basic_interactor_config; +mod basic_interactor_state; + +use adder::adder_proxy; +pub use basic_interactor_config::Config; +use basic_interactor_state::State; +use clap::Parser; + +use multiversx_sc_snippets::imports::*; + +const ADDER_CODE_PATH: MxscPath = MxscPath::new("../output/adder.mxsc.json"); + +pub async fn adder_cli() { + env_logger::init(); + + let config = Config::load_config(); + + let mut basic_interact = AdderInteract::new(config).await; + + let cli = basic_interactor_cli::InteractCli::parse(); + match &cli.command { + Some(basic_interactor_cli::InteractCliCommand::Deploy) => { + basic_interact.deploy().await; + }, + Some(basic_interactor_cli::InteractCliCommand::Upgrade(args)) => { + let owner_address = basic_interact.adder_owner_address.clone(); + basic_interact + .upgrade(args.value, &owner_address, None) + .await + }, + Some(basic_interactor_cli::InteractCliCommand::Add(args)) => { + basic_interact.add(args.value).await; + }, + Some(basic_interactor_cli::InteractCliCommand::Sum) => { + let sum = basic_interact.get_sum().await; + println!("sum: {sum}"); + }, + None => {}, + } +} + +pub struct AdderInteract { + pub interactor: Interactor, + pub adder_owner_address: Bech32Address, + pub wallet_address: Bech32Address, + pub state: State, +} + +impl AdderInteract { + pub async fn new(config: Config) -> Self { + let mut interactor = Interactor::new(config.gateway_uri()) + .await + .use_chain_simulator(config.use_chain_simulator()); + interactor.set_current_dir_from_workspace("contracts/examples/adder/interactor"); + + let adder_owner_address = interactor.register_wallet(test_wallets::heidi()).await; + let wallet_address = interactor.register_wallet(test_wallets::ivan()).await; + + interactor.generate_blocks_until_epoch(1).await.unwrap(); + + AdderInteract { + interactor, + adder_owner_address: adder_owner_address.into(), + wallet_address: wallet_address.into(), + state: State::load_state(), + } + } + + pub async fn deploy(&mut self) { + let new_address = self + .interactor + .tx() + .from(&self.adder_owner_address.clone()) + .gas(6_000_000) + .typed(adder_proxy::AdderProxy) + .init(0u64) + .code(ADDER_CODE_PATH) + .returns(ReturnsNewBech32Address) + .run() + .await; + + println!("new address: {new_address}"); + self.state.set_adder_address(new_address); + } + + pub async fn upgrade(&mut self, new_value: u32, sender: &Bech32Address, err: Option<&str>) { + let response = self + .interactor + .tx() + .from(sender) + .to(self.state.current_adder_address()) + .gas(6_000_000) + .typed(adder_proxy::AdderProxy) + .upgrade(new_value) + .code(ADDER_CODE_PATH) + .code_metadata(CodeMetadata::UPGRADEABLE) + .returns(ReturnsHandledOrError::new()) + .run() + .await; + + match response { + Ok(_) => { + println!("Contract successfully upgraded."); + }, + Err(tx_err) => { + println!("Contract failed upgrade with error: {}", tx_err.message); + assert_eq!(tx_err.message, err.unwrap_or_default()); + }, + } + } + + pub async fn add(&mut self, value: u32) { + self.interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_adder_address()) + .gas(6_000_000u64) + .typed(adder_proxy::AdderProxy) + .add(value) + .run() + .await; + + println!("Successfully performed add"); + } + + pub async fn get_sum(&mut self) -> RustBigUint { + self.interactor + .query() + .to(self.state.current_adder_address()) + .typed(adder_proxy::AdderProxy) + .sum() + .returns(ReturnsResultUnmanaged) + .run() + .await + } +} diff --git a/contracts/examples/adder/interact/src/basic_interact_cli.rs b/contracts/examples/adder/interactor/src/basic_interactor_cli.rs similarity index 79% rename from contracts/examples/adder/interact/src/basic_interact_cli.rs rename to contracts/examples/adder/interactor/src/basic_interactor_cli.rs index 6766981802..3a4a98e502 100644 --- a/contracts/examples/adder/interact/src/basic_interact_cli.rs +++ b/contracts/examples/adder/interactor/src/basic_interactor_cli.rs @@ -12,18 +12,14 @@ pub struct InteractCli { /// 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, #[command(name = "upgrade", about = "Upgrade contract")] Upgrade(UpgradeArgs), + #[command(name = "sum", about = "Print sum")] + Sum, + #[command(name = "add", about = "Add value")] + Add(AddArgs), } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] @@ -31,10 +27,6 @@ pub struct AddArgs { /// The value to add #[arg(short = 'v', long = "value")] pub value: u32, - - /// Repeat this number of times - #[arg(short = 'c', long = "count", default_value = "1")] - pub count: usize, } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] diff --git a/contracts/examples/adder/interact/src/basic_interact_config.rs b/contracts/examples/adder/interactor/src/basic_interactor_config.rs similarity index 100% rename from contracts/examples/adder/interact/src/basic_interact_config.rs rename to contracts/examples/adder/interactor/src/basic_interactor_config.rs diff --git a/contracts/examples/adder/interactor/src/basic_interactor_main.rs b/contracts/examples/adder/interactor/src/basic_interactor_main.rs new file mode 100644 index 0000000000..72c8291332 --- /dev/null +++ b/contracts/examples/adder/interactor/src/basic_interactor_main.rs @@ -0,0 +1,6 @@ +extern crate basic_interactor; + +#[tokio::main] +pub async fn main() { + basic_interactor::adder_cli().await; +} diff --git a/contracts/examples/adder/interact/src/basic_interact_state.rs b/contracts/examples/adder/interactor/src/basic_interactor_state.rs similarity index 97% rename from contracts/examples/adder/interact/src/basic_interact_state.rs rename to contracts/examples/adder/interactor/src/basic_interactor_state.rs index 41453e36fd..bcab774134 100644 --- a/contracts/examples/adder/interact/src/basic_interact_state.rs +++ b/contracts/examples/adder/interactor/src/basic_interactor_state.rs @@ -8,7 +8,7 @@ use std::{ /// State file const STATE_FILE: &str = "state.toml"; -/// Multisig Interact state +/// Adder Interact state #[derive(Debug, Default, Serialize, Deserialize)] pub struct State { adder_address: Option, diff --git a/contracts/examples/adder/interact/tests/basic_interact_cs_test.rs b/contracts/examples/adder/interactor/tests/basic_interactor_cs_test.rs similarity index 53% rename from contracts/examples/adder/interact/tests/basic_interact_cs_test.rs rename to contracts/examples/adder/interactor/tests/basic_interactor_cs_test.rs index 0418813846..1f07ee4c87 100644 --- a/contracts/examples/adder/interact/tests/basic_interact_cs_test.rs +++ b/contracts/examples/adder/interactor/tests/basic_interactor_cs_test.rs @@ -1,12 +1,9 @@ -use basic_interact::{AdderInteract, Config}; +use basic_interactor::{AdderInteract, Config}; #[tokio::test] #[cfg_attr(not(feature = "chain-simulator-tests"), ignore)] async fn simulator_upgrade_test() { - let mut basic_interact = AdderInteract::init(Config::chain_simulator_config()).await; - let wallet_address = basic_interact.wallet_address.clone(); - let adder_owner_address = basic_interact.adder_owner_address.clone(); - let error_not_owner = (4, "upgrade is allowed only for owner"); + let mut basic_interact = AdderInteract::new(Config::chain_simulator_config()).await; basic_interact.deploy().await; basic_interact.add(1u32).await; @@ -16,18 +13,23 @@ async fn simulator_upgrade_test() { assert_eq!(sum, 1u32.into()); basic_interact - .upgrade(7u32, &adder_owner_address, None) + .upgrade(7u32, &basic_interact.adder_owner_address.clone(), None) .await; // Sum will be the updated value of 7 let sum = basic_interact.get_sum().await; assert_eq!(sum, 7u32.into()); + // Upgrade fails basic_interact - .upgrade(10u32, &wallet_address, Some(error_not_owner)) + .upgrade( + 10u32, + &basic_interact.wallet_address.clone(), + Some("upgrade is allowed only for owner"), + ) .await; - // // Sum will remain 7 + // Sum will remain 7 let sum = basic_interact.get_sum().await; assert_eq!(sum, 7u32.into()); } diff --git a/contracts/examples/adder/mxsc-template.toml b/contracts/examples/adder/mxsc-template.toml index 490557cc50..f6a6bb7815 100644 --- a/contracts/examples/adder/mxsc-template.toml +++ b/contracts/examples/adder/mxsc-template.toml @@ -16,9 +16,10 @@ files_include = [ "README.md", "sc-config.toml", "multiversx.json", - "interact/Cargo.toml", - "interact/config.toml", - "interact/.gitignore", - "interact/src", + "interactor/Cargo.toml", + "interactor/config.toml", + "interactor/.gitignore", + "interactor/src", + "interactor/tests", ] has_interactor = true