From 9602c1015680f317f035c30bd43e947d2697e4e4 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 9 Dec 2024 14:56:18 +0100 Subject: [PATCH] forwarder interactor setup --- Cargo.toml | 1 + .../forwarder-interactor/.gitignore | 2 + .../forwarder-interactor/Cargo.toml | 32 + .../forwarder-interactor/config.toml | 7 + .../forwarder-interactor/src/config.rs | 51 + .../forwarder-interactor/src/interact.rs | 1944 +++++++++++++++++ .../src/interactor_main.rs | 7 + .../forwarder-interactor/src/proxy.rs | 1375 ++++++++++++ .../forwarder-interactor/state.toml | 1 + .../tests/interact_cs_tests.rs | 15 + .../tests/interact_tests.rs | 13 + .../composability/forwarder/sc-config.toml | 4 + .../forwarder/src/forwarder_proxy.rs | 4 +- .../forwarder/src/fwd_call_async.rs | 2 +- .../composability/forwarder/src/fwd_nft.rs | 4 +- 15 files changed, 3457 insertions(+), 5 deletions(-) create mode 100644 contracts/feature-tests/composability/forwarder-interactor/.gitignore create mode 100644 contracts/feature-tests/composability/forwarder-interactor/Cargo.toml create mode 100644 contracts/feature-tests/composability/forwarder-interactor/config.toml create mode 100644 contracts/feature-tests/composability/forwarder-interactor/src/config.rs create mode 100644 contracts/feature-tests/composability/forwarder-interactor/src/interact.rs create mode 100644 contracts/feature-tests/composability/forwarder-interactor/src/interactor_main.rs create mode 100644 contracts/feature-tests/composability/forwarder-interactor/src/proxy.rs create mode 100644 contracts/feature-tests/composability/forwarder-interactor/state.toml create mode 100644 contracts/feature-tests/composability/forwarder-interactor/tests/interact_cs_tests.rs create mode 100644 contracts/feature-tests/composability/forwarder-interactor/tests/interact_tests.rs diff --git a/Cargo.toml b/Cargo.toml index 3cc34e3bd4..43a83719f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -133,6 +133,7 @@ members = [ "contracts/feature-tests/composability/execute-on-dest-esdt-issue-callback/child", "contracts/feature-tests/composability/execute-on-dest-esdt-issue-callback/child/meta", "contracts/feature-tests/composability/forwarder", + "contracts/feature-tests/composability/forwarder-interactor", "contracts/feature-tests/composability/forwarder/meta", "contracts/feature-tests/composability/forwarder-legacy", "contracts/feature-tests/composability/forwarder-legacy/meta", diff --git a/contracts/feature-tests/composability/forwarder-interactor/.gitignore b/contracts/feature-tests/composability/forwarder-interactor/.gitignore new file mode 100644 index 0000000000..5a64d09a70 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/.gitignore @@ -0,0 +1,2 @@ +# Pem files are used for interactions, but shouldn't be committed +*.pem diff --git a/contracts/feature-tests/composability/forwarder-interactor/Cargo.toml b/contracts/feature-tests/composability/forwarder-interactor/Cargo.toml new file mode 100644 index 0000000000..b8dce626fc --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "forwarder-interact" +version = "0.0.0" +authors = ["you"] +edition = "2021" +publish = false + +[[bin]] +name = "forwarder-interact" +path = "src/interactor_main.rs" + +[lib] +path = "src/interact.rs" + +[dependencies.forwarder] +path = "../forwarder" + +[dependencies.multiversx-sc-snippets] +version = "0.54.5" +path = "../../../../framework/snippets" + +[dependencies.multiversx-sc] +version = "0.54.5" +path = "../../../../framework/base" + +[dependencies] +clap = { version = "4.4.7", features = ["derive"] } +serde = { version = "1.0", features = ["derive"] } +toml = "0.8.6" + +[features] +chain-simulator-tests = [] diff --git a/contracts/feature-tests/composability/forwarder-interactor/config.toml b/contracts/feature-tests/composability/forwarder-interactor/config.toml new file mode 100644 index 0000000000..97acd5a5c6 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/config.toml @@ -0,0 +1,7 @@ + +# chain_type = 'simulator' +# gateway_uri = 'http://localhost:8085' + +chain_type = 'real' +gateway_uri = 'https://devnet-gateway.multiversx.com' + diff --git a/contracts/feature-tests/composability/forwarder-interactor/src/config.rs b/contracts/feature-tests/composability/forwarder-interactor/src/config.rs new file mode 100644 index 0000000000..2d072b4bfb --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/src/config.rs @@ -0,0 +1,51 @@ +#![allow(unused)] + +use serde::Deserialize; +use std::io::Read; + +/// Config file +const CONFIG_FILE: &str = "config.toml"; + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ChainType { + Real, + Simulator, +} + +/// Contract Interact configuration +#[derive(Debug, Deserialize)] +pub struct Config { + pub gateway_uri: String, + pub chain_type: ChainType, +} + +impl Config { + // Deserializes config from file + pub fn new() -> 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: "http://localhost:8085".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/feature-tests/composability/forwarder-interactor/src/interact.rs b/contracts/feature-tests/composability/forwarder-interactor/src/interact.rs new file mode 100644 index 0000000000..b4ed599a3e --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/src/interact.rs @@ -0,0 +1,1944 @@ +#![allow(non_snake_case)] + +mod config; +mod proxy; + +use config::Config; +use multiversx_sc_snippets::imports::*; +use proxy::Color; +use serde::{Deserialize, Serialize}; +use std::{ + io::{Read, Write}, + path::Path, +}; + +const STATE_FILE: &str = "state.toml"; + +pub async fn forwarder_cli() { + env_logger::init(); + + let mut args = std::env::args(); + let _ = args.next(); + let cmd = args.next().expect("at least one argument required"); + let mut interact = ContractInteract::new().await; + match cmd.as_str() { + "deploy" => interact.deploy().await, + "send_egld" => interact.send_egld().await, + "echo_arguments_sync" => interact.echo_arguments_sync().await, + "echo_arguments_sync_twice" => interact.echo_arguments_sync_twice().await, + "forward_sync_accept_funds" => interact.forward_sync_accept_funds().await, + "forward_sync_accept_funds_rh_egld" => interact.forward_sync_accept_funds_rh_egld().await, + "forward_sync_accept_funds_rh_single_esdt" => { + interact.forward_sync_accept_funds_rh_single_esdt().await + }, + "forward_sync_accept_funds_rh_multi_esdt" => { + interact.forward_sync_accept_funds_rh_multi_esdt().await + }, + "forward_sync_accept_funds_with_fees" => { + interact.forward_sync_accept_funds_with_fees().await + }, + "forward_sync_accept_funds_then_read" => { + interact.forward_sync_accept_funds_then_read().await + }, + "forward_sync_retrieve_funds" => interact.forward_sync_retrieve_funds().await, + "forward_sync_retrieve_funds_with_accept_func" => { + interact + .forward_sync_retrieve_funds_with_accept_func() + .await + }, + "accept_funds_func" => interact.accept_funds_func().await, + "forward_sync_accept_funds_multi_transfer" => { + interact.forward_sync_accept_funds_multi_transfer().await + }, + "echo_args_async" => interact.echo_args_async().await, + "forward_async_accept_funds" => interact.forward_async_accept_funds().await, + "forward_async_accept_funds_half_payment" => { + interact.forward_async_accept_funds_half_payment().await + }, + "forward_async_accept_funds_with_fees" => { + interact.forward_async_accept_funds_with_fees().await + }, + "forward_async_retrieve_funds" => interact.forward_async_retrieve_funds().await, + "send_funds_twice" => interact.send_funds_twice().await, + "send_async_accept_multi_transfer" => interact.send_async_accept_multi_transfer().await, + "callback_data" => interact.callback_data().await, + "callback_data_at_index" => interact.callback_data_at_index().await, + "clear_callback_data" => interact.clear_callback_data().await, + "forward_transf_exec_accept_funds" => interact.forward_transf_exec_accept_funds().await, + "forward_transf_execu_accept_funds_with_fees" => { + interact.forward_transf_execu_accept_funds_with_fees().await + }, + "forward_transf_exec_accept_funds_twice" => { + interact.forward_transf_exec_accept_funds_twice().await + }, + "forward_transf_exec_accept_funds_return_values" => { + interact + .forward_transf_exec_accept_funds_return_values() + .await + }, + "transf_exec_multi_accept_funds" => interact.transf_exec_multi_accept_funds().await, + "forward_transf_exec_reject_funds_multi_transfer" => { + interact + .forward_transf_exec_reject_funds_multi_transfer() + .await + }, + "transf_exec_multi_reject_funds" => interact.transf_exec_multi_reject_funds().await, + "changeOwnerAddress" => interact.change_owner().await, + "deploy_contract" => interact.deploy_contract().await, + "deploy_two_contracts" => interact.deploy_two_contracts().await, + "deploy_vault_from_source" => interact.deploy_vault_from_source().await, + "upgradeVault" => interact.upgrade_vault().await, + "upgrade_vault_from_source" => interact.upgrade_vault_from_source().await, + "getFungibleEsdtBalance" => interact.get_fungible_esdt_balance().await, + "getCurrentNftNonce" => interact.get_current_nft_nonce().await, + "send_esdt" => interact.send_esdt().await, + "send_esdt_with_fees" => interact.send_esdt_with_fees().await, + "send_esdt_twice" => interact.send_esdt_twice().await, + "send_esdt_direct_multi_transfer" => interact.send_esdt_direct_multi_transfer().await, + "issue_fungible_token" => interact.issue_fungible_token().await, + "local_mint" => interact.local_mint().await, + "local_burn" => interact.local_burn().await, + "get_esdt_local_roles" => interact.get_esdt_local_roles().await, + "get_esdt_token_data" => interact.get_esdt_token_data().await, + "is_esdt_frozen" => interact.is_esdt_frozen().await, + "is_esdt_paused" => interact.is_esdt_paused().await, + "is_esdt_limited_transfer" => interact.is_esdt_limited_transfer().await, + "validate_token_identifier" => interact.validate_token_identifier().await, + "sft_issue" => interact.sft_issue().await, + "get_nft_balance" => interact.get_nft_balance().await, + "buy_nft" => interact.buy_nft().await, + "nft_issue" => interact.nft_issue().await, + "nft_create" => interact.nft_create().await, + "nft_create_compact" => interact.nft_create_compact().await, + "nft_add_uris" => interact.nft_add_uris().await, + "nft_update_attributes" => interact.nft_update_attributes().await, + "nft_decode_complex_attributes" => interact.nft_decode_complex_attributes().await, + "nft_add_quantity" => interact.nft_add_quantity().await, + "nft_burn" => interact.nft_burn().await, + "transfer_nft_via_async_call" => interact.transfer_nft_via_async_call().await, + "transfer_nft_and_execute" => interact.transfer_nft_and_execute().await, + "create_and_send" => interact.create_and_send().await, + "setLocalRoles" => interact.set_local_roles().await, + "unsetLocalRoles" => interact.unset_local_roles().await, + "issue_dynamic_token" => interact.issue_dynamic_token().await, + "change_to_dynamic" => interact.change_to_dynamic().await, + "update_token" => interact.update_token().await, + "modify_royalties" => interact.modify_royalties().await, + "set_new_uris" => interact.set_new_uris().await, + "modify_creator" => interact.modify_creator().await, + "metadata_recreate" => interact.metadata_recreate().await, + "metadata_update" => interact.metadata_update().await, + "lastIssuedToken" => interact.last_issued_token().await, + "lastErrorMessage" => interact.last_error_message().await, + _ => panic!("unknown command: {}", &cmd), + } +} + +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct State { + contract_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 contract address + pub fn set_address(&mut self, address: Bech32Address) { + self.contract_address = Some(address); + } + + /// Returns the contract address + pub fn current_address(&self) -> &Bech32Address { + self.contract_address + .as_ref() + .expect("no known 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(); + } +} + +pub struct ContractInteract { + interactor: Interactor, + wallet_address: Address, + contract_code: BytesValue, + state: State, +} + +impl ContractInteract { + pub async fn new() -> Self { + let config = Config::new(); + let mut interactor = Interactor::new(config.gateway_uri()) + .await + .use_chain_simulator(config.use_chain_simulator()); + + interactor.set_current_dir_from_workspace("forwarder-interactor"); + let wallet_address = interactor.register_wallet(test_wallets::alice()).await; + + // Useful in the chain simulator setting + // generate blocks until ESDTSystemSCAddress is enabled + interactor.generate_blocks_until_epoch(1).await.unwrap(); + + let contract_code = BytesValue::interpret_from( + "mxsc:../forwarder/output/forwarder.mxsc.json", + &InterpreterContext::default(), + ); + + ContractInteract { + interactor, + wallet_address, + contract_code, + state: State::load_state(), + } + } + + pub async fn deploy(&mut self) { + let new_address = self + .interactor + .tx() + .from(&self.wallet_address) + .gas(300_000_000u64) + .typed(proxy::ForwarderProxy) + .init() + .code(&self.contract_code) + .returns(ReturnsNewAddress) + .run() + .await; + let new_address_bech32 = bech32::encode(&new_address); + self.state.set_address(Bech32Address::from_bech32_string( + new_address_bech32.clone(), + )); + + println!("new address: {new_address_bech32}"); + } + + pub async fn send_egld(&mut self) { + let to = bech32::decode(""); + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .send_egld(to, amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn echo_arguments_sync(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + let args = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .echo_arguments_sync(to, args) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn echo_arguments_sync_twice(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + let args = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .echo_arguments_sync_twice(to, args) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_sync_accept_funds(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_sync_accept_funds(to) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_sync_accept_funds_rh_egld(&mut self) { + let egld_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_sync_accept_funds_rh_egld(to) + .egld(egld_amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_sync_accept_funds_rh_single_esdt(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_sync_accept_funds_rh_single_esdt(to) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_sync_accept_funds_rh_multi_esdt(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_sync_accept_funds_rh_multi_esdt(to) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_sync_accept_funds_with_fees(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + let percentage_fees = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_sync_accept_funds_with_fees(to, percentage_fees) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_sync_accept_funds_then_read(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_sync_accept_funds_then_read(to) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_sync_retrieve_funds(&mut self) { + let to = bech32::decode(""); + let token = EgldOrEsdtTokenIdentifier::esdt(&b""[..]); + let token_nonce = 0u64; + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_sync_retrieve_funds(to, token, token_nonce, amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_sync_retrieve_funds_with_accept_func(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + let token = TokenIdentifier::from_esdt_bytes(&b""[..]); + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_sync_retrieve_funds_with_accept_func(to, token, amount) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn accept_funds_func(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .accept_funds_func() + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_sync_accept_funds_multi_transfer(&mut self) { + let to = bech32::decode(""); + let token_payments = MultiValueVec::from(vec![MultiValue3::< + TokenIdentifier, + u64, + BigUint, + >::from(( + TokenIdentifier::from_esdt_bytes(&b""[..]), + 0u64, + BigUint::::from(0u128), + ))]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_sync_accept_funds_multi_transfer(to, token_payments) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn echo_args_async(&mut self) { + let to = bech32::decode(""); + let args = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .echo_args_async(to, args) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_async_accept_funds(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_async_accept_funds(to) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_async_accept_funds_half_payment(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_async_accept_funds_half_payment(to) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_async_accept_funds_with_fees(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + let percentage_fees = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_async_accept_funds_with_fees(to, percentage_fees) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_async_retrieve_funds(&mut self) { + let to = bech32::decode(""); + let token = EgldOrEsdtTokenIdentifier::esdt(&b""[..]); + let token_nonce = 0u64; + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_async_retrieve_funds(to, token, token_nonce, amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn send_funds_twice(&mut self) { + let to = bech32::decode(""); + let token_identifier = EgldOrEsdtTokenIdentifier::esdt(&b""[..]); + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .send_funds_twice(to, token_identifier, amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn send_async_accept_multi_transfer(&mut self) { + let to = bech32::decode(""); + let token_payments = MultiValueVec::from(vec![MultiValue3::< + TokenIdentifier, + u64, + BigUint, + >::from(( + TokenIdentifier::from_esdt_bytes(&b""[..]), + 0u64, + BigUint::::from(0u128), + ))]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .send_async_accept_multi_transfer(to, token_payments) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn callback_data(&mut self) { + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .callback_data() + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {:?}", result_value.0); + } + + pub async fn callback_data_at_index(&mut self) { + let index = 0u32; + + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .callback_data_at_index(index) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn clear_callback_data(&mut self) { + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .clear_callback_data() + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_transf_exec_accept_funds(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_transf_exec_accept_funds(to) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_transf_execu_accept_funds_with_fees(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + let percentage_fees = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_transf_execu_accept_funds_with_fees(to, percentage_fees) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_transf_exec_accept_funds_twice(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_transf_exec_accept_funds_twice(to) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_transf_exec_accept_funds_return_values(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_transf_exec_accept_funds_return_values(to) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn transf_exec_multi_accept_funds(&mut self) { + let to = bech32::decode(""); + let token_payments = MultiValueVec::from(vec![MultiValue3::< + TokenIdentifier, + u64, + BigUint, + >::from(( + TokenIdentifier::from_esdt_bytes(&b""[..]), + 0u64, + BigUint::::from(0u128), + ))]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .transf_exec_multi_accept_funds(to, token_payments) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn forward_transf_exec_reject_funds_multi_transfer(&mut self) { + let to = bech32::decode(""); + let token_payments = MultiValueVec::from(vec![MultiValue3::< + TokenIdentifier, + u64, + BigUint, + >::from(( + TokenIdentifier::from_esdt_bytes(&b""[..]), + 0u64, + BigUint::::from(0u128), + ))]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .forward_transf_exec_reject_funds_multi_transfer(to, token_payments) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn transf_exec_multi_reject_funds(&mut self) { + let to = bech32::decode(""); + let token_payments = MultiValueVec::from(vec![MultiValue3::< + TokenIdentifier, + u64, + BigUint, + >::from(( + TokenIdentifier::from_esdt_bytes(&b""[..]), + 0u64, + BigUint::::from(0u128), + ))]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .transf_exec_multi_reject_funds(to, token_payments) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn change_owner(&mut self) { + let child_sc_address = bech32::decode(""); + let new_owner = bech32::decode(""); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .change_owner(child_sc_address, new_owner) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn deploy_contract(&mut self) { + let code = ManagedBuffer::new_from_bytes(&b""[..]); + let opt_arg = OptionalValue::Some(ManagedBuffer::new_from_bytes(&b""[..])); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .deploy_contract(code, opt_arg) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn deploy_two_contracts(&mut self) { + let code = ManagedBuffer::new_from_bytes(&b""[..]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .deploy_two_contracts(code) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn deploy_vault_from_source(&mut self) { + let source_address = bech32::decode(""); + let opt_arg = OptionalValue::Some(ManagedBuffer::new_from_bytes(&b""[..])); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .deploy_vault_from_source(source_address, opt_arg) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn upgrade_vault(&mut self) { + let child_sc_address = bech32::decode(""); + let new_code = ManagedBuffer::new_from_bytes(&b""[..]); + let opt_arg = OptionalValue::Some(ManagedBuffer::new_from_bytes(&b""[..])); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .upgrade_vault(child_sc_address, new_code, opt_arg) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn upgrade_vault_from_source(&mut self) { + let child_sc_address = bech32::decode(""); + let source_address = bech32::decode(""); + let opt_arg = OptionalValue::Some(ManagedBuffer::new_from_bytes(&b""[..])); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .upgrade_vault_from_source(child_sc_address, source_address, opt_arg) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn get_fungible_esdt_balance(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .get_fungible_esdt_balance(token_identifier) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn get_current_nft_nonce(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .get_current_nft_nonce(token_identifier) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn send_esdt(&mut self) { + let to = bech32::decode(""); + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .send_esdt(to, token_id, amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn send_esdt_with_fees(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let to = bech32::decode(""); + let percentage_fees = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .send_esdt_with_fees(to, percentage_fees) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn send_esdt_twice(&mut self) { + let to = bech32::decode(""); + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + let amount_first_time = BigUint::::from(0u128); + let amount_second_time = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .send_esdt_twice(to, token_id, amount_first_time, amount_second_time) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn send_esdt_direct_multi_transfer(&mut self) { + let to = bech32::decode(""); + let token_payments = MultiValueVec::from(vec![MultiValue3::< + TokenIdentifier, + u64, + BigUint, + >::from(( + TokenIdentifier::from_esdt_bytes(&b""[..]), + 0u64, + BigUint::::from(0u128), + ))]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .send_esdt_direct_multi_transfer(to, token_payments) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn issue_fungible_token(&mut self) { + let egld_amount = BigUint::::from(0u128); + + let token_display_name = ManagedBuffer::new_from_bytes(&b""[..]); + let token_ticker = ManagedBuffer::new_from_bytes(&b""[..]); + let initial_supply = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .issue_fungible_token(token_display_name, token_ticker, initial_supply) + .egld(egld_amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn local_mint(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .local_mint(token_identifier, amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn local_burn(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .local_burn(token_identifier, amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn get_esdt_local_roles(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .get_esdt_local_roles(token_id) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn get_esdt_token_data(&mut self) { + let address = bech32::decode(""); + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .get_esdt_token_data(address, token_id, nonce) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn is_esdt_frozen(&mut self) { + let address = bech32::decode(""); + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .is_esdt_frozen(address, token_id, nonce) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn is_esdt_paused(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .is_esdt_paused(token_id) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn is_esdt_limited_transfer(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .is_esdt_limited_transfer(token_id) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn validate_token_identifier(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .validate_token_identifier(token_id) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn sft_issue(&mut self) { + let egld_amount = BigUint::::from(0u128); + + let token_display_name = ManagedBuffer::new_from_bytes(&b""[..]); + let token_ticker = ManagedBuffer::new_from_bytes(&b""[..]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .sft_issue(token_display_name, token_ticker) + .egld(egld_amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn get_nft_balance(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .get_nft_balance(token_identifier, nonce) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn buy_nft(&mut self) { + let token_id = String::new(); + let token_nonce = 0u64; + let token_amount = BigUint::::from(0u128); + + let nft_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nft_nonce = 0u64; + let nft_amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .buy_nft(nft_id, nft_nonce, nft_amount) + .payment(( + TokenIdentifier::from(token_id.as_str()), + token_nonce, + token_amount, + )) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn nft_issue(&mut self) { + let egld_amount = BigUint::::from(0u128); + + let token_display_name = ManagedBuffer::new_from_bytes(&b""[..]); + let token_ticker = ManagedBuffer::new_from_bytes(&b""[..]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .nft_issue(token_display_name, token_ticker) + .egld(egld_amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn nft_create(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let amount = BigUint::::from(0u128); + let name = ManagedBuffer::new_from_bytes(&b""[..]); + let royalties = BigUint::::from(0u128); + let hash = ManagedBuffer::new_from_bytes(&b""[..]); + let color = Color::default(); + let uri = ManagedBuffer::new_from_bytes(&b""[..]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .nft_create(token_identifier, amount, name, royalties, hash, color, uri) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn nft_create_compact(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let amount = BigUint::::from(0u128); + let color = Color::default(); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .nft_create_compact(token_identifier, amount, color) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn nft_add_uris(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + let uris = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .nft_add_uris(token_identifier, nonce, uris) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn nft_update_attributes(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + let new_attributes = Color::default(); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .nft_update_attributes(token_identifier, nonce, new_attributes) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn nft_decode_complex_attributes(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let amount = BigUint::::from(0u128); + let name = ManagedBuffer::new_from_bytes(&b""[..]); + let royalties = BigUint::::from(0u128); + let hash = ManagedBuffer::new_from_bytes(&b""[..]); + let uri = ManagedBuffer::new_from_bytes(&b""[..]); + let attrs_arg = MultiValue5::< + BigUint, + ManagedBuffer, + TokenIdentifier, + bool, + ManagedBuffer, + >::from(( + BigUint::::from(0u128), + ManagedBuffer::new_from_bytes(&b""[..]), + TokenIdentifier::from_esdt_bytes(&b""[..]), + false, + ManagedBuffer::new_from_bytes(&b""[..]), + )); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .nft_decode_complex_attributes( + token_identifier, + amount, + name, + royalties, + hash, + uri, + attrs_arg, + ) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn nft_add_quantity(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .nft_add_quantity(token_identifier, nonce, amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn nft_burn(&mut self) { + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .nft_burn(token_identifier, nonce, amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn transfer_nft_via_async_call(&mut self) { + let to = bech32::decode(""); + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + let amount = BigUint::::from(0u128); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .transfer_nft_via_async_call(to, token_identifier, nonce, amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn transfer_nft_and_execute(&mut self) { + let to = bech32::decode(""); + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + let amount = BigUint::::from(0u128); + let function = ManagedBuffer::new_from_bytes(&b""[..]); + let arguments = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .transfer_nft_and_execute(to, token_identifier, nonce, amount, function, arguments) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn create_and_send(&mut self) { + let to = bech32::decode(""); + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let amount = BigUint::::from(0u128); + let name = ManagedBuffer::new_from_bytes(&b""[..]); + let royalties = BigUint::::from(0u128); + let hash = ManagedBuffer::new_from_bytes(&b""[..]); + let color = Color::default(); + let uri = ManagedBuffer::new_from_bytes(&b""[..]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .create_and_send( + to, + token_identifier, + amount, + name, + royalties, + hash, + color, + uri, + ) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn set_local_roles(&mut self) { + let address = bech32::decode(""); + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let roles = MultiValueVec::::new(); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .set_local_roles(address, token_identifier, roles) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn unset_local_roles(&mut self) { + let address = bech32::decode(""); + let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); + let roles = MultiValueVec::::new(); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .unset_local_roles(address, token_identifier, roles) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn issue_dynamic_token(&mut self) { + let egld_amount = BigUint::::from(0u128); + + let token_display_name = ManagedBuffer::new_from_bytes(&b""[..]); + let token_ticker = ManagedBuffer::new_from_bytes(&b""[..]); + let token_type = EsdtTokenType::DynamicNFT; + let num_decimals = 0u32; + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .issue_dynamic_token(token_display_name, token_ticker, token_type, num_decimals) + .egld(egld_amount) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn change_to_dynamic(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .change_to_dynamic(token_id) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn update_token(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .update_token(token_id) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn modify_royalties(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + let new_royalty = 0u64; + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .modify_royalties(token_id, nonce, new_royalty) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn set_new_uris(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + let new_uris = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .set_new_uris(token_id, nonce, new_uris) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn modify_creator(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .modify_creator(token_id, nonce) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn metadata_recreate(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + let name = ManagedBuffer::new_from_bytes(&b""[..]); + let royalties = 0u64; + let hash = ManagedBuffer::new_from_bytes(&b""[..]); + let new_attributes = Color::default(); + let uris = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .metadata_recreate(token_id, nonce, name, royalties, hash, new_attributes, uris) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn metadata_update(&mut self) { + let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + let nonce = 0u64; + let name = ManagedBuffer::new_from_bytes(&b""[..]); + let royalties = 0u64; + let hash = ManagedBuffer::new_from_bytes(&b""[..]); + let new_attributes = Color::default(); + let uris = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); + + let response = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(30_000_000u64) + .typed(proxy::ForwarderProxy) + .metadata_update(token_id, nonce, name, royalties, hash, new_attributes, uris) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {response:?}"); + } + + pub async fn last_issued_token(&mut self) { + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .last_issued_token() + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } + + pub async fn last_error_message(&mut self) { + let result_value = self + .interactor + .query() + .to(self.state.current_address()) + .typed(proxy::ForwarderProxy) + .last_error_message() + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result_value:?}"); + } +} diff --git a/contracts/feature-tests/composability/forwarder-interactor/src/interactor_main.rs b/contracts/feature-tests/composability/forwarder-interactor/src/interactor_main.rs new file mode 100644 index 0000000000..cf6bcaa48f --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/src/interactor_main.rs @@ -0,0 +1,7 @@ +use forwarder_interact::forwarder_cli; +use multiversx_sc_snippets::imports::*; + +#[tokio::main] +async fn main() { + forwarder_cli().await; +} diff --git a/contracts/feature-tests/composability/forwarder-interactor/src/proxy.rs b/contracts/feature-tests/composability/forwarder-interactor/src/proxy.rs new file mode 100644 index 0000000000..b27ce77f88 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/src/proxy.rs @@ -0,0 +1,1375 @@ +// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(dead_code)] +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct ForwarderProxy; + +impl TxProxyTrait for ForwarderProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = ForwarderProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + ForwarderProxyMethods { wrapped_tx: tx } + } +} + +pub struct ForwarderProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl ForwarderProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init( + self, + ) -> TxTypedDeploy { + self.wrapped_tx + .payment(NotPayable) + .raw_deploy() + .original_result() + } +} + +#[rustfmt::skip] +impl ForwarderProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn send_egld< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + to: Arg0, + amount: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("send_egld") + .argument(&to) + .argument(&amount) + .original_result() + } + + pub fn echo_arguments_sync< + Arg0: ProxyArg>, + Arg1: ProxyArg>>, + >( + self, + to: Arg0, + args: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("echo_arguments_sync") + .argument(&to) + .argument(&args) + .original_result() + } + + pub fn echo_arguments_sync_twice< + Arg0: ProxyArg>, + Arg1: ProxyArg>>, + >( + self, + to: Arg0, + args: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("echo_arguments_sync_twice") + .argument(&to) + .argument(&args) + .original_result() + } + + pub fn forward_sync_accept_funds< + Arg0: ProxyArg>, + >( + self, + to: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("forward_sync_accept_funds") + .argument(&to) + .original_result() + } + + pub fn forward_sync_accept_funds_rh_egld< + Arg0: ProxyArg>, + >( + self, + to: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .raw_call("forward_sync_accept_funds_rh_egld") + .argument(&to) + .original_result() + } + + pub fn forward_sync_accept_funds_rh_single_esdt< + Arg0: ProxyArg>, + >( + self, + to: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .raw_call("forward_sync_accept_funds_rh_single_esdt") + .argument(&to) + .original_result() + } + + pub fn forward_sync_accept_funds_rh_multi_esdt< + Arg0: ProxyArg>, + >( + self, + to: Arg0, + ) -> TxTypedCall>> { + self.wrapped_tx + .raw_call("forward_sync_accept_funds_rh_multi_esdt") + .argument(&to) + .original_result() + } + + pub fn forward_sync_accept_funds_with_fees< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + to: Arg0, + percentage_fees: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("forward_sync_accept_funds_with_fees") + .argument(&to) + .argument(&percentage_fees) + .original_result() + } + + pub fn forward_sync_accept_funds_then_read< + Arg0: ProxyArg>, + >( + self, + to: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("forward_sync_accept_funds_then_read") + .argument(&to) + .original_result() + } + + pub fn forward_sync_retrieve_funds< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg, + Arg3: ProxyArg>, + >( + self, + to: Arg0, + token: Arg1, + token_nonce: Arg2, + amount: Arg3, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("forward_sync_retrieve_funds") + .argument(&to) + .argument(&token) + .argument(&token_nonce) + .argument(&amount) + .original_result() + } + + pub fn forward_sync_retrieve_funds_with_accept_func< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + >( + self, + to: Arg0, + token: Arg1, + amount: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("forward_sync_retrieve_funds_with_accept_func") + .argument(&to) + .argument(&token) + .argument(&amount) + .original_result() + } + + pub fn accept_funds_func( + self, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("accept_funds_func") + .original_result() + } + + pub fn forward_sync_accept_funds_multi_transfer< + Arg0: ProxyArg>, + Arg1: ProxyArg, u64, BigUint>>>, + >( + self, + to: Arg0, + token_payments: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("forward_sync_accept_funds_multi_transfer") + .argument(&to) + .argument(&token_payments) + .original_result() + } + + pub fn echo_args_async< + Arg0: ProxyArg>, + Arg1: ProxyArg>>, + >( + self, + to: Arg0, + args: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("echo_args_async") + .argument(&to) + .argument(&args) + .original_result() + } + + pub fn forward_async_accept_funds< + Arg0: ProxyArg>, + >( + self, + to: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("forward_async_accept_funds") + .argument(&to) + .original_result() + } + + pub fn forward_async_accept_funds_half_payment< + Arg0: ProxyArg>, + >( + self, + to: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("forward_async_accept_funds_half_payment") + .argument(&to) + .original_result() + } + + pub fn forward_async_accept_funds_with_fees< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + to: Arg0, + percentage_fees: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("forward_async_accept_funds_with_fees") + .argument(&to) + .argument(&percentage_fees) + .original_result() + } + + pub fn forward_async_retrieve_funds< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg, + Arg3: ProxyArg>, + >( + self, + to: Arg0, + token: Arg1, + token_nonce: Arg2, + amount: Arg3, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("forward_async_retrieve_funds") + .argument(&to) + .argument(&token) + .argument(&token_nonce) + .argument(&amount) + .original_result() + } + + pub fn send_funds_twice< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + >( + self, + to: Arg0, + token_identifier: Arg1, + amount: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("send_funds_twice") + .argument(&to) + .argument(&token_identifier) + .argument(&amount) + .original_result() + } + + pub fn send_async_accept_multi_transfer< + Arg0: ProxyArg>, + Arg1: ProxyArg, u64, BigUint>>>, + >( + self, + to: Arg0, + token_payments: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("send_async_accept_multi_transfer") + .argument(&to) + .argument(&token_payments) + .original_result() + } + + pub fn callback_data( + self, + ) -> TxTypedCall>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("callback_data") + .original_result() + } + + pub fn callback_data_at_index< + Arg0: ProxyArg, + >( + self, + index: Arg0, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier, u64, BigUint, MultiValueManagedVec>>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("callback_data_at_index") + .argument(&index) + .original_result() + } + + pub fn clear_callback_data( + self, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("clear_callback_data") + .original_result() + } + + pub fn forward_transf_exec_accept_funds< + Arg0: ProxyArg>, + >( + self, + to: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("forward_transf_exec_accept_funds") + .argument(&to) + .original_result() + } + + pub fn forward_transf_execu_accept_funds_with_fees< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + to: Arg0, + percentage_fees: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("forward_transf_execu_accept_funds_with_fees") + .argument(&to) + .argument(&percentage_fees) + .original_result() + } + + pub fn forward_transf_exec_accept_funds_twice< + Arg0: ProxyArg>, + >( + self, + to: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("forward_transf_exec_accept_funds_twice") + .argument(&to) + .original_result() + } + + /// Test that the default gas provided to the transfer_execute call + /// leaves enough in the transaction for finish to happen. + pub fn forward_transf_exec_accept_funds_return_values< + Arg0: ProxyArg>, + >( + self, + to: Arg0, + ) -> TxTypedCall, EgldOrEsdtTokenIdentifier>> { + self.wrapped_tx + .raw_call("forward_transf_exec_accept_funds_return_values") + .argument(&to) + .original_result() + } + + pub fn transf_exec_multi_accept_funds< + Arg0: ProxyArg>, + Arg1: ProxyArg, u64, BigUint>>>, + >( + self, + to: Arg0, + token_payments: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("transf_exec_multi_accept_funds") + .argument(&to) + .argument(&token_payments) + .original_result() + } + + pub fn forward_transf_exec_reject_funds_multi_transfer< + Arg0: ProxyArg>, + Arg1: ProxyArg, u64, BigUint>>>, + >( + self, + to: Arg0, + token_payments: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("forward_transf_exec_reject_funds_multi_transfer") + .argument(&to) + .argument(&token_payments) + .original_result() + } + + pub fn transf_exec_multi_reject_funds< + Arg0: ProxyArg>, + Arg1: ProxyArg, u64, BigUint>>>, + >( + self, + to: Arg0, + token_payments: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("transf_exec_multi_reject_funds") + .argument(&to) + .argument(&token_payments) + .original_result() + } + + pub fn change_owner< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + child_sc_address: Arg0, + new_owner: Arg1, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("changeOwnerAddress") + .argument(&child_sc_address) + .argument(&new_owner) + .original_result() + } + + pub fn deploy_contract< + Arg0: ProxyArg>, + Arg1: ProxyArg>>, + >( + self, + code: Arg0, + opt_arg: Arg1, + ) -> TxTypedCall, OptionalValue>>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("deploy_contract") + .argument(&code) + .argument(&opt_arg) + .original_result() + } + + pub fn deploy_two_contracts< + Arg0: ProxyArg>, + >( + self, + code: Arg0, + ) -> TxTypedCall, ManagedAddress>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("deploy_two_contracts") + .argument(&code) + .original_result() + } + + pub fn deploy_vault_from_source< + Arg0: ProxyArg>, + Arg1: ProxyArg>>, + >( + self, + source_address: Arg0, + opt_arg: Arg1, + ) -> TxTypedCall, OptionalValue>>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("deploy_vault_from_source") + .argument(&source_address) + .argument(&opt_arg) + .original_result() + } + + pub fn upgrade_vault< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>>, + >( + self, + child_sc_address: Arg0, + new_code: Arg1, + opt_arg: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("upgradeVault") + .argument(&child_sc_address) + .argument(&new_code) + .argument(&opt_arg) + .original_result() + } + + pub fn upgrade_vault_from_source< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>>, + >( + self, + child_sc_address: Arg0, + source_address: Arg1, + opt_arg: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("upgrade_vault_from_source") + .argument(&child_sc_address) + .argument(&source_address) + .argument(&opt_arg) + .original_result() + } + + pub fn get_fungible_esdt_balance< + Arg0: ProxyArg>, + >( + self, + token_identifier: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getFungibleEsdtBalance") + .argument(&token_identifier) + .original_result() + } + + pub fn get_current_nft_nonce< + Arg0: ProxyArg>, + >( + self, + token_identifier: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getCurrentNftNonce") + .argument(&token_identifier) + .original_result() + } + + pub fn send_esdt< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + >( + self, + to: Arg0, + token_id: Arg1, + amount: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("send_esdt") + .argument(&to) + .argument(&token_id) + .argument(&amount) + .original_result() + } + + pub fn send_esdt_with_fees< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + to: Arg0, + percentage_fees: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("send_esdt_with_fees") + .argument(&to) + .argument(&percentage_fees) + .original_result() + } + + pub fn send_esdt_twice< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + Arg3: ProxyArg>, + >( + self, + to: Arg0, + token_id: Arg1, + amount_first_time: Arg2, + amount_second_time: Arg3, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("send_esdt_twice") + .argument(&to) + .argument(&token_id) + .argument(&amount_first_time) + .argument(&amount_second_time) + .original_result() + } + + pub fn send_esdt_direct_multi_transfer< + Arg0: ProxyArg>, + Arg1: ProxyArg, u64, BigUint>>>, + >( + self, + to: Arg0, + token_payments: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("send_esdt_direct_multi_transfer") + .argument(&to) + .argument(&token_payments) + .original_result() + } + + pub fn issue_fungible_token< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + >( + self, + token_display_name: Arg0, + token_ticker: Arg1, + initial_supply: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("issue_fungible_token") + .argument(&token_display_name) + .argument(&token_ticker) + .argument(&initial_supply) + .original_result() + } + + pub fn local_mint< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + token_identifier: Arg0, + amount: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("local_mint") + .argument(&token_identifier) + .argument(&amount) + .original_result() + } + + pub fn local_burn< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + token_identifier: Arg0, + amount: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("local_burn") + .argument(&token_identifier) + .argument(&amount) + .original_result() + } + + pub fn get_esdt_local_roles< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("get_esdt_local_roles") + .argument(&token_id) + .original_result() + } + + pub fn get_esdt_token_data< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg, + >( + self, + address: Arg0, + token_id: Arg1, + nonce: Arg2, + ) -> TxTypedCall, bool, ManagedBuffer, ManagedBuffer, ManagedBuffer, ManagedAddress, BigUint, ManagedVec>>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("get_esdt_token_data") + .argument(&address) + .argument(&token_id) + .argument(&nonce) + .original_result() + } + + pub fn is_esdt_frozen< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg, + >( + self, + address: Arg0, + token_id: Arg1, + nonce: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("is_esdt_frozen") + .argument(&address) + .argument(&token_id) + .argument(&nonce) + .original_result() + } + + pub fn is_esdt_paused< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("is_esdt_paused") + .argument(&token_id) + .original_result() + } + + pub fn is_esdt_limited_transfer< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("is_esdt_limited_transfer") + .argument(&token_id) + .original_result() + } + + pub fn validate_token_identifier< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("validate_token_identifier") + .argument(&token_id) + .original_result() + } + + pub fn sft_issue< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + token_display_name: Arg0, + token_ticker: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("sft_issue") + .argument(&token_display_name) + .argument(&token_ticker) + .original_result() + } + + pub fn get_nft_balance< + Arg0: ProxyArg>, + Arg1: ProxyArg, + >( + self, + token_identifier: Arg0, + nonce: Arg1, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("get_nft_balance") + .argument(&token_identifier) + .argument(&nonce) + .original_result() + } + + pub fn buy_nft< + Arg0: ProxyArg>, + Arg1: ProxyArg, + Arg2: ProxyArg>, + >( + self, + nft_id: Arg0, + nft_nonce: Arg1, + nft_amount: Arg2, + ) -> TxTypedCall> { + self.wrapped_tx + .raw_call("buy_nft") + .argument(&nft_id) + .argument(&nft_nonce) + .argument(&nft_amount) + .original_result() + } + + pub fn nft_issue< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + token_display_name: Arg0, + token_ticker: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("nft_issue") + .argument(&token_display_name) + .argument(&token_ticker) + .original_result() + } + + pub fn nft_create< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + Arg3: ProxyArg>, + Arg4: ProxyArg>, + Arg5: ProxyArg, + Arg6: ProxyArg>, + >( + self, + token_identifier: Arg0, + amount: Arg1, + name: Arg2, + royalties: Arg3, + hash: Arg4, + color: Arg5, + uri: Arg6, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("nft_create") + .argument(&token_identifier) + .argument(&amount) + .argument(&name) + .argument(&royalties) + .argument(&hash) + .argument(&color) + .argument(&uri) + .original_result() + } + + pub fn nft_create_compact< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg, + >( + self, + token_identifier: Arg0, + amount: Arg1, + color: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("nft_create_compact") + .argument(&token_identifier) + .argument(&amount) + .argument(&color) + .original_result() + } + + pub fn nft_add_uris< + Arg0: ProxyArg>, + Arg1: ProxyArg, + Arg2: ProxyArg>>, + >( + self, + token_identifier: Arg0, + nonce: Arg1, + uris: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("nft_add_uris") + .argument(&token_identifier) + .argument(&nonce) + .argument(&uris) + .original_result() + } + + pub fn nft_update_attributes< + Arg0: ProxyArg>, + Arg1: ProxyArg, + Arg2: ProxyArg, + >( + self, + token_identifier: Arg0, + nonce: Arg1, + new_attributes: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("nft_update_attributes") + .argument(&token_identifier) + .argument(&nonce) + .argument(&new_attributes) + .original_result() + } + + pub fn nft_decode_complex_attributes< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + Arg3: ProxyArg>, + Arg4: ProxyArg>, + Arg5: ProxyArg>, + Arg6: ProxyArg, ManagedBuffer, TokenIdentifier, bool, ManagedBuffer>>, + >( + self, + token_identifier: Arg0, + amount: Arg1, + name: Arg2, + royalties: Arg3, + hash: Arg4, + uri: Arg5, + attrs_arg: Arg6, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("nft_decode_complex_attributes") + .argument(&token_identifier) + .argument(&amount) + .argument(&name) + .argument(&royalties) + .argument(&hash) + .argument(&uri) + .argument(&attrs_arg) + .original_result() + } + + pub fn nft_add_quantity< + Arg0: ProxyArg>, + Arg1: ProxyArg, + Arg2: ProxyArg>, + >( + self, + token_identifier: Arg0, + nonce: Arg1, + amount: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("nft_add_quantity") + .argument(&token_identifier) + .argument(&nonce) + .argument(&amount) + .original_result() + } + + pub fn nft_burn< + Arg0: ProxyArg>, + Arg1: ProxyArg, + Arg2: ProxyArg>, + >( + self, + token_identifier: Arg0, + nonce: Arg1, + amount: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("nft_burn") + .argument(&token_identifier) + .argument(&nonce) + .argument(&amount) + .original_result() + } + + pub fn transfer_nft_via_async_call< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg, + Arg3: ProxyArg>, + >( + self, + to: Arg0, + token_identifier: Arg1, + nonce: Arg2, + amount: Arg3, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("transfer_nft_via_async_call") + .argument(&to) + .argument(&token_identifier) + .argument(&nonce) + .argument(&amount) + .original_result() + } + + pub fn transfer_nft_and_execute< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg, + Arg3: ProxyArg>, + Arg4: ProxyArg>, + Arg5: ProxyArg>>, + >( + self, + to: Arg0, + token_identifier: Arg1, + nonce: Arg2, + amount: Arg3, + function: Arg4, + arguments: Arg5, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("transfer_nft_and_execute") + .argument(&to) + .argument(&token_identifier) + .argument(&nonce) + .argument(&amount) + .argument(&function) + .argument(&arguments) + .original_result() + } + + pub fn create_and_send< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + Arg3: ProxyArg>, + Arg4: ProxyArg>, + Arg5: ProxyArg>, + Arg6: ProxyArg, + Arg7: ProxyArg>, + >( + self, + to: Arg0, + token_identifier: Arg1, + amount: Arg2, + name: Arg3, + royalties: Arg4, + hash: Arg5, + color: Arg6, + uri: Arg7, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("create_and_send") + .argument(&to) + .argument(&token_identifier) + .argument(&amount) + .argument(&name) + .argument(&royalties) + .argument(&hash) + .argument(&color) + .argument(&uri) + .original_result() + } + + pub fn set_local_roles< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + >( + self, + address: Arg0, + token_identifier: Arg1, + roles: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("setLocalRoles") + .argument(&address) + .argument(&token_identifier) + .argument(&roles) + .original_result() + } + + pub fn unset_local_roles< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg>, + >( + self, + address: Arg0, + token_identifier: Arg1, + roles: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("unsetLocalRoles") + .argument(&address) + .argument(&token_identifier) + .argument(&roles) + .original_result() + } + + pub fn issue_dynamic_token< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + Arg2: ProxyArg, + Arg3: ProxyArg, + >( + self, + token_display_name: Arg0, + token_ticker: Arg1, + token_type: Arg2, + num_decimals: Arg3, + ) -> TxTypedCall { + self.wrapped_tx + .raw_call("issue_dynamic_token") + .argument(&token_display_name) + .argument(&token_ticker) + .argument(&token_type) + .argument(&num_decimals) + .original_result() + } + + pub fn change_to_dynamic< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("change_to_dynamic") + .argument(&token_id) + .original_result() + } + + pub fn update_token< + Arg0: ProxyArg>, + >( + self, + token_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("update_token") + .argument(&token_id) + .original_result() + } + + pub fn modify_royalties< + Arg0: ProxyArg>, + Arg1: ProxyArg, + Arg2: ProxyArg, + >( + self, + token_id: Arg0, + nonce: Arg1, + new_royalty: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("modify_royalties") + .argument(&token_id) + .argument(&nonce) + .argument(&new_royalty) + .original_result() + } + + pub fn set_new_uris< + Arg0: ProxyArg>, + Arg1: ProxyArg, + Arg2: ProxyArg>>, + >( + self, + token_id: Arg0, + nonce: Arg1, + new_uris: Arg2, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("set_new_uris") + .argument(&token_id) + .argument(&nonce) + .argument(&new_uris) + .original_result() + } + + pub fn modify_creator< + Arg0: ProxyArg>, + Arg1: ProxyArg, + >( + self, + token_id: Arg0, + nonce: Arg1, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("modify_creator") + .argument(&token_id) + .argument(&nonce) + .original_result() + } + + pub fn metadata_recreate< + Arg0: ProxyArg>, + Arg1: ProxyArg, + Arg2: ProxyArg>, + Arg3: ProxyArg, + Arg4: ProxyArg>, + Arg5: ProxyArg, + Arg6: ProxyArg>>, + >( + self, + token_id: Arg0, + nonce: Arg1, + name: Arg2, + royalties: Arg3, + hash: Arg4, + new_attributes: Arg5, + uris: Arg6, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("metadata_recreate") + .argument(&token_id) + .argument(&nonce) + .argument(&name) + .argument(&royalties) + .argument(&hash) + .argument(&new_attributes) + .argument(&uris) + .original_result() + } + + pub fn metadata_update< + Arg0: ProxyArg>, + Arg1: ProxyArg, + Arg2: ProxyArg>, + Arg3: ProxyArg, + Arg4: ProxyArg>, + Arg5: ProxyArg, + Arg6: ProxyArg>>, + >( + self, + token_id: Arg0, + nonce: Arg1, + name: Arg2, + royalties: Arg3, + hash: Arg4, + new_attributes: Arg5, + uris: Arg6, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("metadata_update") + .argument(&token_id) + .argument(&nonce) + .argument(&name) + .argument(&royalties) + .argument(&hash) + .argument(&new_attributes) + .argument(&uris) + .original_result() + } + + pub fn last_issued_token( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("lastIssuedToken") + .original_result() + } + + pub fn last_error_message( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("lastErrorMessage") + .original_result() + } +} + +#[type_abi] +#[derive(TopEncode, TopDecode, Debug)] +pub struct CallbackData +where + Api: ManagedTypeApi, +{ + pub callback_name: ManagedBuffer, + pub token_identifier: EgldOrEsdtTokenIdentifier, + pub token_nonce: u64, + pub token_amount: BigUint, + pub args: ManagedVec>, +} + +#[type_abi] +#[derive(TopEncode, TopDecode, Clone, Copy, PartialEq, Debug, Default)] +pub struct Color { + pub r: u8, + pub g: u8, + pub b: u8, +} diff --git a/contracts/feature-tests/composability/forwarder-interactor/state.toml b/contracts/feature-tests/composability/forwarder-interactor/state.toml new file mode 100644 index 0000000000..0bf61e6358 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/state.toml @@ -0,0 +1 @@ +contract_address = "erd1qqqqqqqqqqqqqpgqcr2nq237tg5vr3ezjvr750spkmtsjstjd8ssfp6eun" diff --git a/contracts/feature-tests/composability/forwarder-interactor/tests/interact_cs_tests.rs b/contracts/feature-tests/composability/forwarder-interactor/tests/interact_cs_tests.rs new file mode 100644 index 0000000000..b85fc01bf3 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/tests/interact_cs_tests.rs @@ -0,0 +1,15 @@ +use forwarder_interact::ContractInteract; +use multiversx_sc_snippets::imports::*; + +// Simple deploy test that runs using the chain simulator configuration. +// In order for this test to work, make sure that the `config.toml` file contains the chain simulator config (or choose it manually) +// The chain simulator should already be installed and running before attempting to run this test. +// The chain-simulator-tests feature should be present in Cargo.toml. +// Can be run with `sc-meta test -c`. +#[tokio::test] +#[cfg_attr(not(feature = "chain-simulator-tests"), ignore)] +async fn deploy_test_forwarder_cs() { + let mut interactor = ContractInteract::new().await; + + interactor.deploy().await; +} diff --git a/contracts/feature-tests/composability/forwarder-interactor/tests/interact_tests.rs b/contracts/feature-tests/composability/forwarder-interactor/tests/interact_tests.rs new file mode 100644 index 0000000000..2005f0176f --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/tests/interact_tests.rs @@ -0,0 +1,13 @@ +use forwarder_interact::ContractInteract; +use multiversx_sc_snippets::imports::*; + +// Simple deploy test that runs on the real blockchain configuration. +// In order for this test to work, make sure that the `config.toml` file contains the real blockchain config (or choose it manually) +// Can be run with `sc-meta test`. +#[tokio::test] +#[ignore = "run on demand, relies on real blockchain state"] +async fn deploy_test_forwarder() { + let mut interactor = ContractInteract::new().await; + + interactor.deploy().await; +} diff --git a/contracts/feature-tests/composability/forwarder/sc-config.toml b/contracts/feature-tests/composability/forwarder/sc-config.toml index b78f0086a5..5974cd2dbf 100644 --- a/contracts/feature-tests/composability/forwarder/sc-config.toml +++ b/contracts/feature-tests/composability/forwarder/sc-config.toml @@ -1,2 +1,6 @@ [[proxy]] path = "src/forwarder_proxy.rs" + +[[proxy]] +path = "../forwarder-interactor/src/proxy.rs" + diff --git a/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs b/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs index 964df0bf23..b27ce77f88 100644 --- a/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs +++ b/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs @@ -1354,7 +1354,7 @@ where } #[type_abi] -#[derive(TopEncode, TopDecode)] +#[derive(TopEncode, TopDecode, Debug)] pub struct CallbackData where Api: ManagedTypeApi, @@ -1367,7 +1367,7 @@ where } #[type_abi] -#[derive(TopEncode, TopDecode, Clone, Copy, PartialEq, Debug)] +#[derive(TopEncode, TopDecode, Clone, Copy, PartialEq, Debug, Default)] pub struct Color { pub r: u8, pub g: u8, diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_call_async.rs b/contracts/feature-tests/composability/forwarder/src/fwd_call_async.rs index 5492a45a10..463cd26465 100644 --- a/contracts/feature-tests/composability/forwarder/src/fwd_call_async.rs +++ b/contracts/feature-tests/composability/forwarder/src/fwd_call_async.rs @@ -4,7 +4,7 @@ multiversx_sc::imports!(); multiversx_sc::derive_imports!(); #[type_abi] -#[derive(TopEncode, TopDecode)] +#[derive(TopEncode, TopDecode, Debug)] pub struct CallbackData { callback_name: ManagedBuffer, token_identifier: EgldOrEsdtTokenIdentifier, diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_nft.rs b/contracts/feature-tests/composability/forwarder/src/fwd_nft.rs index 5358397df9..53f01ec5ea 100644 --- a/contracts/feature-tests/composability/forwarder/src/fwd_nft.rs +++ b/contracts/feature-tests/composability/forwarder/src/fwd_nft.rs @@ -5,7 +5,7 @@ use super::fwd_storage; // used as mock attributes for NFTs #[type_abi] -#[derive(TopEncode, TopDecode, Clone, Copy, PartialEq, Debug)] +#[derive(TopEncode, TopDecode, Clone, Copy, PartialEq, Debug, Default)] pub struct Color { pub r: u8, pub g: u8, @@ -13,7 +13,7 @@ pub struct Color { } #[type_abi] -#[derive(TopEncode, TopDecode, PartialEq, Eq, Clone)] +#[derive(TopEncode, TopDecode, PartialEq, Eq, Clone, Debug)] pub struct ComplexAttributes { pub biguint: BigUint, pub vec_u8: ManagedBuffer,