diff --git a/Cargo.lock b/Cargo.lock index 7c3caf656f..5281934ee8 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -2285,6 +2285,20 @@ dependencies = [ "multiversx-sc-meta-lib", ] +[[package]] +name = "lottery-interactor" +version = "0.0.0" +dependencies = [ + "clap", + "lottery-esdt", + "multiversx-sc-snippets", + "serde", + "serde_json", + "serial_test", + "tokio", + "toml", +] + [[package]] name = "managed-map-features" version = "0.0.0" diff --git a/Cargo.toml b/Cargo.toml index c2033d527d..0aebf21812 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,6 +83,7 @@ members = [ "contracts/examples/fractional-nfts/meta", "contracts/examples/lottery-esdt", "contracts/examples/lottery-esdt/meta", + "contracts/examples/lottery-esdt/interactor", "contracts/examples/multisig", "contracts/examples/multisig/meta", "contracts/examples/multisig/interact", diff --git a/contracts/examples/lottery-esdt/interactor/.gitignore b/contracts/examples/lottery-esdt/interactor/.gitignore new file mode 100644 index 0000000000..88af50ac47 --- /dev/null +++ b/contracts/examples/lottery-esdt/interactor/.gitignore @@ -0,0 +1,5 @@ +# 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 diff --git a/contracts/examples/lottery-esdt/interactor/Cargo.toml b/contracts/examples/lottery-esdt/interactor/Cargo.toml new file mode 100644 index 0000000000..dee6f466f5 --- /dev/null +++ b/contracts/examples/lottery-esdt/interactor/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "lottery-interactor" +version = "0.0.0" +authors = ["MultiversX "] +edition = "2021" +publish = false + +[[bin]] +name = "lottery-interactor" +path = "src/lottery_interactor_main.rs" + +[lib] +path = "src/lottery_interactor.rs" + +[dependencies.lottery-esdt] +path = ".." + +[dependencies.multiversx-sc-snippets] +version = "0.56.0" +path = "../../../../framework/snippets" + +[dependencies] +clap = { version = "4.4.7", features = ["derive"] } +serde = { version = "1.0", features = ["derive"] } +toml = "0.8.6" +serde_json = "1.0" +tokio = { version = "1.24" } +serial_test = { version = "3.2.0" } + +[features] +chain-simulator-tests = [] diff --git a/contracts/examples/lottery-esdt/interactor/config.toml b/contracts/examples/lottery-esdt/interactor/config.toml new file mode 100644 index 0000000000..a8e45600b0 --- /dev/null +++ b/contracts/examples/lottery-esdt/interactor/config.toml @@ -0,0 +1,6 @@ + +# chain_type = 'simulator' +# gateway_uri = 'http://localhost:8085' + +chain_type = 'real' +gateway_uri = 'https://devnet-gateway.multiversx.com' diff --git a/contracts/examples/lottery-esdt/interactor/set_state.json b/contracts/examples/lottery-esdt/interactor/set_state.json new file mode 100644 index 0000000000..47bd206b5e --- /dev/null +++ b/contracts/examples/lottery-esdt/interactor/set_state.json @@ -0,0 +1,89 @@ +[ + { + "address": "erd1uv40ahysflse896x4ktnh6ecx43u7cmy9wnxnvcyp7deg299a4sq6vaywa", + "nonce": 6221, + "balance": "37980784869999986", + "pairs": { + "454c524f4e44657364745453542d343265356138": "1209004563918244f40000", + "454c524f4e44657364745453542d393836646663": "12020064", + "454c524f4e4465736474544553542d61366131663601": "080512020001223a080112056d794e46541a20e32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60201e32003a090000000000000002032a0510e2f09003", + "454c524f4e44657364745453542d306632306637": "12020064", + "454c524f4e44657364745453542d656338383735": "12020064", + "454c524f4e4465736474544553542d65373261666101": "080512020001223a080112056d794e46541a200139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1201e32003a09000000000000000203", + "454c524f4e44657364745453542d303362373664": "12020064", + "454c524f4e44726f6c6565736474544553542d396262623231": "0a1545534454526f6c654d6f6469667943726561746f72", + "454c524f4e4465736474544553542d39626262323101": "080512020001223a080112056d794e46541a20e32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed60201e32003a090000000000000002032a0510f9f5ae03", + "454c524f4e44657364745453542d336339363762": "12020064", + "454c524f4e44657364745453542d343562383235": "12020064", + "454c524f4e44657364745453542d363437383930": "1209004563918244f40000", + "454c524f4e4465736474424358535542542d33393264366172": "080112020001", + "454c524f4e44726f6c656573647450544d2d353336666162": "0a1145534454526f6c654e46544372656174650a0f45534454526f6c654e46544275726e", + "454c524f4e44657364744c5453542d346638343965": "1209000de0b6b3a763fc19", + "454c524f4e44657364745453542d353966316165": "1209004563918244f40000", + "454c524f4e44657364745453542d343138613232": "1209004563918244f40000", + "454c524f4e44657364745453542d363434633935": "12020064", + "454c524f4e44657364745453542d633636666535": "1209004563918244f40000", + "454c524f4e44657364745453542d643862306438": "12020064", + "454c524f4e44657364745453542d333639646531": "1209004563918244f40000", + "454c524f4e44657364744c5453542d376266336431": "1209000de0b6b3a763fc19", + "454c524f4e44657364745453542d643964336136": "1209004563918244f40000", + "454c524f4e44657364745453542d393864633566": "1209004563918244f40000", + "454c524f4e4465736474475245454e2d306531363163": "120b00152d02c7e14af67fffdc", + "454c524f4e44657364745453542d353538616434": "12020064", + "454c524f4e44657364745453542d623136363735": "1209004563918244f40000", + "454c524f4e446573647450544d2d35333666616201": "08021202000122ef0108011212546573742d5061696e742d486172766573741a20e32afedc904fe1939746ad973beb383563cf63642ba669b3040f9b9428a5ed6020c4132a2e516d57564239575362674b52655a64615a434344766b454b70705a6b4d696d397563736e7857565041414c6a4374324368747470733a2f2f697066732e696f2f697066732f516d57564239575362674b52655a64615a434344766b454b70705a6b4d696d397563736e7857565041414c6a43743a3d746167733a3b6d657461646174613a516d52635039346b5872357a5a6a52477669376d4a36756e374c7078556859565234523452706963787a67596b74", + "454c524f4e44657364745453542d303637373232": "1209004563918244f40000", + "454c524f4e44657364745453542d396230323030": "1209004563918244f40000", + "454c524f4e44657364745453542d623830663863": "1209004563918244f40000", + "454c524f4e446573647455544b2d313464353764": "120b0001e6ce88d5ebbfd00000", + "454c524f4e44657364745453542d363835303064": "1209004563918244f40000", + "454c524f4e44657364745453542d373639313337": "1209004563918244f40000", + "454c524f4e44657364745453542d613562663131": "12020064", + "454c524f4e44657364745453542d386564363538": "1209004563918244f40000", + "454c524f4e44657364745453542d333331386638": "1209004563918244f40000", + "454c524f4e44657364745745474c442d613238633539": "120900389351ce08f09e12", + "454c524f4e4465736474544553542d393236313861": "1202005a", + "454c524f4e44657364745453542d346634303238": "12020064", + "454c524f4e44726f6c6565736474544553542d613661316636": "0a1545534454526f6c654d6f6469667943726561746f72", + "454c524f4e44657364745453542d346230653865": "1209004563918244f40000", + "454c524f4e44657364745453542d623130616461": "1209004563918244f40000", + "454c524f4e4465736474544553542d326130616532": "12020064", + "454c524f4e446e6f6e636550544d2d353336666162": "01", + "454c524f4e44657364745453542d323833633361": "12020064", + "454c524f4e44657364745453542d633565303835": "1209004563918244f40000", + "454c524f4e44657364745453542d633933336139": "1209004563918244f40000" + }, + "code": "", + "code_hash": "", + "root_hash": "bm7koGXVtATCN5jJdsU2nmEx9MQGQ3Szb9Gq/Yb7Di0=", + "code_metadata": "", + "owner_address": "", + "developer_reward": "0" + }, + { + "address": "erd13x29rvmp4qlgn4emgztd8jgvyzdj0p6vn37tqxas3v9mfhq4dy7shalqrx", + "nonce": 1550, + "balance": "4950745448587014056", + "pairs": { + "454c524f4e446573647445564e544e4f544946592d393634383835": "120b00152d02c7e14af6800000", + "454c524f4e44657364744e4943552d393730323932": "120b00d3c21bcecceda1000000", + "454c524f4e4465736474424358535542542d3339326436616e": "080112020001", + "454c524f4e4465736474494e5445524e532d63393332356601": "0801120b0013097d1fb962e12fff47", + "454c524f4e446573647442534b2d343736343730": "120b00021e19e0c9bab23fff7b", + "454c524f4e44657364744e455453432d623635306261": "120b00d137965aa7a731800000", + "454c524f4e446e6f6e6365494e5445524e532d633933323566": "01", + "454c524f4e44726f6c6565736474494e5445524e532d633933323566": "0a1145534454526f6c654e46544372656174650a1645534454526f6c654e46544164645175616e74697479", + "454c524f4e44657364744e45543253432d306438663962": "120f0004ee2d6d3f3d6bcc25c64dc00000", + "454c524f4e4465736474424358535542542d3339326436616c": "080112020001", + "454c524f4e44657364745745474c442d613238633539": "120800010593b233281b", + "454c524f4e446e6f6e63654d4554414e46542d643062623339": "01", + "454c524f4e44726f6c65657364744d4554414e46542d643062623339": "0a1145534454526f6c654e4654437265617465" + }, + "code": "", + "code_hash": "", + "root_hash": "AJ2jyOcPXgZAl0kHAlbWZIlG3F1VDtcoLAHR6eqehBA=", + "code_metadata": "", + "owner_address": "", + "developer_reward": "0" + } +] \ No newline at end of file diff --git a/contracts/examples/lottery-esdt/interactor/src/lottery_interactor.rs b/contracts/examples/lottery-esdt/interactor/src/lottery_interactor.rs new file mode 100644 index 0000000000..869804defd --- /dev/null +++ b/contracts/examples/lottery-esdt/interactor/src/lottery_interactor.rs @@ -0,0 +1,234 @@ +mod lottery_interactor_cli; +mod lottery_interactor_config; +mod lottery_interactor_state; + +use clap::Parser; +use lottery_esdt::lottery_proxy; +pub use lottery_interactor_config::Config; +use lottery_interactor_state::State; +use num_bigint::BigUint; + +use multiversx_sc_snippets::imports::*; + +const LOTTERY_CODE_PATH: MxscPath = MxscPath::new("../output/lottery-esdt.mxsc.json"); + +pub async fn lottery_cli() { + env_logger::init(); + + let config = Config::load_config(); + + let mut lottery_interact = LotteryInteract::new(config).await; + + let cli = lottery_interactor_cli::InteractCli::parse(); + match &cli.command { + Some(lottery_interactor_cli::InteractCliCommand::Deploy) => { + lottery_interact.deploy().await; + }, + Some(lottery_interactor_cli::InteractCliCommand::CreateLotteryPool(args)) => { + lottery_interact + .create_lottery_pool( + &args.lottery_name, + TokenIdentifier::from(&args.token_identifier), + args.ticket_price.clone(), + args.opt_total_tickets, + args.opt_deadline, + args.opt_max_entries_per_user, + args.opt_prize_distribution.clone(), + args.get_opt_whitelist_arg(), + OptionalValue::from(args.opt_burn_percentage.clone()), + ) + .await; + }, + Some(lottery_interactor_cli::InteractCliCommand::BuyTicket(args)) => { + lottery_interact.buy_ticket(&args.name).await; + }, + Some(lottery_interactor_cli::InteractCliCommand::DetermineWinner(args)) => { + lottery_interact.determine_winner(&args.name).await; + }, + Some(lottery_interactor_cli::InteractCliCommand::ClaimRewards(args)) => { + lottery_interact + .claim_rewards( + args.tokens + .iter() + .map(|token| TokenIdentifier::from(token)) + .collect(), + ) + .await; + }, + None => {}, + } +} + +#[derive(Clone)] +pub struct AddressWithShard { + pub address: Bech32Address, + pub shard: u8, +} + +pub struct LotteryInteract { + pub interactor: Interactor, + pub lottery_owner: AddressWithShard, + pub account_1: AddressWithShard, + pub account_2: AddressWithShard, + pub other_shard_account: AddressWithShard, + pub state: State, +} + +impl LotteryInteract { + 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/lottery-esdt/interactor"); + + let lottery_owner_wallet = test_wallets::heidi(); // shard 1 + let account_1_wallet = test_wallets::alice(); // shard 0 + let account_2_wallet = test_wallets::bob(); // shard 2 + let other_shard_wallet = test_wallets::carol(); // shard 0 + + let lottery_owner_address = interactor.register_wallet(lottery_owner_wallet).await; + let account_1_address = interactor.register_wallet(account_1_wallet).await; + let account_2_address = interactor.register_wallet(account_2_wallet).await; + let other_shard_address = interactor.register_wallet(other_shard_wallet).await; + + interactor.generate_blocks(30u64).await.unwrap(); + + LotteryInteract { + interactor, + lottery_owner: AddressWithShard { + address: lottery_owner_address.clone().into(), + shard: lottery_owner_wallet.get_shard(), + }, + account_1: AddressWithShard { + address: account_1_address.into(), + shard: account_1_wallet.get_shard(), + }, + account_2: AddressWithShard { + address: account_2_address.into(), + shard: account_2_wallet.get_shard(), + }, + other_shard_account: AddressWithShard { + address: other_shard_address.into(), + shard: other_shard_wallet.get_shard(), + }, + state: State::load_state(), + } + } + + pub async fn deploy(&mut self) { + let (new_address, shard) = self.handle_different_shard_address().await; + println!("new address: {new_address} on shard {shard}"); + self.state.set_lottery_address(new_address); + } + + async fn handle_different_shard_address(&mut self) -> (Bech32Address, u32) { + let (new_address, tx_hash) = self + .interactor + .tx() + .from(&self.lottery_owner.address) + .gas(50_000_000) + .typed(lottery_proxy::LotteryProxy) + .init() + .code(LOTTERY_CODE_PATH) + .returns(ReturnsNewBech32Address) + .returns(ReturnsTxHash) + .run() + .await; + + /* let tx_hash_string = String::from_utf8(tx_hash.to_vec()).unwrap(); + let tx_on_network = self + .interactor + .proxy + .get_transaction_info_with_results(&tx_hash_string) + .await + .unwrap(); + let shard = tx_on_network.destination_shard; + + if self.other_shard_account.shard as u32 == shard { + // we want to have other_shard_account on another shard than the SC + let buffer_address_with_shard = self.other_shard_account.clone(); + self.other_shard_account = self.account_2.clone(); + self.account_2 = buffer_address_with_shard; + }*/ + + return (new_address, 0); + } + + pub async fn create_lottery_pool( + &mut self, + lottery_name: &String, + token_identifier: TokenIdentifier, + ticket_price: BigUint, + opt_total_tickets: Option, + opt_deadline: Option, + opt_max_entries_per_user: Option, + opt_prize_distribution: Option>, + opt_whitelist: Option>, + opt_burn_percentage: OptionalValue, + ) { + self.interactor + .tx() + .from(&self.account_1.address) + .to(self.state.current_lottery_address()) + .gas(6_000_000u64) + .typed(lottery_proxy::LotteryProxy) + .create_lottery_pool( + lottery_name, + token_identifier, + ticket_price, + opt_total_tickets, + opt_deadline, + opt_max_entries_per_user, + opt_prize_distribution, + opt_whitelist, + opt_burn_percentage, + ) + .run() + .await; + + println!("Successfully performed create_lottery_poll"); + } + + pub async fn buy_ticket(&mut self, lottery_name: &String) { + self.interactor + .tx() + .from(&self.account_1.address) + .to(self.state.current_lottery_address()) + .gas(6_000_000u64) + .typed(lottery_proxy::LotteryProxy) + .buy_ticket(lottery_name) + .run() + .await; + + println!("Successfully performed buy_ticket"); + } + + pub async fn determine_winner(&mut self, lottery_name: &String) { + self.interactor + .tx() + .from(&self.account_1.address) + .to(self.state.current_lottery_address()) + .gas(6_000_000u64) + .typed(lottery_proxy::LotteryProxy) + .determine_winner(lottery_name) + .run() + .await; + println!("Successfully performed determine_winner"); + } + + pub async fn claim_rewards( + &mut self, + tokens: MultiValueEncoded>, + ) { + self.interactor + .tx() + .from(&self.account_1.address) + .to(self.state.current_lottery_address()) + .gas(6_000_000u64) + .typed(lottery_proxy::LotteryProxy) + .claim_rewards(tokens) + .run() + .await; + println!("Successfully performed claim_rewards"); + } +} diff --git a/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_cli.rs b/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_cli.rs new file mode 100644 index 0000000000..cb05e854ca --- /dev/null +++ b/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_cli.rs @@ -0,0 +1,78 @@ +use clap::{Args, Parser, Subcommand}; +use multiversx_sc_snippets::imports::{Address, RustBigUint}; + +/// Lottery Interact CLI +#[derive(Default, PartialEq, Eq, Debug, Parser)] +#[command(version, about)] +#[command(propagate_version = true)] +pub struct InteractCli { + #[command(subcommand)] + pub command: Option, +} + +/// Lottery Interact CLI Commands +#[derive(Clone, PartialEq, Eq, Debug, Subcommand)] +pub enum InteractCliCommand { + #[command(name = "deploy", about = "Deploy contract")] + Deploy, + #[command(name = "create_lottery_pool", about = "Create Lottery Pool")] + CreateLotteryPool(CreateLotteryPollArgs), + #[command(name = "buy_ticket", about = "Buy Ticket")] + BuyTicket(LotteryNameArg), + #[command(name = "determine_winner", about = "Determine Winner")] + DetermineWinner(LotteryNameArg), + #[command(name = "claim_rewards", about = "Claim Rewards")] + ClaimRewards(ClaimRewardsArg), +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct CreateLotteryPollArgs { + /// The value to add + #[arg(short = 'n', long = "name")] + pub lottery_name: String, + #[arg(short = 'n', long = "name")] + pub token_identifier: String, + #[arg(short = 'n', long = "name")] + pub ticket_price: RustBigUint, + #[arg(short = 'n', long = "name")] + pub opt_total_tickets: Option, + #[arg(short = 'n', long = "name")] + pub opt_deadline: Option, + #[arg(short = 'n', long = "name")] + pub opt_max_entries_per_user: Option, + #[arg(short = 'n', long = "name")] + pub opt_prize_distribution: Option>, + #[arg(short = 'n', long = "name")] + pub opt_whitelist: Option>, + #[arg(short = 'n', long = "name")] + pub opt_burn_percentage: Option, +} + +impl CreateLotteryPollArgs { + pub fn get_opt_whitelist_arg(&self) -> Option> { + let mut opt_whitelist_with_addresses = Vec::new(); + if self.opt_whitelist.is_none() { + return Option::None; + } + + for str_address in self.opt_whitelist.as_ref().unwrap() { + opt_whitelist_with_addresses.push(Address::from_slice(str_address.as_bytes())); + } + + return Some(opt_whitelist_with_addresses); + } +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct LotteryNameArg { + /// The name of the lottery + #[arg(short = 'n', long = "name")] + pub name: String, +} + +#[derive(Default, Clone, PartialEq, Eq, Debug, Args)] +pub struct ClaimRewardsArg { + /// The name of the lottery + #[arg(short = 'n', long = "name")] + pub tokens: Vec, +} diff --git a/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_config.rs b/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_config.rs new file mode 100644 index 0000000000..c891d2d1d4 --- /dev/null +++ b/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_config.rs @@ -0,0 +1,50 @@ +use serde::Deserialize; +use std::io::Read; + +/// Config file +const CONFIG_FILE: &str = "config.toml"; +pub const CHAIN_SIMULATOR_GATEWAY: &str = "http://localhost:8085"; + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ChainType { + Real, + Simulator, +} + +/// Lottery Interact configuration +#[derive(Debug, Deserialize)] +pub struct Config { + pub gateway_uri: String, + pub chain_type: ChainType, +} + +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() + } + + pub fn chain_simulator_config() -> Self { + Config { + gateway_uri: CHAIN_SIMULATOR_GATEWAY.to_owned(), + chain_type: ChainType::Simulator, + } + } + + // Returns the gateway URI + pub fn gateway_uri(&self) -> &str { + &self.gateway_uri + } + + // Returns if chain type is chain simulator + pub fn use_chain_simulator(&self) -> bool { + match self.chain_type { + ChainType::Real => false, + ChainType::Simulator => true, + } + } +} diff --git a/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_main.rs b/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_main.rs new file mode 100644 index 0000000000..cda0392531 --- /dev/null +++ b/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_main.rs @@ -0,0 +1,6 @@ +extern crate lottery_interactor; + +#[tokio::main] +pub async fn main() { + lottery_interactor::lottery_cli().await; +} diff --git a/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_state.rs b/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_state.rs new file mode 100644 index 0000000000..a49256abde --- /dev/null +++ b/contracts/examples/lottery-esdt/interactor/src/lottery_interactor_state.rs @@ -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"; + +/// Lottery Interact state +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct State { + lottery_address: Option, +} + +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 lottery address + pub fn set_lottery_address(&mut self, address: Bech32Address) { + self.lottery_address = Some(address); + } + + /// Returns the lottery contract + pub fn current_lottery_address(&self) -> &Bech32Address { + self.lottery_address + .as_ref() + .expect("no known lottery 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(); + } +} diff --git a/contracts/examples/lottery-esdt/interactor/tests/lottery_interactor_cs_test.rs b/contracts/examples/lottery-esdt/interactor/tests/lottery_interactor_cs_test.rs new file mode 100644 index 0000000000..d09f8a3e37 --- /dev/null +++ b/contracts/examples/lottery-esdt/interactor/tests/lottery_interactor_cs_test.rs @@ -0,0 +1,44 @@ +use lottery_interactor::{Config, LotteryInteract}; +use multiversx_sc_snippets::{ + imports::{num_bigint, GatewayHttpProxy, OptionalValue}, + sdk::gateway::NetworkStatusRequest, +}; +use num_bigint::BigUint; +use serial_test::serial; + +pub const CHAIN_SIMULATOR_GATEWAY: &str = "http://localhost:8085"; +const TEN_MINUTES_IN_SECONDS: u64 = 60 * 10; + +#[tokio::test] +#[serial] +#[cfg_attr(not(feature = "chain-simulator-tests"), ignore)] +async fn set_state_from_file_cs_test() { + let mut interact = LotteryInteract::new(Config::chain_simulator_config()).await; + + interact.deploy().await; + /* let current_timestamp = get_current_timestamp().await; + + interact + .create_lottery_pool( + &"lottery_name".to_string(), + "LOTTERY-123456".into(), + BigUint::from(100u64), + None, + Some(current_timestamp + TEN_MINUTES_IN_SECONDS), + None, + None, + None, + OptionalValue::None, + ) + .await;*/ +} + +async fn get_current_timestamp() -> u64 { + let blockchain = GatewayHttpProxy::new(CHAIN_SIMULATOR_GATEWAY.to_string()); + + let network_config = blockchain + .http_request(NetworkStatusRequest::default()) + .await + .unwrap(); + network_config.current_block_timestamp +} diff --git a/contracts/examples/lottery-esdt/src/lottery.rs b/contracts/examples/lottery-esdt/src/lottery.rs index 4db0845d62..2461941c2c 100644 --- a/contracts/examples/lottery-esdt/src/lottery.rs +++ b/contracts/examples/lottery-esdt/src/lottery.rs @@ -25,4 +25,7 @@ pub trait Lottery: { #[init] fn init(&self) {} + + #[upgrade] + fn upgrade(&self) {} } diff --git a/contracts/examples/lottery-esdt/src/lottery_proxy.rs b/contracts/examples/lottery-esdt/src/lottery_proxy.rs index 9825cd83ca..bde1abb0fc 100644 --- a/contracts/examples/lottery-esdt/src/lottery_proxy.rs +++ b/contracts/examples/lottery-esdt/src/lottery_proxy.rs @@ -53,6 +53,25 @@ where } } +#[rustfmt::skip] +impl LotteryProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn upgrade( + self, + ) -> TxTypedUpgrade { + self.wrapped_tx + .payment(NotPayable) + .raw_upgrade() + .original_result() + } +} + #[rustfmt::skip] impl LotteryProxyMethods where diff --git a/contracts/examples/lottery-esdt/wasm/src/lib.rs b/contracts/examples/lottery-esdt/wasm/src/lib.rs index 468182c673..49138904dd 100644 --- a/contracts/examples/lottery-esdt/wasm/src/lib.rs +++ b/contracts/examples/lottery-esdt/wasm/src/lib.rs @@ -5,9 +5,10 @@ //////////////////////////////////////////////////// // Init: 1 +// Upgrade: 1 // Endpoints: 7 // Async Callback (empty): 1 -// Total number of exported functions: 9 +// Total number of exported functions: 10 #![no_std] @@ -18,6 +19,7 @@ multiversx_sc_wasm_adapter::endpoints! { lottery_esdt ( init => init + upgrade => upgrade determine_winner => determine_winner status => status getLotteryInfo => lottery_info