diff --git a/contracts/examples/adder/interact/config.toml b/contracts/examples/adder/interact/config.toml index 61ac8dbf87..64846243cc 100644 --- a/contracts/examples/adder/interact/config.toml +++ b/contracts/examples/adder/interact/config.toml @@ -1 +1,2 @@ -gateway = 'https://devnet-gateway.multiversx.com' +chain_type = 'simulator' +gateway_uri = 'http://localhost:8085' diff --git a/contracts/examples/adder/interact/src/basic_interact.rs b/contracts/examples/adder/interact/src/basic_interact.rs index 454060eb0d..7042df9781 100644 --- a/contracts/examples/adder/interact/src/basic_interact.rs +++ b/contracts/examples/adder/interact/src/basic_interact.rs @@ -2,6 +2,8 @@ mod basic_interact_cli; mod basic_interact_config; mod basic_interact_state; +use core::str; + use adder::adder_proxy; use basic_interact_config::Config; use basic_interact_state::State; @@ -61,22 +63,27 @@ struct AdderInteract { impl AdderInteract { async fn init() -> Self { let config = Config::load_config(); - let mut interactor = Interactor::new(config.gateway()) + let mut interactor = Interactor::new(config.gateway_uri(), config.use_chain_simulator()) .await .with_tracer(INTERACTOR_SCENARIO_TRACE_PATH) .await; - let adder_owner_address = - interactor.register_wallet(Wallet::from_pem_file("adder-owner.pem").unwrap()); + 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()), + let wallet_address = interactor + .register_wallet( + Wallet::from_keystore_secret( + "alice.json", + InsertPassword::Plaintext("alice".to_string()), + ) + .unwrap(), ) - .unwrap(), - ); + .await; + + interactor.proxy.generate_blocks(1).await.unwrap(); Self { interactor, diff --git a/contracts/examples/adder/interact/src/basic_interact_config.rs b/contracts/examples/adder/interact/src/basic_interact_config.rs index e17d0cbe65..edd4ba6b1e 100644 --- a/contracts/examples/adder/interact/src/basic_interact_config.rs +++ b/contracts/examples/adder/interact/src/basic_interact_config.rs @@ -4,10 +4,18 @@ use std::io::Read; /// Config file const CONFIG_FILE: &str = "config.toml"; +#[derive(Debug, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ChainType { + Real, + Simulator, +} + /// Adder Interact configuration #[derive(Debug, Deserialize)] pub struct Config { - gateway: String, + gateway_uri: String, + chain_type: ChainType, } impl Config { @@ -19,8 +27,16 @@ impl Config { toml::from_str(&content).unwrap() } - // Returns the gateway - pub fn gateway(&self) -> &str { - &self.gateway + // 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/multisig/interact/config.toml b/contracts/examples/multisig/interact/config.toml index 029fab5ac7..148ebb5803 100644 --- a/contracts/examples/multisig/interact/config.toml +++ b/contracts/examples/multisig/interact/config.toml @@ -1,3 +1,4 @@ -gateway = 'https://devnet-gateway.multiversx.com' +chain_type = 'real' +gateway_uri = 'https://devnet-gateway.multiversx.com' quorum = 2 wegld_address = "erd1qqqqqqqqqqqqqpgqqkwzsxkjc83vlfex9dmznwm7tjvxlqqkpauqx0n782" diff --git a/contracts/examples/multisig/interact/src/multisig_interact.rs b/contracts/examples/multisig/interact/src/multisig_interact.rs index 497b6636dd..0701841b6a 100644 --- a/contracts/examples/multisig/interact/src/multisig_interact.rs +++ b/contracts/examples/multisig/interact/src/multisig_interact.rs @@ -19,7 +19,7 @@ async fn main() { env_logger::init(); let mut multisig_interact = MultisigInteract::init().await; - multisig_interact.register_wallets(); + multisig_interact.register_wallets().await; let cli = multisig_interact_cli::InteractCli::parse(); match &cli.command { @@ -86,11 +86,11 @@ struct MultisigInteract { impl MultisigInteract { async fn init() -> Self { let config = Config::load_config(); - let mut interactor = Interactor::new(&config.gateway) + let mut interactor = Interactor::new(config.gateway_uri(), config.use_chain_simulator()) .await .with_tracer(INTERACTOR_SCENARIO_TRACE_PATH) .await; - let wallet_address = interactor.register_wallet(test_wallets::mike()); + let wallet_address = interactor.register_wallet(test_wallets::mike()).await; let multisig_code = BytesValue::interpret_from( "mxsc:../output/multisig.mxsc.json", &InterpreterContext::default(), @@ -106,13 +106,13 @@ impl MultisigInteract { } } - fn register_wallets(&mut self) { + async fn register_wallets(&mut self) { let carol = test_wallets::carol(); let dan = test_wallets::dan(); let eve = test_wallets::eve(); for wallet in &[carol, dan, eve] { - self.interactor.register_wallet(*wallet); + self.interactor.register_wallet(*wallet).await; } } diff --git a/contracts/examples/multisig/interact/src/multisig_interact_config.rs b/contracts/examples/multisig/interact/src/multisig_interact_config.rs index 4aa9903cc0..c11c2c447f 100644 --- a/contracts/examples/multisig/interact/src/multisig_interact_config.rs +++ b/contracts/examples/multisig/interact/src/multisig_interact_config.rs @@ -5,10 +5,18 @@ use std::io::Read; /// Config file const CONFIG_FILE: &str = "config.toml"; +#[derive(Debug, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ChainType { + Real, + Simulator, +} + /// Multisig Interact configuration #[derive(Debug, Deserialize)] pub struct Config { - pub gateway: String, + pub gateway_uri: String, + pub chain_type: ChainType, pub quorum: usize, pub wegld_address: Bech32Address, } @@ -21,4 +29,17 @@ impl Config { file.read_to_string(&mut content).unwrap(); toml::from_str(&content).unwrap() } + + // 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/feature-tests/basic-features/interact/config.toml b/contracts/feature-tests/basic-features/interact/config.toml index 61ac8dbf87..dfc1ba62a6 100644 --- a/contracts/feature-tests/basic-features/interact/config.toml +++ b/contracts/feature-tests/basic-features/interact/config.toml @@ -1 +1,2 @@ -gateway = 'https://devnet-gateway.multiversx.com' +chain_type = 'real' +gateway_uri = 'https://devnet-gateway.multiversx.com' diff --git a/contracts/feature-tests/basic-features/interact/src/bf_interact.rs b/contracts/feature-tests/basic-features/interact/src/bf_interact.rs index e8f269cb71..b971818f2b 100644 --- a/contracts/feature-tests/basic-features/interact/src/bf_interact.rs +++ b/contracts/feature-tests/basic-features/interact/src/bf_interact.rs @@ -41,11 +41,11 @@ struct BasicFeaturesInteract { impl BasicFeaturesInteract { async fn init() -> Self { let config = Config::load_config(); - let mut interactor = Interactor::new(config.gateway()) + let mut interactor = Interactor::new(config.gateway_uri(), config.use_chain_simulator()) .await .with_tracer(INTERACTOR_SCENARIO_TRACE_PATH) .await; - let wallet_address = interactor.register_wallet(test_wallets::mike()); + let wallet_address = interactor.register_wallet(test_wallets::mike()).await; let code_expr = BytesValue::interpret_from( "mxsc:../output/basic-features-storage-bytes.mxsc.json", &InterpreterContext::default(), diff --git a/contracts/feature-tests/basic-features/interact/src/bf_interact_config.rs b/contracts/feature-tests/basic-features/interact/src/bf_interact_config.rs index e17d0cbe65..edd4ba6b1e 100644 --- a/contracts/feature-tests/basic-features/interact/src/bf_interact_config.rs +++ b/contracts/feature-tests/basic-features/interact/src/bf_interact_config.rs @@ -4,10 +4,18 @@ use std::io::Read; /// Config file const CONFIG_FILE: &str = "config.toml"; +#[derive(Debug, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ChainType { + Real, + Simulator, +} + /// Adder Interact configuration #[derive(Debug, Deserialize)] pub struct Config { - gateway: String, + gateway_uri: String, + chain_type: ChainType, } impl Config { @@ -19,8 +27,16 @@ impl Config { toml::from_str(&content).unwrap() } - // Returns the gateway - pub fn gateway(&self) -> &str { - &self.gateway + // 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/feature-tests/composability/interact/config.toml b/contracts/feature-tests/composability/interact/config.toml index accfdf2fa5..992112c225 100644 --- a/contracts/feature-tests/composability/interact/config.toml +++ b/contracts/feature-tests/composability/interact/config.toml @@ -1,6 +1,7 @@ -gateway = 'https://testnet-gateway.multiversx.com' -call_type = "LegacyAsync" # Sync / LegacyAsync / TransferExecute +chain_type = 'real' +gateway_uri = 'https://testnet-gateway.multiversx.com' +call_type = "LegacyAsync" # Sync / LegacyAsync / TransferExecute # token_id = "CMPT-4e9332" token_id = "EGLD" -token_nonce = 0 # is 0 if fungible -amount = '50000000000000000' \ No newline at end of file +token_nonce = 0 # is 0 if fungible +amount = '50000000000000000' diff --git a/contracts/feature-tests/composability/interact/src/comp_interact_config.rs b/contracts/feature-tests/composability/interact/src/comp_interact_config.rs index d09c2323f7..cffff8e915 100644 --- a/contracts/feature-tests/composability/interact/src/comp_interact_config.rs +++ b/contracts/feature-tests/composability/interact/src/comp_interact_config.rs @@ -8,10 +8,18 @@ use crate::forwarder_queue_proxy::QueuedCallType; /// Config file const CONFIG_FILE: &str = "config.toml"; +#[derive(Debug, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ChainType { + Real, + Simulator, +} + /// Multisig Interact configuration #[derive(Debug, Deserialize)] pub struct Config { - gateway: String, + gateway_uri: String, + chain_type: ChainType, call_type: String, token_id: String, token_nonce: u64, @@ -27,9 +35,17 @@ impl Config { toml::from_str(&content).unwrap() } - // Returns the gateway - pub fn gateway(&self) -> &str { - &self.gateway + // 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, + } } pub fn call_type(&self) -> QueuedCallType { diff --git a/contracts/feature-tests/composability/interact/src/comp_interact_controller.rs b/contracts/feature-tests/composability/interact/src/comp_interact_controller.rs index 1c2457494b..e486c6d522 100644 --- a/contracts/feature-tests/composability/interact/src/comp_interact_controller.rs +++ b/contracts/feature-tests/composability/interact/src/comp_interact_controller.rs @@ -16,11 +16,11 @@ pub struct ComposabilityInteract { impl ComposabilityInteract { pub async fn init() -> Self { let config = Config::load_config(); - let mut interactor = Interactor::new(config.gateway()) + let mut interactor = Interactor::new(config.gateway_uri(), config.use_chain_simulator()) .await .with_tracer(INTERACTOR_SCENARIO_TRACE_PATH) .await; - let wallet_address = interactor.register_wallet(test_wallets::judy()); + let wallet_address = interactor.register_wallet(test_wallets::judy()).await; let forw_queue_code = BytesValue::interpret_from( "mxsc:../forwarder-queue/output/forwarder-queue.mxsc.json", &InterpreterContext::default(), diff --git a/framework/meta/src/cli/cli_args_standalone.rs b/framework/meta/src/cli/cli_args_standalone.rs index ce2c3b66a6..28b47d51e1 100644 --- a/framework/meta/src/cli/cli_args_standalone.rs +++ b/framework/meta/src/cli/cli_args_standalone.rs @@ -408,11 +408,19 @@ pub struct InstallWasmOptArgs {} #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] pub struct AccountArgs { - /// Provide the target API you want the real data to come from + /// Provide the target API you want the data to come from #[arg(long = "api")] #[clap(global = true)] pub api: Option, + /// Provide if the API is a chain simulator or not + #[arg( + long = "chain-simulator", + default_value = "false", + verbatim_doc_comment + )] + pub chain_simulator: Option, + /// Provide the address you want to retrieve data from #[arg(long = "address", verbatim_doc_comment)] pub address: String, diff --git a/framework/meta/src/cmd/retrieve_address.rs b/framework/meta/src/cmd/retrieve_address.rs index f20b5b8e05..15335408ef 100644 --- a/framework/meta/src/cmd/retrieve_address.rs +++ b/framework/meta/src/cmd/retrieve_address.rs @@ -5,5 +5,11 @@ use crate::cli::AccountArgs; /// Interprets arguments and call the account tool from `multiversx_sc_snippets`. pub async fn retrieve_address(args: &AccountArgs) { let api_string = args.api.clone().expect("API needs to be specified"); - account_tool::print_account_as_scenario_set_state(api_string, args.address.to_string()).await; + let use_chain_simulator = args.chain_simulator.unwrap_or_default(); + account_tool::print_account_as_scenario_set_state( + api_string, + use_chain_simulator, + args.address.to_string(), + ) + .await; } diff --git a/framework/snippets/src/account_tool.rs b/framework/snippets/src/account_tool.rs index b10baf4a80..3370fc738e 100644 --- a/framework/snippets/src/account_tool.rs +++ b/framework/snippets/src/account_tool.rs @@ -15,9 +15,10 @@ use std::collections::{BTreeMap, HashMap}; /// then formats it as a scenario set state step. pub async fn print_account_as_scenario_set_state( api_string: String, + use_chain_simulator: bool, address_bech32_string: String, ) { - let api = GatewayProxy::new(api_string); + let api = GatewayProxy::new(api_string, use_chain_simulator); let address = Bech32Address::from_bech32_string(address_bech32_string); let set_state = retrieve_account_as_scenario_set_state(&api, &address).await; let scenario = build_scenario(set_state); @@ -40,20 +41,30 @@ pub async fn retrieve_account_as_scenario_set_state( let sdk_address = Address::from_bech32_string(address.to_bech32_str()).unwrap(); let sdk_account = api.get_account(&sdk_address).await.unwrap(); - let account_esdt = api - .get_account_esdt_tokens(&sdk_address) - .await - .unwrap_or_else(|err| { - panic!("failed to retrieve ESDT tokens for address {address}: {err}") - }); - let account_esdt_roles = api - .get_account_esdt_roles(&sdk_address) - .await - .unwrap_or_else(|err| panic!("failed to retrieve ESDT roles for address {address}: {err}")); - let account_storage = api - .get_account_storage_keys(&sdk_address) - .await - .unwrap_or_else(|err| panic!("failed to retrieve storage for address {address}: {err}")); + let (account_esdt, account_esdt_roles, account_storage) = if api.chain_simulator { + (HashMap::new(), HashMap::new(), HashMap::new()) + } else { + let account_esdt = api + .get_account_esdt_tokens(&sdk_address) + .await + .unwrap_or_else(|err| { + panic!("failed to retrieve ESDT tokens for address {address}: {err}") + }); + let account_esdt_roles = api + .get_account_esdt_roles(&sdk_address) + .await + .unwrap_or_else(|err| { + panic!("failed to retrieve ESDT roles for address {address}: {err}") + }); + let account_storage = api + .get_account_storage_keys(&sdk_address) + .await + .unwrap_or_else(|err| { + panic!("failed to retrieve storage for address {address}: {err}") + }); + + (account_esdt, account_esdt_roles, account_storage) + }; let account_state = set_account( sdk_account, diff --git a/framework/snippets/src/interactor.rs b/framework/snippets/src/interactor.rs index bb38873afe..3102d88d64 100644 --- a/framework/snippets/src/interactor.rs +++ b/framework/snippets/src/interactor.rs @@ -32,8 +32,8 @@ pub struct Interactor { } impl Interactor { - pub async fn new(gateway_url: &str) -> Self { - let proxy = GatewayProxy::new(gateway_url.to_string()); + pub async fn new(gateway_uri: &str, use_chain_simulator: bool) -> Self { + let proxy = GatewayProxy::new(gateway_uri.to_string(), use_chain_simulator); let network_config = proxy.get_network_config().await.unwrap(); Self { proxy, @@ -46,8 +46,13 @@ impl Interactor { } } - pub fn register_wallet(&mut self, wallet: Wallet) -> Address { + pub async fn register_wallet(&mut self, wallet: Wallet) -> Address { let address = erdrs_address_to_h256(wallet.address()); + self.proxy + .send_user_funds(&Bech32Address::from(&address).to_bech32_string()) + .await + .unwrap(); + self.sender_map.insert( address.clone(), Sender { diff --git a/framework/snippets/src/interactor_scenario/interactor_sc_call.rs b/framework/snippets/src/interactor_scenario/interactor_sc_call.rs index 6802304ae9..a9d3930eb6 100644 --- a/framework/snippets/src/interactor_scenario/interactor_sc_call.rs +++ b/framework/snippets/src/interactor_scenario/interactor_sc_call.rs @@ -14,6 +14,10 @@ impl Interactor { { let sc_call_step = sc_call_step.as_mut(); let tx_hash = self.launch_sc_call(sc_call_step).await; + self.proxy + .generate_blocks_until_tx_processed(&tx_hash) + .await + .unwrap(); let tx = self.proxy.retrieve_tx_on_network(tx_hash.clone()).await; sc_call_step.save_response(network_response::parse_tx_response(tx)); diff --git a/framework/snippets/src/interactor_scenario/interactor_sc_deploy.rs b/framework/snippets/src/interactor_scenario/interactor_sc_deploy.rs index 59de249e83..20d45649d8 100644 --- a/framework/snippets/src/interactor_scenario/interactor_sc_deploy.rs +++ b/framework/snippets/src/interactor_scenario/interactor_sc_deploy.rs @@ -53,6 +53,10 @@ impl Interactor { { let sc_deploy_step = sc_deploy_step.as_mut(); let tx_hash = self.launch_sc_deploy(sc_deploy_step).await; + self.proxy + .generate_blocks_until_tx_processed(&tx_hash) + .await + .unwrap(); let tx = self.proxy.retrieve_tx_on_network(tx_hash.clone()).await; let addr = sc_deploy_step.tx.from.clone(); diff --git a/framework/snippets/src/interactor_scenario/interactor_transfer.rs b/framework/snippets/src/interactor_scenario/interactor_transfer.rs index 6557e4119f..53da3a64b9 100644 --- a/framework/snippets/src/interactor_scenario/interactor_transfer.rs +++ b/framework/snippets/src/interactor_scenario/interactor_transfer.rs @@ -11,6 +11,11 @@ impl Interactor { self.set_nonce_and_sign_tx(sender_address, &mut transaction) .await; let tx_hash = self.proxy.send_transaction(&transaction).await.unwrap(); + self.proxy + .generate_blocks_until_tx_processed(&tx_hash) + .await + .unwrap(); + println!("transfer tx hash: {tx_hash}"); info!("transfer tx hash: {}", tx_hash); diff --git a/framework/snippets/src/multi/interactor_multi_sc_process.rs b/framework/snippets/src/multi/interactor_multi_sc_process.rs index 3364a4d5ee..076c005d84 100644 --- a/framework/snippets/src/multi/interactor_multi_sc_process.rs +++ b/framework/snippets/src/multi/interactor_multi_sc_process.rs @@ -34,6 +34,7 @@ impl Interactor { futures.push(self.proxy.retrieve_tx_on_network(tx_hash.clone())); } + self.proxy.generate_blocks(4).await.unwrap(); join_all(futures).await } } diff --git a/sdk/core/examples/account.rs b/sdk/core/examples/account.rs index 5e9456f4b0..92e3914717 100644 --- a/sdk/core/examples/account.rs +++ b/sdk/core/examples/account.rs @@ -1,6 +1,6 @@ use multiversx_sdk::{ data::address::Address, - gateway::{GatewayProxy, DEVNET_GATEWAY}, + gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}, }; #[tokio::main] @@ -10,7 +10,7 @@ async fn main() { ) .unwrap(); - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let account = blockchain.get_account(&addr).await.unwrap(); println!("account: {account:#?}"); diff --git a/sdk/core/examples/account_storage.rs b/sdk/core/examples/account_storage.rs index 7693c26e08..148cc644da 100644 --- a/sdk/core/examples/account_storage.rs +++ b/sdk/core/examples/account_storage.rs @@ -1,16 +1,16 @@ use multiversx_sdk::{ data::address::Address, - gateway::{GatewayProxy, DEVNET_GATEWAY}, + gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}, }; #[tokio::main] async fn main() { let addr = Address::from_bech32_string( - "erd1932eft30w753xyvme8d49qejgkjc09n5e49w4mwdjtm0neld797su0dlxp", + "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", ) .unwrap(); - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let account_storage = blockchain.get_account_storage_keys(&addr).await.unwrap(); println!("Account Storage: {account_storage:#?}"); diff --git a/sdk/core/examples/get_esdt_tokens.rs b/sdk/core/examples/get_esdt_tokens.rs index fac424da27..6c2f663e09 100644 --- a/sdk/core/examples/get_esdt_tokens.rs +++ b/sdk/core/examples/get_esdt_tokens.rs @@ -1,6 +1,6 @@ use multiversx_sdk::{ data::address::Address, - gateway::{GatewayProxy, DEVNET_GATEWAY}, + gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}, }; #[tokio::main] @@ -10,7 +10,7 @@ async fn main() { ) .unwrap(); - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let balances = blockchain.get_account_esdt_tokens(&addr).await.unwrap(); println!("{balances:#?}"); diff --git a/sdk/core/examples/get_hyper_block_by_hash.rs b/sdk/core/examples/get_hyper_block_by_hash.rs index 1d7f969ce1..d6f36e2aba 100644 --- a/sdk/core/examples/get_hyper_block_by_hash.rs +++ b/sdk/core/examples/get_hyper_block_by_hash.rs @@ -1,10 +1,10 @@ -use multiversx_sdk::gateway::{GatewayProxy, DEVNET_GATEWAY}; +use multiversx_sdk::gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}; #[tokio::main] async fn main() { - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let result = blockchain - .get_hyper_block_by_hash("20b14ba0e68c465810c5ded091f220e51dad41629d7ccd87dab572206185e419") + .get_hyper_block_by_hash("d59e0dc7d407b1175655357cb8056ec3bb77961192753cddda2fb700c6ce71c6") .await; println!("block by hash result: {result:?}"); diff --git a/sdk/core/examples/get_hyper_block_by_nonce.rs b/sdk/core/examples/get_hyper_block_by_nonce.rs index 575255d6c9..68ec349081 100644 --- a/sdk/core/examples/get_hyper_block_by_nonce.rs +++ b/sdk/core/examples/get_hyper_block_by_nonce.rs @@ -1,8 +1,8 @@ -use multiversx_sdk::gateway::{GatewayProxy, DEVNET_GATEWAY}; +use multiversx_sdk::gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}; #[tokio::main] async fn main() { - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let result = blockchain.get_hyper_block_by_nonce(7468).await; println!("block by nonce result: {result:?}") diff --git a/sdk/core/examples/get_hyper_block_latest.rs b/sdk/core/examples/get_hyper_block_latest.rs index 934358fdbf..91ddd9e9c7 100644 --- a/sdk/core/examples/get_hyper_block_latest.rs +++ b/sdk/core/examples/get_hyper_block_latest.rs @@ -1,9 +1,9 @@ -use multiversx_sdk::gateway::{GatewayProxy, DEVNET_GATEWAY}; +use multiversx_sdk::gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}; #[tokio::main] async fn main() { - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); - let result = blockchain.get_latest_hyper_block_nonce(false).await; + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); + let result = blockchain.get_latest_hyper_block_nonce().await; println!("latest block result: {result:?}") } diff --git a/sdk/core/examples/get_network_config.rs b/sdk/core/examples/get_network_config.rs index d53e0e7ce1..481cc31da3 100644 --- a/sdk/core/examples/get_network_config.rs +++ b/sdk/core/examples/get_network_config.rs @@ -1,8 +1,8 @@ -use multiversx_sdk::gateway::{GatewayProxy, DEVNET_GATEWAY}; +use multiversx_sdk::gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}; #[tokio::main] async fn main() { - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let network_config = blockchain.get_network_config().await.unwrap(); println!("network_config: {network_config:#?}") diff --git a/sdk/core/examples/get_network_economics.rs b/sdk/core/examples/get_network_economics.rs index bb0410c8f0..f7cf9e808b 100644 --- a/sdk/core/examples/get_network_economics.rs +++ b/sdk/core/examples/get_network_economics.rs @@ -1,8 +1,8 @@ -use multiversx_sdk::gateway::{GatewayProxy, DEVNET_GATEWAY}; +use multiversx_sdk::gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}; #[tokio::main] async fn main() { - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let network_economics = blockchain.get_network_economics().await.unwrap(); println!("network_economics: {network_economics:#?}") diff --git a/sdk/core/examples/sign_tx.rs b/sdk/core/examples/sign_tx.rs index aa3f977321..50d2a885d6 100644 --- a/sdk/core/examples/sign_tx.rs +++ b/sdk/core/examples/sign_tx.rs @@ -1,6 +1,6 @@ use multiversx_sdk::{ data::transaction::Transaction, - gateway::{GatewayProxy, DEVNET_GATEWAY}, + gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}, wallet::Wallet, }; @@ -11,7 +11,7 @@ async fn main() { ) .unwrap(); let addr = wl.address(); - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let network_config = blockchain.get_network_config().await.unwrap(); let arg = blockchain diff --git a/sdk/core/examples/sign_txs.rs b/sdk/core/examples/sign_txs.rs index 2860d528f7..35cc6d2e01 100644 --- a/sdk/core/examples/sign_txs.rs +++ b/sdk/core/examples/sign_txs.rs @@ -1,6 +1,6 @@ use multiversx_sdk::{ data::transaction::Transaction, - gateway::{GatewayProxy, DEVNET_GATEWAY}, + gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}, wallet::Wallet, }; @@ -11,7 +11,7 @@ async fn main() { ) .unwrap(); let addr = wl.address(); - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let network_config = blockchain.get_network_config().await.unwrap(); let arg = blockchain diff --git a/sdk/core/examples/tx_cost.rs b/sdk/core/examples/tx_cost.rs index a982b130ec..1d24230c12 100644 --- a/sdk/core/examples/tx_cost.rs +++ b/sdk/core/examples/tx_cost.rs @@ -1,6 +1,6 @@ use multiversx_sdk::{ data::{address::Address, transaction::Transaction}, - gateway::{GatewayProxy, DEVNET_GATEWAY}, + gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}, utils::base64_encode, }; @@ -26,7 +26,7 @@ async fn main() { signature: None, }; - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let cost = blockchain.request_transaction_cost(&tx).await.unwrap(); println!("tx cost: {cost:#?}"); diff --git a/sdk/core/examples/tx_default_args.rs b/sdk/core/examples/tx_default_args.rs index 01b91aa5a6..76412b34d4 100644 --- a/sdk/core/examples/tx_default_args.rs +++ b/sdk/core/examples/tx_default_args.rs @@ -1,11 +1,11 @@ use multiversx_sdk::{ data::address::Address, - gateway::{GatewayProxy, DEVNET_GATEWAY}, + gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}, }; #[tokio::main] async fn main() { - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let network_config = blockchain.get_network_config().await.unwrap(); let addr = Address::from_bech32_string( "erd1qqqqqqqqqqqqqpgqfzydqmdw7m2vazsp6u5p95yxz76t2p9rd8ss0zp9ts", diff --git a/sdk/core/examples/tx_info.rs b/sdk/core/examples/tx_info.rs index f7126daca9..d2c4cc93ef 100644 --- a/sdk/core/examples/tx_info.rs +++ b/sdk/core/examples/tx_info.rs @@ -1,9 +1,9 @@ -use multiversx_sdk::gateway::{GatewayProxy, DEVNET_GATEWAY}; +use multiversx_sdk::gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}; #[tokio::main] async fn main() { - let tx_hash = "49edb289892a655a0e988b360c19326c21107f9696c6197b435667c6e8c6e1a3"; - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let tx_hash = "fd21782ddb9e2217a3239e849e39d1d2c8fa74142a73f2dda3adb3028c0514e9"; + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let status = blockchain.get_transaction_status(tx_hash).await; println!("tx status: {status:?}"); diff --git a/sdk/core/examples/vm_query.rs b/sdk/core/examples/vm_query.rs index d07f49b856..51e37f6f68 100644 --- a/sdk/core/examples/vm_query.rs +++ b/sdk/core/examples/vm_query.rs @@ -1,23 +1,20 @@ use multiversx_sdk::{ data::{address::Address, vm::VmValueRequest}, - gateway::{GatewayProxy, DEVNET_GATEWAY}, + gateway::{GatewayProxy, DEFAULT_USE_CHAIN_SIMULATOR, DEVNET_GATEWAY}, wallet::Wallet, }; #[tokio::main] async fn main() { - let wl = Wallet::from_private_key( - "1648ad209d6b157a289884933e3bb30f161ec7113221ec16f87c3578b05830b0", - ) - .unwrap(); + let wl = Wallet::from_pem_file("sdk/core/tests/alice.pem").unwrap(); let addr = wl.address(); - let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string()); + let blockchain = GatewayProxy::new(DEVNET_GATEWAY.to_string(), DEFAULT_USE_CHAIN_SIMULATOR); let req = VmValueRequest { sc_address: Address::from_bech32_string( - "erd1qqqqqqqqqqqqqpgqhn3ae8dpc957t7jadn7kywtg503dy7pnj9ts3umqxx", + "erd1qqqqqqqqqqqqqpgq5dvvkmka7sujfsx7cfmygnx0n7luv8k0d8sskpqcec", ) .unwrap(), - func_name: "get".to_string(), + func_name: "empty".to_string(), args: vec![], caller: addr.clone(), value: "0".to_string(), diff --git a/sdk/core/src/gateway.rs b/sdk/core/src/gateway.rs index 35e2668b50..c0fc0062d2 100644 --- a/sdk/core/src/gateway.rs +++ b/sdk/core/src/gateway.rs @@ -1,5 +1,6 @@ mod gateway_account; mod gateway_block; +mod gateway_chain_simulator; mod gateway_network; mod gateway_proxy; mod gateway_tx; @@ -10,6 +11,9 @@ pub use gateway_proxy::GatewayProxy; pub const MAINNET_GATEWAY: &str = "https://gateway.multiversx.com"; pub const TESTNET_GATEWAY: &str = "https://testnet-gateway.multiversx.com"; pub const DEVNET_GATEWAY: &str = "https://devnet-gateway.multiversx.com"; +pub const SIMULATOR_GATEWAY: &str = "http://localhost:8085"; // MetachainShardId will be used to identify a shard ID as metachain pub const METACHAIN_SHARD_ID: u32 = 0xFFFFFFFF; + +pub const DEFAULT_USE_CHAIN_SIMULATOR: bool = false; diff --git a/sdk/core/src/gateway/gateway_block.rs b/sdk/core/src/gateway/gateway_block.rs index b6daf57abb..5e1af681ee 100644 --- a/sdk/core/src/gateway/gateway_block.rs +++ b/sdk/core/src/gateway/gateway_block.rs @@ -41,12 +41,8 @@ impl GatewayProxy { } // get_latest_hyper_block_nonce retrieves the latest hyper block (metachain) nonce from the network - pub async fn get_latest_hyper_block_nonce(&self, with_metachain: bool) -> Result { - let mut endpoint = GET_NETWORK_STATUS_ENDPOINT.to_string(); - - if with_metachain { - endpoint = format!("{GET_NETWORK_STATUS_ENDPOINT}/{METACHAIN_SHARD_ID}"); - } + pub async fn get_latest_hyper_block_nonce(&self) -> Result { + let endpoint = format!("{GET_NETWORK_STATUS_ENDPOINT}/{METACHAIN_SHARD_ID}"); let endpoint = self.get_endpoint(endpoint.as_str()); diff --git a/sdk/core/src/gateway/gateway_chain_simulator.rs b/sdk/core/src/gateway/gateway_chain_simulator.rs new file mode 100644 index 0000000000..9c9e75b819 --- /dev/null +++ b/sdk/core/src/gateway/gateway_chain_simulator.rs @@ -0,0 +1,86 @@ +use std::collections::HashMap; + +use super::GatewayProxy; +use anyhow::{anyhow, Error}; +use serde::{Deserialize, Serialize}; + +const SEND_USER_FUNDS_ENDPOINT: &str = "transaction/send-user-funds"; +const GENERATE_BLOCKS_FUNDS_ENDPOINT: &str = "simulator/generate-blocks"; +const GENERATE_BLOCKS_UNTIL_TX_PROCESSED_ENDPOINT: &str = + "simulator/generate-blocks-until-transaction-processed"; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GenerateBlocksResponse { + pub data: serde_json::Value, + pub error: String, + pub code: String, +} + +impl GatewayProxy { + pub async fn send_user_funds(&self, receiver: &String) -> Result { + if !self.chain_simulator { + return Ok(String::from("no-simulator")); + } + + let mut r = HashMap::new(); + r.insert("receiver", receiver); + let endpoint_funds = self.get_endpoint(SEND_USER_FUNDS_ENDPOINT); + let resp = self + .client + .post(endpoint_funds) + .json(&r) + .send() + .await? + .json::() + .await?; + + match resp.code.as_str() { + "successful" => Ok(resp.code), + _ => Err(anyhow!("{}", resp.error)), + } + } + + pub async fn generate_blocks(&self, number_blocks: u64) -> Result { + if !self.chain_simulator { + return Ok(String::from("no-simulator")); + } + + let url_gen_blocks: String = + format!("{}/{}", GENERATE_BLOCKS_FUNDS_ENDPOINT, number_blocks); + let endpoint_blocks = self.get_endpoint(&url_gen_blocks); + let resp = self + .client + .post(endpoint_blocks) + .send() + .await? + .json::() + .await?; + + match resp.code.as_str() { + "successful" => Ok(resp.code), + _ => Err(anyhow!("{}", resp.error)), + } + } + + pub async fn generate_blocks_until_tx_processed(&self, tx: &String) -> Result { + if !self.chain_simulator { + return Ok(String::from("no-simulator")); + } + + let url_gen_blocks_until_tx_processed: String = + format!("{}/{}", GENERATE_BLOCKS_UNTIL_TX_PROCESSED_ENDPOINT, tx); + let endpoint_blocks = self.get_endpoint(&url_gen_blocks_until_tx_processed); + let resp = self + .client + .post(endpoint_blocks) + .send() + .await? + .json::() + .await?; + + match resp.code.as_str() { + "successful" => Ok(resp.code), + _ => Err(anyhow!("{}", resp.error)), + } + } +} diff --git a/sdk/core/src/gateway/gateway_proxy.rs b/sdk/core/src/gateway/gateway_proxy.rs index 47925cd79f..46e48455e5 100644 --- a/sdk/core/src/gateway/gateway_proxy.rs +++ b/sdk/core/src/gateway/gateway_proxy.rs @@ -3,19 +3,21 @@ use reqwest::Client; /// Allows communication with the MultiversX gateway API. #[derive(Clone, Debug)] pub struct GatewayProxy { - pub(crate) proxy_url: String, + pub(crate) proxy_uri: String, pub(crate) client: Client, + pub chain_simulator: bool, } impl GatewayProxy { - pub fn new(proxy_url: String) -> Self { + pub fn new(proxy_uri: String, chain_simulator: bool) -> Self { Self { - proxy_url, + proxy_uri, client: Client::new(), + chain_simulator, } } pub(crate) fn get_endpoint(&self, endpoint: &str) -> String { - format!("{}/{}", self.proxy_url, endpoint) + format!("{}/{}", self.proxy_uri, endpoint) } } diff --git a/tools/interactor-system-func-calls/config.toml b/tools/interactor-system-func-calls/config.toml index 61ac8dbf87..dfc1ba62a6 100644 --- a/tools/interactor-system-func-calls/config.toml +++ b/tools/interactor-system-func-calls/config.toml @@ -1 +1,2 @@ -gateway = 'https://devnet-gateway.multiversx.com' +chain_type = 'real' +gateway_uri = 'https://devnet-gateway.multiversx.com' diff --git a/tools/interactor-system-func-calls/src/system_sc_interact.rs b/tools/interactor-system-func-calls/src/system_sc_interact.rs index df47733d47..dbfa11a14e 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact.rs @@ -227,9 +227,10 @@ struct SysFuncCallsInteract { impl SysFuncCallsInteract { async fn init() -> Self { let config = Config::load_config(); - let mut interactor = Interactor::new(config.gateway()).await; + let mut interactor = + Interactor::new(config.gateway_uri(), config.use_chain_simulator()).await; - let wallet_address = interactor.register_wallet(test_wallets::alice()); + let wallet_address = interactor.register_wallet(test_wallets::alice()).await; Self { interactor, diff --git a/tools/interactor-system-func-calls/src/system_sc_interact_config.rs b/tools/interactor-system-func-calls/src/system_sc_interact_config.rs index 4495f069b8..c61059d57e 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact_config.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact_config.rs @@ -2,12 +2,20 @@ use serde::Deserialize; use std::io::Read; /// Config file -const CONFIG_FILE: &str = "../config.toml"; +const CONFIG_FILE: &str = "config.toml"; + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ChainType { + Real, + Simulator, +} /// SysFuncCalls Interact configuration #[derive(Debug, Deserialize)] pub struct Config { - gateway: String, + gateway_uri: String, + chain_type: ChainType, } impl Config { @@ -19,8 +27,16 @@ impl Config { toml::from_str(&content).unwrap() } - // Returns the gateway - pub fn gateway(&self) -> &str { - &self.gateway + // 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, + } } }