Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chain simulator - integration with interactor #1728

Merged
merged 13 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contracts/examples/adder/interact/config.toml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
gateway = 'https://devnet-gateway.multiversx.com'
chain_type = "simulator"
13 changes: 8 additions & 5 deletions contracts/examples/adder/interact/src/basic_interact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -63,9 +65,10 @@ impl AdderInteract {
.with_tracer(INTERACTOR_SCENARIO_TRACE_PATH)
.await;

let adder_owner_address =
interactor.register_wallet(Wallet::from_pem_file("adder-owner.pem").unwrap());
let wallet_address = interactor.register_wallet(test_wallets::mike());
let adder_owner_address = interactor.register_wallet(test_wallets::alice()).await;
let wallet_address = interactor.register_wallet(test_wallets::mike()).await;

interactor.proxy.generate_blocks(20).await.unwrap();

Self {
interactor,
Expand Down Expand Up @@ -205,7 +208,7 @@ impl AdderInteract {
let response = self
.interactor
.tx()
.from(&self.wallet_address)
.from(&self.adder_owner_address)
.to(self.state.current_adder_address())
.gas(3_000_000)
.typed(adder_proxy::AdderProxy)
Expand Down Expand Up @@ -241,5 +244,5 @@ async fn test() {
basic_interact.deploy().await;
basic_interact.add(1u32).await;

basic_interact.upgrade(7u32).await;
basic_interact.upgrade(5u32).await;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const CONFIG_FILE: &str = "config.toml";
/// Adder Interact configuration
#[derive(Debug, Deserialize)]
pub struct Config {
gateway: String,
gateway: Option<String>,
chain_type: String,
}

impl Config {
Expand All @@ -21,6 +22,10 @@ impl Config {

// Returns the gateway
pub fn gateway(&self) -> &str {
&self.gateway
match self.chain_type.as_str() {
"real" => self.gateway.as_deref().expect("Please provide gateway!"),
"simulator" => "http://localhost:8085",
_ => "",
}
}
}
8 changes: 4 additions & 4 deletions contracts/examples/multisig/interact/src/multisig_interact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -90,7 +90,7 @@ impl MultisigInteract {
.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(),
Expand All @@ -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;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl BasicFeaturesInteract {
.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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl ComposabilityInteract {
.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(),
Expand Down
38 changes: 24 additions & 14 deletions framework/snippets/src/account_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,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,
Expand Down
7 changes: 6 additions & 1 deletion framework/snippets/src/interactor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
2 changes: 2 additions & 0 deletions sdk/core/src/gateway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ mod gateway_network;
mod gateway_proxy;
mod gateway_tx;
mod gateway_tx_retrieve;
mod gateway_chain_simulator;

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;
86 changes: 86 additions & 0 deletions sdk/core/src/gateway/gateway_chain_simulator.rs
Original file line number Diff line number Diff line change
@@ -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<String, Error> {
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::<GenerateBlocksResponse>()
.await?;

match resp.code.as_str() {
"successful" => Ok(resp.code),
_ => Err(anyhow!("{}", resp.error)),
}
}

pub async fn generate_blocks(&self, number_blocks: u64) -> Result<String, Error> {
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::<GenerateBlocksResponse>()
.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<String, Error> {
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::<GenerateBlocksResponse>()
.await?;

match resp.code.as_str() {
"successful" => Ok(resp.code),
_ => Err(anyhow!("{}", resp.error)),
}
}
}
6 changes: 6 additions & 0 deletions sdk/core/src/gateway/gateway_proxy.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
use reqwest::Client;

pub const CHAIN_SIMULATOR_GATEWAY: &str = "http://localhost:8085";

/// Allows communication with the MultiversX gateway API.
#[derive(Clone, Debug)]
pub struct GatewayProxy {
pub(crate) proxy_url: String,
pub(crate) client: Client,
pub chain_simulator: bool,
}

impl GatewayProxy {
pub fn new(proxy_url: String) -> Self {
let chain_simulator = proxy_url == CHAIN_SIMULATOR_GATEWAY;
BiancaIalangi marked this conversation as resolved.
Show resolved Hide resolved

Self {
proxy_url,
client: Client::new(),
chain_simulator,
}
}

Expand Down
Loading