From 04997020dbeaa242a08de28bba5bbfb7983cd0cd Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 29 Nov 2024 21:30:27 +0100 Subject: [PATCH 01/17] initial implementation dynamic esdts --- chain/core/src/builtin_func_names.rs | 6 + chain/core/src/types/flags/esdt_local_role.rs | 47 +++++- .../src/types/flags/esdt_local_role_flags.rs | 5 + chain/core/src/types/flags/esdt_token_type.rs | 30 +++- .../contract_base/wrappers/send_wrapper.rs | 82 +++++++++++ .../system_proxy/builtin_func_proxy.rs | 138 +++++++++++++++++- .../system_proxy/esdt_system_sc_proxy.rs | 26 +++- .../system_proxy/legacy_system_sc_proxy.rs | 38 +++-- 8 files changed, 355 insertions(+), 17 deletions(-) diff --git a/chain/core/src/builtin_func_names.rs b/chain/core/src/builtin_func_names.rs index 108ed29016..51777f201b 100644 --- a/chain/core/src/builtin_func_names.rs +++ b/chain/core/src/builtin_func_names.rs @@ -14,3 +14,9 @@ pub const SET_USERNAME_FUNC_NAME: &str = "SetUserName"; pub const MIGRATE_USERNAME_FUNC_NAME: &str = "migrateUserName"; pub const DELETE_USERNAME_FUNC_NAME: &str = "DeleteUserName"; pub const UPGRADE_CONTRACT_FUNC_NAME: &str = "upgradeContract"; +pub const ESDT_SET_TOKEN_TYPE_FUNC_NAME: &str = "ESDTSetTokenType"; +pub const ESDT_MODIFY_ROYALTIES_FUNC_NAME: &str = "ESDTModifyRoyalties"; +pub const ESDT_SET_NEW_URIS_FUNC_NAME: &str = "ESDTSetNewURIs"; +pub const ESDT_MODIFY_CREATOR_FUNC_NAME: &str = "ESDTModifyCreator"; +pub const ESDT_METADATA_RECREATE_FUNC_NAME: &str = "ESDTMetaDataRecreate"; +pub const ESDT_METADATA_UPDATE_FUNC_NAME: &str = "ESDTMetaDataUpdate"; diff --git a/chain/core/src/types/flags/esdt_local_role.rs b/chain/core/src/types/flags/esdt_local_role.rs index 048d3876ce..3634e5d891 100644 --- a/chain/core/src/types/flags/esdt_local_role.rs +++ b/chain/core/src/types/flags/esdt_local_role.rs @@ -13,6 +13,11 @@ const ESDT_ROLE_NFT_BURN: &str = "ESDTRoleNFTBurn"; const ESDT_ROLE_NFT_ADD_URI: &str = "ESDTRoleNFTAddURI"; const ESDT_ROLE_NFT_UPDATE_ATTRIBUTES: &str = "ESDTRoleNFTUpdateAttributes"; const ESDT_ROLE_TRANSFER: &str = "ESDTTransferRole"; +const ESDT_ROLE_SET_NEW_URI: &str = "ESDTRoleSetNewURI"; +const ESDT_ROLE_MODIFY_ROYALTIES: &str = "ESDTRoleModifyRoyalties"; +const ESDT_ROLE_MODIFY_CREATOR: &str = "ESDTRoleModifyCreator"; +const ESDT_ROLE_NFT_RECREATE: &str = "ESDTRoleNFTRecreate"; +const ESDT_ROLE_NFT_UPDATE: &str = "ESDTRoleNFTUpdate"; #[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug, Copy)] pub enum EsdtLocalRole { @@ -25,6 +30,11 @@ pub enum EsdtLocalRole { NftAddUri, NftUpdateAttributes, Transfer, + SetNewUri, + ModifyRoyalties, + ModifyCreator, + NftRecreate, + NftUpdate, } impl EsdtLocalRole { @@ -39,6 +49,11 @@ impl EsdtLocalRole { Self::NftAddUri => 6, Self::NftUpdateAttributes => 7, Self::Transfer => 8, + Self::SetNewUri => 9, + Self::ModifyRoyalties => 10, + Self::ModifyCreator => 11, + Self::NftRecreate => 12, + Self::NftUpdate => 13, } } @@ -57,6 +72,11 @@ impl EsdtLocalRole { Self::NftAddUri => ESDT_ROLE_NFT_ADD_URI, Self::NftUpdateAttributes => ESDT_ROLE_NFT_UPDATE_ATTRIBUTES, Self::Transfer => ESDT_ROLE_TRANSFER, + Self::SetNewUri => ESDT_ROLE_SET_NEW_URI, + Self::ModifyRoyalties => ESDT_ROLE_MODIFY_ROYALTIES, + Self::ModifyCreator => ESDT_ROLE_MODIFY_CREATOR, + Self::NftRecreate => ESDT_ROLE_NFT_RECREATE, + Self::NftUpdate => ESDT_ROLE_NFT_UPDATE, } } @@ -71,13 +91,18 @@ impl EsdtLocalRole { Self::NftAddUri => EsdtLocalRoleFlags::NFT_ADD_URI, Self::NftUpdateAttributes => EsdtLocalRoleFlags::NFT_UPDATE_ATTRIBUTES, Self::Transfer => EsdtLocalRoleFlags::TRANSFER, + Self::SetNewUri => EsdtLocalRoleFlags::SET_NEW_URI, + Self::ModifyRoyalties => EsdtLocalRoleFlags::MODIFY_ROYALTIES, + Self::ModifyCreator => EsdtLocalRoleFlags::MODIFY_CREATOR, + Self::NftRecreate => EsdtLocalRoleFlags::NFT_RECREATE, + Self::NftUpdate => EsdtLocalRoleFlags::NFT_UPDATE, } } } // TODO: can be done with macros, but I didn't find a public library that does it and is no_std // we can implement it, it's easy -const ALL_ROLES: [EsdtLocalRole; 8] = [ +const ALL_ROLES: [EsdtLocalRole; 13] = [ EsdtLocalRole::Mint, EsdtLocalRole::Burn, EsdtLocalRole::NftCreate, @@ -86,6 +111,11 @@ const ALL_ROLES: [EsdtLocalRole; 8] = [ EsdtLocalRole::NftAddUri, EsdtLocalRole::NftUpdateAttributes, EsdtLocalRole::Transfer, + EsdtLocalRole::SetNewUri, + EsdtLocalRole::ModifyRoyalties, + EsdtLocalRole::ModifyCreator, + EsdtLocalRole::NftRecreate, + EsdtLocalRole::NftUpdate, ]; impl EsdtLocalRole { @@ -106,6 +136,11 @@ impl From for EsdtLocalRole { 6 => Self::NftAddUri, 7 => Self::NftUpdateAttributes, 8 => Self::Transfer, + 9 => Self::SetNewUri, + 10 => Self::ModifyRoyalties, + 11 => Self::ModifyCreator, + 12 => Self::NftRecreate, + 13 => Self::NftUpdate, _ => Self::None, } } @@ -130,6 +165,16 @@ impl<'a> From<&'a [u8]> for EsdtLocalRole { Self::NftUpdateAttributes } else if byte_slice == ESDT_ROLE_TRANSFER.as_bytes() { Self::Transfer + } else if byte_slice == ESDT_ROLE_SET_NEW_URI.as_bytes() { + Self::SetNewUri + } else if byte_slice == ESDT_ROLE_MODIFY_ROYALTIES.as_bytes() { + Self::ModifyRoyalties + } else if byte_slice == ESDT_ROLE_MODIFY_CREATOR.as_bytes() { + Self::ModifyCreator + } else if byte_slice == ESDT_ROLE_NFT_RECREATE.as_bytes() { + Self::NftRecreate + } else if byte_slice == ESDT_ROLE_NFT_UPDATE.as_bytes() { + Self::NftUpdate } else { Self::None } diff --git a/chain/core/src/types/flags/esdt_local_role_flags.rs b/chain/core/src/types/flags/esdt_local_role_flags.rs index 29be64aba2..cac9aa6795 100644 --- a/chain/core/src/types/flags/esdt_local_role_flags.rs +++ b/chain/core/src/types/flags/esdt_local_role_flags.rs @@ -15,6 +15,11 @@ bitflags! { const NFT_ADD_URI = 0b00100000; const NFT_UPDATE_ATTRIBUTES = 0b01000000; const TRANSFER = 0b10000000; + const SET_NEW_URI = 0b00000001_00000000; + const MODIFY_ROYALTIES = 0b00000010_00000000; + const MODIFY_CREATOR = 0b00000100_00000000; + const NFT_RECREATE = 0b00001000_00000000; + const NFT_UPDATE = 0b00010000_00000000; } } diff --git a/chain/core/src/types/flags/esdt_token_type.rs b/chain/core/src/types/flags/esdt_token_type.rs index 74db07c9a6..bfa2b07192 100644 --- a/chain/core/src/types/flags/esdt_token_type.rs +++ b/chain/core/src/types/flags/esdt_token_type.rs @@ -9,6 +9,10 @@ const ESDT_TYPE_FUNGIBLE: &[u8] = b"FungibleESDT"; const ESDT_TYPE_NON_FUNGIBLE: &[u8] = b"NonFungibleESDT"; const ESDT_TYPE_SEMI_FUNGIBLE: &[u8] = b"SemiFungibleESDT"; const ESDT_TYPE_META: &[u8] = b"MetaESDT"; +const ESDT_TYPE_NON_FUNGIBLE_V2: &[u8] = b"NonFungibleESDTv2"; +const ESDT_TYPE_DYNAMIC_NON_FUNGIBLE: &[u8] = b"DynamicNonFungibleESDT"; +const ESDT_TYPE_DYNAMIC_SEMI_FUNGIBLE: &[u8] = b"DynamicSemiFungibleESDT"; +const ESDT_TYPE_DYNAMIC_META: &[u8] = b"DynamicMetaESDT"; const ESDT_TYPE_INVALID: &[u8] = &[]; // Note: In the current implementation, SemiFungible is never returned @@ -19,6 +23,10 @@ pub enum EsdtTokenType { NonFungible, SemiFungible, Meta, + NonFungibleV2, + DynamicNFT, + DynamicSFT, + DynamicMeta, Invalid, } @@ -37,7 +45,11 @@ impl EsdtTokenType { Self::NonFungible => 1, Self::SemiFungible => 2, Self::Meta => 3, - Self::Invalid => 4, + Self::NonFungibleV2 => 4, + Self::DynamicNFT => 5, + Self::DynamicSFT => 6, + Self::DynamicMeta => 7, + Self::Invalid => 8, } } @@ -47,6 +59,10 @@ impl EsdtTokenType { Self::NonFungible => ESDT_TYPE_NON_FUNGIBLE, Self::SemiFungible => ESDT_TYPE_SEMI_FUNGIBLE, Self::Meta => ESDT_TYPE_META, + Self::NonFungibleV2 => ESDT_TYPE_NON_FUNGIBLE_V2, + Self::DynamicNFT => ESDT_TYPE_DYNAMIC_NON_FUNGIBLE, + Self::DynamicSFT => ESDT_TYPE_DYNAMIC_SEMI_FUNGIBLE, + Self::DynamicMeta => ESDT_TYPE_DYNAMIC_META, Self::Invalid => ESDT_TYPE_INVALID, } } @@ -60,6 +76,10 @@ impl From for EsdtTokenType { 1 => Self::NonFungible, 2 => Self::SemiFungible, 3 => Self::Meta, + 4 => Self::NonFungibleV2, + 5 => Self::DynamicNFT, + 6 => Self::DynamicSFT, + 7 => Self::DynamicMeta, _ => Self::Invalid, } } @@ -76,6 +96,14 @@ impl<'a> From<&'a [u8]> for EsdtTokenType { Self::SemiFungible } else if byte_slice == ESDT_TYPE_META { Self::Meta + } else if byte_slice == ESDT_TYPE_NON_FUNGIBLE_V2 { + Self::NonFungibleV2 + } else if byte_slice == ESDT_TYPE_DYNAMIC_NON_FUNGIBLE { + Self::DynamicNFT + } else if byte_slice == ESDT_TYPE_DYNAMIC_SEMI_FUNGIBLE { + Self::DynamicSFT + } else if byte_slice == ESDT_TYPE_DYNAMIC_META { + Self::DynamicMeta } else { Self::Invalid } diff --git a/framework/base/src/contract_base/wrappers/send_wrapper.rs b/framework/base/src/contract_base/wrappers/send_wrapper.rs index 0c23b67cd4..468d75c92c 100644 --- a/framework/base/src/contract_base/wrappers/send_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/send_wrapper.rs @@ -1,5 +1,7 @@ use core::marker::PhantomData; +use multiversx_chain_core::types::EsdtTokenType; + use crate::codec::Empty; use crate::types::ManagedRef; @@ -763,4 +765,84 @@ where .nft_update_attributes(token_id, nft_nonce, new_attributes) .sync_call() } + + /// Sets the token type for a specific token. + pub fn esdt_set_token_type(&self, token_id: &TokenIdentifier, token_type: EsdtTokenType) { + Tx::new_tx_from_sc() + .to(ToSelf) + .gas(GasLeft) + .typed(system_proxy::UserBuiltinProxy) + .esdt_set_token_type(token_id, token_type) + .sync_call() + } + + /// Modifies royalties for a specific token. + pub fn esdt_modify_royalties( + &self, + token_id: &TokenIdentifier, + nonce: u64, + new_royalty: u64, + ) { + Tx::new_tx_from_sc() + .to(ToSelf) + .gas(GasLeft) + .typed(system_proxy::UserBuiltinProxy) + .esdt_modify_royalties(token_id, nonce, new_royalty) + .sync_call() + } + + /// Sets new uris for a specific token. + pub fn esdt_nft_set_new_uris( + &self, + token_id: &TokenIdentifier, + nonce: u64, + uris: &ManagedVec>, + ) { + Tx::new_tx_from_sc() + .to(ToSelf) + .gas(GasLeft) + .typed(system_proxy::UserBuiltinProxy) + .esdt_nft_set_new_uris(token_id, nonce, uris) + .sync_call() + } + + /// Changes the creator of a specific token into the caller. + pub fn esdt_nft_modify_creator(&self, token_id: &TokenIdentifier, nonce: u64) { + Tx::new_tx_from_sc() + .to(ToSelf) + .gas(GasLeft) + .typed(system_proxy::UserBuiltinProxy) + .esdt_nft_modify_creator(token_id, nonce) + .sync_call() + } + + /// Recreates an ESDT token with the newly specified attributes. + pub fn esdt_metadata_recreate( + &self, + token_id: TokenIdentifier, + nonce: u64, + new_attributes: &T, + ) { + Tx::new_tx_from_sc() + .to(ToSelf) + .gas(GasLeft) + .typed(system_proxy::UserBuiltinProxy) + .esdt_metadata_recreate(token_id, nonce, new_attributes) + .sync_call() + } + + /// Updates an ESDT token with the newly specified attributes. + pub fn esdt_metadata_update( + &self, + token_id: &TokenIdentifier, + nonce: u64, + new_attributes: &T, + ) { + Tx::new_tx_from_sc() + .to(ToSelf) + .gas(GasLeft) + .typed(system_proxy::UserBuiltinProxy) + .esdt_metadata_update(token_id, nonce, new_attributes) + .sync_call() + } } diff --git a/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs b/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs index 1bf7c3a1fc..1612965f4b 100644 --- a/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs @@ -1,15 +1,17 @@ use multiversx_sc_codec::{Empty, TopEncode}; use crate::types::{ - BigUint, ManagedAddress, ManagedBuffer, ManagedVec, NotPayable, ProxyArg, TokenIdentifier, Tx, - TxEnv, TxFrom, TxGas, TxProxyTrait, TxTo, TxTypedCall, + BigUint, EsdtTokenType, ManagedAddress, ManagedBuffer, ManagedVec, NotPayable, ProxyArg, + TokenIdentifier, Tx, TxEnv, TxFrom, TxGas, TxProxyTrait, TxTo, TxTypedCall, }; use crate::chain_core::builtin_func_names::{ CHANGE_OWNER_BUILTIN_FUNC_NAME, CLAIM_DEVELOPER_REWARDS_FUNC_NAME, DELETE_USERNAME_FUNC_NAME, - ESDT_LOCAL_BURN_FUNC_NAME, ESDT_LOCAL_MINT_FUNC_NAME, ESDT_NFT_ADD_QUANTITY_FUNC_NAME, - ESDT_NFT_ADD_URI_FUNC_NAME, ESDT_NFT_BURN_FUNC_NAME, ESDT_NFT_CREATE_FUNC_NAME, - ESDT_NFT_UPDATE_ATTRIBUTES_FUNC_NAME, SET_USERNAME_FUNC_NAME, + ESDT_LOCAL_BURN_FUNC_NAME, ESDT_LOCAL_MINT_FUNC_NAME, ESDT_METADATA_RECREATE_FUNC_NAME, + ESDT_METADATA_UPDATE_FUNC_NAME, ESDT_MODIFY_CREATOR_FUNC_NAME, ESDT_MODIFY_ROYALTIES_FUNC_NAME, + ESDT_NFT_ADD_QUANTITY_FUNC_NAME, ESDT_NFT_ADD_URI_FUNC_NAME, ESDT_NFT_BURN_FUNC_NAME, + ESDT_NFT_CREATE_FUNC_NAME, ESDT_NFT_UPDATE_ATTRIBUTES_FUNC_NAME, ESDT_SET_NEW_URIS_FUNC_NAME, + ESDT_SET_TOKEN_TYPE_FUNC_NAME, SET_USERNAME_FUNC_NAME, }; /// Proxy describing the user builtin function signatures. @@ -214,4 +216,130 @@ where tx.original_result() } + + pub fn esdt_set_token_type< + Arg0: ProxyArg>, + Arg1: ProxyArg, + >( + self, + token_id: Arg0, + token_type: Arg1, + ) -> TxTypedCall { + let tx = self + .wrapped_tx + .payment(NotPayable) + .raw_call(ESDT_SET_TOKEN_TYPE_FUNC_NAME) + .argument(&token_id) + .argument(&token_type); + + tx.original_result() + } + + pub fn esdt_modify_royalties< + Arg0: ProxyArg>, + Arg1: ProxyArg, + Arg2: ProxyArg, + >( + self, + token_id: Arg0, + nonce: Arg1, + new_royalty: Arg2, + ) -> TxTypedCall { + let tx = self + .wrapped_tx + .payment(NotPayable) + .raw_call(ESDT_MODIFY_ROYALTIES_FUNC_NAME) + .argument(&token_id) + .argument(&nonce) + .argument(&new_royalty); + + tx.original_result() + } + + pub fn esdt_nft_set_new_uris>, Arg1: ProxyArg>( + self, + token_id: Arg0, + nonce: Arg1, + uris: &ManagedVec>, + ) -> TxTypedCall { + let mut tx = self + .wrapped_tx + .payment(NotPayable) + .raw_call(ESDT_SET_NEW_URIS_FUNC_NAME) + .argument(&token_id) + .argument(&nonce); + + if uris.is_empty() { + // at least one URI is required, so we push an empty one + tx = tx.argument(&Empty); + } else { + // The API function has the last argument as variadic, + // so we top-encode each and send as separate argument + for uri in uris { + tx = tx.argument(&uri); + } + } + + tx.original_result() + } + + pub fn esdt_nft_modify_creator< + Arg0: ProxyArg>, + Arg1: ProxyArg, + >( + self, + token_id: Arg0, + nonce: Arg1, + ) -> TxTypedCall { + let tx = self + .wrapped_tx + .payment(NotPayable) + .raw_call(ESDT_MODIFY_CREATOR_FUNC_NAME) + .argument(&token_id) + .argument(&nonce); + + tx.original_result() + } + + pub fn esdt_metadata_recreate< + T: TopEncode, + Arg0: ProxyArg>, + Arg1: ProxyArg, + >( + self, + token_id: Arg0, + nonce: Arg1, + new_attributes: &T, + ) -> TxTypedCall { + let tx = self + .wrapped_tx + .payment(NotPayable) + .raw_call(ESDT_METADATA_RECREATE_FUNC_NAME) + .argument(&token_id) + .argument(&nonce) + .argument(&new_attributes); + + tx.original_result() + } + + pub fn esdt_metadata_update< + T: TopEncode, + Arg0: ProxyArg>, + Arg1: ProxyArg, + >( + self, + token_id: Arg0, + nonce: Arg1, + new_attributes: &T, + ) -> TxTypedCall { + let tx = self + .wrapped_tx + .payment(NotPayable) + .raw_call(ESDT_METADATA_UPDATE_FUNC_NAME) + .argument(&token_id) + .argument(&nonce) + .argument(&new_attributes); + + tx.original_result() + } } diff --git a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs index 979f9d1d60..a68950b0f9 100644 --- a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs @@ -14,6 +14,8 @@ const ISSUE_NON_FUNGIBLE_ENDPOINT_NAME: &str = "issueNonFungible"; const ISSUE_SEMI_FUNGIBLE_ENDPOINT_NAME: &str = "issueSemiFungible"; const REGISTER_META_ESDT_ENDPOINT_NAME: &str = "registerMetaESDT"; const ISSUE_AND_SET_ALL_ROLES_ENDPOINT_NAME: &str = "registerAndSetAllRoles"; +const REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME: &str = "registerDynamic"; +const REGISTER_AND_SET_ALL_ROLES_DYNAMIC_ESDT_ENDPOINT_NAME: &str = "registerAndSetAllRolesDynamic"; /// The specific `Tx` type produces by the issue operations of the ESDTSystemSCProxy. pub type IssueCall = Tx< @@ -214,11 +216,29 @@ where EsdtTokenType::NonFungible => "NFT", EsdtTokenType::SemiFungible => "SFT", EsdtTokenType::Meta => "META", + EsdtTokenType::NonFungibleV2 => "NFT", + EsdtTokenType::DynamicNFT => "NFT", + EsdtTokenType::DynamicSFT => "SFT", + EsdtTokenType::DynamicMeta => "META", + EsdtTokenType::Invalid => "", + }; + + let endpoint = match token_type { + EsdtTokenType::Fungible + | EsdtTokenType::NonFungible + | EsdtTokenType::SemiFungible + | EsdtTokenType::Meta => ISSUE_AND_SET_ALL_ROLES_ENDPOINT_NAME, + + EsdtTokenType::NonFungibleV2 + | EsdtTokenType::DynamicNFT + | EsdtTokenType::DynamicSFT + | EsdtTokenType::DynamicMeta => REGISTER_AND_SET_ALL_ROLES_DYNAMIC_ESDT_ENDPOINT_NAME, + EsdtTokenType::Invalid => "", }; self.wrapped_tx - .raw_call(ISSUE_AND_SET_ALL_ROLES_ENDPOINT_NAME) + .raw_call(endpoint) .egld(issue_cost) .argument(&token_display_name) .argument(&token_ticker) @@ -246,6 +266,10 @@ where EsdtTokenType::NonFungible => ISSUE_NON_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::SemiFungible => ISSUE_SEMI_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::Meta => REGISTER_META_ESDT_ENDPOINT_NAME, + EsdtTokenType::NonFungibleV2 + | EsdtTokenType::DynamicNFT + | EsdtTokenType::DynamicSFT + | EsdtTokenType::DynamicMeta => REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME, EsdtTokenType::Invalid => "", }; diff --git a/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs index 6f74b80812..4af1f5b9b2 100644 --- a/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs @@ -17,6 +17,8 @@ const ISSUE_NON_FUNGIBLE_ENDPOINT_NAME: &str = "issueNonFungible"; const ISSUE_SEMI_FUNGIBLE_ENDPOINT_NAME: &str = "issueSemiFungible"; const REGISTER_META_ESDT_ENDPOINT_NAME: &str = "registerMetaESDT"; const ISSUE_AND_SET_ALL_ROLES_ENDPOINT_NAME: &str = "registerAndSetAllRoles"; +const REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME: &str = "registerDynamic"; +const REGISTER_AND_SET_ALL_ROLES_DYNAMIC_ESDT_ENDPOINT_NAME: &str = "registerAndSetAllRolesDynamic"; /// Proxy for the ESDT system smart contract. /// Unlike other contract proxies, this one has a fixed address, @@ -188,18 +190,32 @@ where EsdtTokenType::NonFungible => "NFT", EsdtTokenType::SemiFungible => "SFT", EsdtTokenType::Meta => "META", + EsdtTokenType::NonFungibleV2 => "NFT", + EsdtTokenType::DynamicNFT => "NFT", + EsdtTokenType::DynamicSFT => "SFT", + EsdtTokenType::DynamicMeta => "META", EsdtTokenType::Invalid => "", }; - ContractCallWithEgld::new( - esdt_system_sc_address, - ISSUE_AND_SET_ALL_ROLES_ENDPOINT_NAME, - issue_cost, - ) - .argument(&token_display_name) - .argument(&token_ticker) - .argument(&token_type_name) - .argument(&num_decimals) + let endpoint = match token_type { + EsdtTokenType::Fungible + | EsdtTokenType::NonFungible + | EsdtTokenType::SemiFungible + | EsdtTokenType::Meta => ISSUE_AND_SET_ALL_ROLES_ENDPOINT_NAME, + + EsdtTokenType::NonFungibleV2 + | EsdtTokenType::DynamicNFT + | EsdtTokenType::DynamicSFT + | EsdtTokenType::DynamicMeta => REGISTER_AND_SET_ALL_ROLES_DYNAMIC_ESDT_ENDPOINT_NAME, + + EsdtTokenType::Invalid => "", + }; + + ContractCallWithEgld::new(esdt_system_sc_address, endpoint, issue_cost) + .argument(&token_display_name) + .argument(&token_ticker) + .argument(&token_type_name) + .argument(&num_decimals) } /// Deduplicates code from all the possible issue functions @@ -219,6 +235,10 @@ where EsdtTokenType::NonFungible => ISSUE_NON_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::SemiFungible => ISSUE_SEMI_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::Meta => REGISTER_META_ESDT_ENDPOINT_NAME, + EsdtTokenType::NonFungibleV2 + | EsdtTokenType::DynamicNFT + | EsdtTokenType::DynamicSFT + | EsdtTokenType::DynamicMeta => REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME, EsdtTokenType::Invalid => "", }; From d03613b21781ac909ea21b4340baea6c8c40a720 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 29 Nov 2024 21:41:50 +0100 Subject: [PATCH 02/17] nftv2 moved to old endpoint --- .../system_proxy/esdt_system_sc_proxy.rs | 31 +++++++++---------- .../system_proxy/legacy_system_sc_proxy.rs | 31 +++++++++---------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs index a68950b0f9..87e4e1fd7b 100644 --- a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs @@ -213,26 +213,24 @@ where ) -> IssueCall { let token_type_name = match token_type { EsdtTokenType::Fungible => "FNG", - EsdtTokenType::NonFungible => "NFT", - EsdtTokenType::SemiFungible => "SFT", - EsdtTokenType::Meta => "META", - EsdtTokenType::NonFungibleV2 => "NFT", - EsdtTokenType::DynamicNFT => "NFT", - EsdtTokenType::DynamicSFT => "SFT", - EsdtTokenType::DynamicMeta => "META", + EsdtTokenType::NonFungible + | EsdtTokenType::NonFungibleV2 + | EsdtTokenType::DynamicNFT => "NFT", + EsdtTokenType::SemiFungible | EsdtTokenType::DynamicSFT => "SFT", + EsdtTokenType::Meta | EsdtTokenType::DynamicMeta => "META", EsdtTokenType::Invalid => "", }; let endpoint = match token_type { EsdtTokenType::Fungible | EsdtTokenType::NonFungible + | EsdtTokenType::NonFungibleV2 | EsdtTokenType::SemiFungible | EsdtTokenType::Meta => ISSUE_AND_SET_ALL_ROLES_ENDPOINT_NAME, - EsdtTokenType::NonFungibleV2 - | EsdtTokenType::DynamicNFT - | EsdtTokenType::DynamicSFT - | EsdtTokenType::DynamicMeta => REGISTER_AND_SET_ALL_ROLES_DYNAMIC_ESDT_ENDPOINT_NAME, + EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { + REGISTER_AND_SET_ALL_ROLES_DYNAMIC_ESDT_ENDPOINT_NAME + }, EsdtTokenType::Invalid => "", }; @@ -263,13 +261,14 @@ where ) -> IssueCall { let endpoint_name = match token_type { EsdtTokenType::Fungible => ISSUE_FUNGIBLE_ENDPOINT_NAME, - EsdtTokenType::NonFungible => ISSUE_NON_FUNGIBLE_ENDPOINT_NAME, + EsdtTokenType::NonFungible | EsdtTokenType::NonFungibleV2 => { + ISSUE_NON_FUNGIBLE_ENDPOINT_NAME + }, EsdtTokenType::SemiFungible => ISSUE_SEMI_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::Meta => REGISTER_META_ESDT_ENDPOINT_NAME, - EsdtTokenType::NonFungibleV2 - | EsdtTokenType::DynamicNFT - | EsdtTokenType::DynamicSFT - | EsdtTokenType::DynamicMeta => REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME, + EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { + REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME + }, EsdtTokenType::Invalid => "", }; diff --git a/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs index 4af1f5b9b2..54b685e61d 100644 --- a/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs @@ -187,26 +187,24 @@ where let token_type_name = match token_type { EsdtTokenType::Fungible => "FNG", - EsdtTokenType::NonFungible => "NFT", - EsdtTokenType::SemiFungible => "SFT", - EsdtTokenType::Meta => "META", - EsdtTokenType::NonFungibleV2 => "NFT", - EsdtTokenType::DynamicNFT => "NFT", - EsdtTokenType::DynamicSFT => "SFT", - EsdtTokenType::DynamicMeta => "META", + EsdtTokenType::NonFungible + | EsdtTokenType::NonFungibleV2 + | EsdtTokenType::DynamicNFT => "NFT", + EsdtTokenType::SemiFungible | EsdtTokenType::DynamicSFT => "SFT", + EsdtTokenType::Meta | EsdtTokenType::DynamicMeta => "META", EsdtTokenType::Invalid => "", }; let endpoint = match token_type { EsdtTokenType::Fungible | EsdtTokenType::NonFungible + | EsdtTokenType::NonFungibleV2 | EsdtTokenType::SemiFungible | EsdtTokenType::Meta => ISSUE_AND_SET_ALL_ROLES_ENDPOINT_NAME, - EsdtTokenType::NonFungibleV2 - | EsdtTokenType::DynamicNFT - | EsdtTokenType::DynamicSFT - | EsdtTokenType::DynamicMeta => REGISTER_AND_SET_ALL_ROLES_DYNAMIC_ESDT_ENDPOINT_NAME, + EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { + REGISTER_AND_SET_ALL_ROLES_DYNAMIC_ESDT_ENDPOINT_NAME + }, EsdtTokenType::Invalid => "", }; @@ -232,13 +230,14 @@ where let endpoint_name = match token_type { EsdtTokenType::Fungible => ISSUE_FUNGIBLE_ENDPOINT_NAME, - EsdtTokenType::NonFungible => ISSUE_NON_FUNGIBLE_ENDPOINT_NAME, + EsdtTokenType::NonFungible | EsdtTokenType::NonFungibleV2 => { + ISSUE_NON_FUNGIBLE_ENDPOINT_NAME + }, EsdtTokenType::SemiFungible => ISSUE_SEMI_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::Meta => REGISTER_META_ESDT_ENDPOINT_NAME, - EsdtTokenType::NonFungibleV2 - | EsdtTokenType::DynamicNFT - | EsdtTokenType::DynamicSFT - | EsdtTokenType::DynamicMeta => REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME, + EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { + REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME + }, EsdtTokenType::Invalid => "", }; From 20f60369d7952740cc51c6f34fa08f828363a736 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 2 Dec 2024 16:18:38 +0100 Subject: [PATCH 03/17] remove nftv2 --- chain/core/src/types/flags/esdt_token_type.rs | 21 +++++++------------ .../system_proxy/esdt_system_sc_proxy.rs | 10 ++------- .../system_proxy/legacy_system_sc_proxy.rs | 9 ++------ 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/chain/core/src/types/flags/esdt_token_type.rs b/chain/core/src/types/flags/esdt_token_type.rs index bfa2b07192..bfa65f604a 100644 --- a/chain/core/src/types/flags/esdt_token_type.rs +++ b/chain/core/src/types/flags/esdt_token_type.rs @@ -9,7 +9,6 @@ const ESDT_TYPE_FUNGIBLE: &[u8] = b"FungibleESDT"; const ESDT_TYPE_NON_FUNGIBLE: &[u8] = b"NonFungibleESDT"; const ESDT_TYPE_SEMI_FUNGIBLE: &[u8] = b"SemiFungibleESDT"; const ESDT_TYPE_META: &[u8] = b"MetaESDT"; -const ESDT_TYPE_NON_FUNGIBLE_V2: &[u8] = b"NonFungibleESDTv2"; const ESDT_TYPE_DYNAMIC_NON_FUNGIBLE: &[u8] = b"DynamicNonFungibleESDT"; const ESDT_TYPE_DYNAMIC_SEMI_FUNGIBLE: &[u8] = b"DynamicSemiFungibleESDT"; const ESDT_TYPE_DYNAMIC_META: &[u8] = b"DynamicMetaESDT"; @@ -23,7 +22,6 @@ pub enum EsdtTokenType { NonFungible, SemiFungible, Meta, - NonFungibleV2, DynamicNFT, DynamicSFT, DynamicMeta, @@ -45,11 +43,10 @@ impl EsdtTokenType { Self::NonFungible => 1, Self::SemiFungible => 2, Self::Meta => 3, - Self::NonFungibleV2 => 4, - Self::DynamicNFT => 5, - Self::DynamicSFT => 6, - Self::DynamicMeta => 7, - Self::Invalid => 8, + Self::DynamicNFT => 4, + Self::DynamicSFT => 5, + Self::DynamicMeta => 6, + Self::Invalid => 7, } } @@ -59,7 +56,6 @@ impl EsdtTokenType { Self::NonFungible => ESDT_TYPE_NON_FUNGIBLE, Self::SemiFungible => ESDT_TYPE_SEMI_FUNGIBLE, Self::Meta => ESDT_TYPE_META, - Self::NonFungibleV2 => ESDT_TYPE_NON_FUNGIBLE_V2, Self::DynamicNFT => ESDT_TYPE_DYNAMIC_NON_FUNGIBLE, Self::DynamicSFT => ESDT_TYPE_DYNAMIC_SEMI_FUNGIBLE, Self::DynamicMeta => ESDT_TYPE_DYNAMIC_META, @@ -76,10 +72,9 @@ impl From for EsdtTokenType { 1 => Self::NonFungible, 2 => Self::SemiFungible, 3 => Self::Meta, - 4 => Self::NonFungibleV2, - 5 => Self::DynamicNFT, - 6 => Self::DynamicSFT, - 7 => Self::DynamicMeta, + 4 => Self::DynamicNFT, + 5 => Self::DynamicSFT, + 6 => Self::DynamicMeta, _ => Self::Invalid, } } @@ -96,8 +91,6 @@ impl<'a> From<&'a [u8]> for EsdtTokenType { Self::SemiFungible } else if byte_slice == ESDT_TYPE_META { Self::Meta - } else if byte_slice == ESDT_TYPE_NON_FUNGIBLE_V2 { - Self::NonFungibleV2 } else if byte_slice == ESDT_TYPE_DYNAMIC_NON_FUNGIBLE { Self::DynamicNFT } else if byte_slice == ESDT_TYPE_DYNAMIC_SEMI_FUNGIBLE { diff --git a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs index 87e4e1fd7b..ccea8494d3 100644 --- a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs @@ -213,9 +213,7 @@ where ) -> IssueCall { let token_type_name = match token_type { EsdtTokenType::Fungible => "FNG", - EsdtTokenType::NonFungible - | EsdtTokenType::NonFungibleV2 - | EsdtTokenType::DynamicNFT => "NFT", + EsdtTokenType::NonFungible | EsdtTokenType::DynamicNFT => "NFT", EsdtTokenType::SemiFungible | EsdtTokenType::DynamicSFT => "SFT", EsdtTokenType::Meta | EsdtTokenType::DynamicMeta => "META", EsdtTokenType::Invalid => "", @@ -224,10 +222,8 @@ where let endpoint = match token_type { EsdtTokenType::Fungible | EsdtTokenType::NonFungible - | EsdtTokenType::NonFungibleV2 | EsdtTokenType::SemiFungible | EsdtTokenType::Meta => ISSUE_AND_SET_ALL_ROLES_ENDPOINT_NAME, - EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { REGISTER_AND_SET_ALL_ROLES_DYNAMIC_ESDT_ENDPOINT_NAME }, @@ -261,9 +257,7 @@ where ) -> IssueCall { let endpoint_name = match token_type { EsdtTokenType::Fungible => ISSUE_FUNGIBLE_ENDPOINT_NAME, - EsdtTokenType::NonFungible | EsdtTokenType::NonFungibleV2 => { - ISSUE_NON_FUNGIBLE_ENDPOINT_NAME - }, + EsdtTokenType::NonFungible => ISSUE_NON_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::SemiFungible => ISSUE_SEMI_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::Meta => REGISTER_META_ESDT_ENDPOINT_NAME, EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { diff --git a/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs index 54b685e61d..a7cdeb4570 100644 --- a/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs @@ -187,9 +187,7 @@ where let token_type_name = match token_type { EsdtTokenType::Fungible => "FNG", - EsdtTokenType::NonFungible - | EsdtTokenType::NonFungibleV2 - | EsdtTokenType::DynamicNFT => "NFT", + EsdtTokenType::NonFungible | EsdtTokenType::DynamicNFT => "NFT", EsdtTokenType::SemiFungible | EsdtTokenType::DynamicSFT => "SFT", EsdtTokenType::Meta | EsdtTokenType::DynamicMeta => "META", EsdtTokenType::Invalid => "", @@ -198,7 +196,6 @@ where let endpoint = match token_type { EsdtTokenType::Fungible | EsdtTokenType::NonFungible - | EsdtTokenType::NonFungibleV2 | EsdtTokenType::SemiFungible | EsdtTokenType::Meta => ISSUE_AND_SET_ALL_ROLES_ENDPOINT_NAME, @@ -230,9 +227,7 @@ where let endpoint_name = match token_type { EsdtTokenType::Fungible => ISSUE_FUNGIBLE_ENDPOINT_NAME, - EsdtTokenType::NonFungible | EsdtTokenType::NonFungibleV2 => { - ISSUE_NON_FUNGIBLE_ENDPOINT_NAME - }, + EsdtTokenType::NonFungible => ISSUE_NON_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::SemiFungible => ISSUE_SEMI_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::Meta => REGISTER_META_ESDT_ENDPOINT_NAME, EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { From 9831902322555e9bd7bb538a0b4d339be8129f59 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 2 Dec 2024 18:30:54 +0100 Subject: [PATCH 04/17] system interactor chain simulator setup --- tools/interactor-system-func-calls/Cargo.toml | 6 + .../src/system_sc_interact.rs | 230 ++++++++++++------ .../src/system_sc_interact_config.rs | 9 +- .../src/system_sc_main.rs | 6 + .../tests/chain_simulator_token_tests.rs | 54 ++++ 5 files changed, 229 insertions(+), 76 deletions(-) create mode 100644 tools/interactor-system-func-calls/src/system_sc_main.rs create mode 100644 tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs diff --git a/tools/interactor-system-func-calls/Cargo.toml b/tools/interactor-system-func-calls/Cargo.toml index a92170f220..28921639df 100644 --- a/tools/interactor-system-func-calls/Cargo.toml +++ b/tools/interactor-system-func-calls/Cargo.toml @@ -1,5 +1,8 @@ [[bin]] name = "system-sc-interact" +path = "src/system_sc_main.rs" + +[lib] path = "src/system_sc_interact.rs" [package] @@ -24,3 +27,6 @@ features = ["derive"] [dependencies.multiversx-sc-snippets] version = "=0.54.5" path = "../../framework/snippets" + +[features] +chain-simulator-tests = [] diff --git a/tools/interactor-system-func-calls/src/system_sc_interact.rs b/tools/interactor-system-func-calls/src/system_sc_interact.rs index 97d3005c97..a10e7caaec 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact.rs @@ -1,21 +1,18 @@ -#![allow(deprecated)] // TODO: move prepare_async calls to a test for backwards compatibility and delete from here - mod system_sc_interact_cli; mod system_sc_interact_config; mod system_sc_interact_state; use clap::Parser; -use system_sc_interact_cli::NftDummyAttributes; -use system_sc_interact_config::Config; +pub use system_sc_interact_cli::NftDummyAttributes; +pub use system_sc_interact_config::Config; use system_sc_interact_state::State; use multiversx_sc_snippets::imports::*; -#[tokio::main] -async fn main() { +pub async fn system_sc_interact_cli() { env_logger::init(); - let mut basic_interact = SysFuncCallsInteract::init().await; + let mut basic_interact = SysFuncCallsInteract::init(Config::load_config()).await; let cli = system_sc_interact_cli::InteractCli::parse(); match &cli.command { @@ -130,6 +127,11 @@ async fn main() { args.name.as_bytes(), args.royalties, args.hash.as_bytes(), + &NftDummyAttributes { + creation_epoch: 2u64, + cool_factor: 3u8, + }, + Vec::new(), ) .await; }, @@ -219,19 +221,18 @@ async fn main() { } } -#[allow(unused)] -struct SysFuncCallsInteract { +pub struct SysFuncCallsInteract { interactor: Interactor, wallet_address: Bech32Address, + #[allow(unused)] state: State, } impl SysFuncCallsInteract { - async fn init() -> Self { - let config = Config::load_config(); + pub async fn init(config: Config) -> Self { let mut interactor = Interactor::new(config.gateway_uri()) .await - .use_chain_simulator(config.use_chain_simulator()); + .use_chain_simulator(config.is_chain_simulator()); interactor.set_current_dir_from_workspace("tools/interactor-system-func-calls"); let wallet_address = interactor.register_wallet(test_wallets::alice()).await; @@ -246,7 +247,7 @@ impl SysFuncCallsInteract { } } - async fn issue_fungible_token( + pub async fn issue_fungible_token( &mut self, issue_cost: RustBigUint, token_display_name: &[u8], @@ -281,14 +282,13 @@ impl SysFuncCallsInteract { }, ) .returns(ReturnsNewTokenIdentifier) - .prepare_async() .run() .await; println!("TOKEN ID: {:?}", res); } - async fn issue_non_fungible_collection( + pub async fn issue_non_fungible_collection( &mut self, issue_cost: RustBigUint, token_display_name: &[u8], @@ -318,14 +318,13 @@ impl SysFuncCallsInteract { }, ) .returns(ReturnsNewTokenIdentifier) - .prepare_async() .run() .await; println!("NFT Collection ID: {:?}", nft_collection_id); } - async fn issue_semi_fungible_collection( + pub async fn issue_semi_fungible_collection( &mut self, issue_cost: RustBigUint, token_display_name: &[u8], @@ -355,22 +354,21 @@ impl SysFuncCallsInteract { }, ) .returns(ReturnsNewTokenIdentifier) - .prepare_async() .run() .await; println!("SFT Collection ID: {:?}", sft_collection_id); } - async fn issue_token( + pub async fn issue_token( &mut self, issue_cost: RustBigUint, token_display_name: &[u8], token_ticker: &[u8], num_decimals: usize, token_type: EsdtTokenType, - ) { - println!("Registering token..."); + ) -> String { + println!("Registering and setting all roles for token {token_ticker:?} of type {token_type:?}..."); let token_id = self .interactor @@ -387,16 +385,17 @@ impl SysFuncCallsInteract { num_decimals, ) .returns(ReturnsNewTokenIdentifier) - .prepare_async() .run() .await; println!("TOKEN ID: {:?}", token_id); + + token_id } - async fn set_roles(&mut self, token_id: &[u8], roles: Vec) { + pub async fn set_roles(&mut self, token_id: &[u8], roles: Vec) { let wallet_address = &self.wallet_address.clone().into_address(); - println!("Setting the following roles: {:?}", roles); + println!("Setting the following roles: {roles:?} for {token_id:?}"); self.interactor .tx() @@ -409,12 +408,11 @@ impl SysFuncCallsInteract { TokenIdentifier::from(token_id), roles.into_iter(), ) - .prepare_async() .run() .await; } - async fn mint_sft( + pub async fn mint_sft( &mut self, token_id: &[u8], amount: RustBigUint, @@ -442,12 +440,11 @@ impl SysFuncCallsInteract { }, &ManagedVec::new(), ) - .prepare_async() .run() .await; } - async fn register_meta_esdt( + pub async fn register_meta_esdt( &mut self, issue_cost: RustBigUint, token_display_name: &[u8], @@ -479,14 +476,13 @@ impl SysFuncCallsInteract { }, ) .returns(ReturnsNewTokenIdentifier) - .prepare_async() .run() .await; println!("Meta-ESDT ID: {:?}", meta_esdt); } - async fn change_sft_meta_esdt(&mut self, token_id: &[u8], num_decimals: usize) { + pub async fn change_sft_meta_esdt(&mut self, token_id: &[u8], num_decimals: usize) { println!("Changing SFT to Meta-ESDT..."); self.interactor @@ -496,12 +492,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .change_sft_to_meta_esdt(token_id, num_decimals) - .prepare_async() .run() .await; } - async fn mint_token(&mut self, token_id: &[u8], nonce: u64, amount: RustBigUint) { + pub async fn mint_token(&mut self, token_id: &[u8], nonce: u64, amount: RustBigUint) { println!("Minting tokens..."); self.interactor @@ -511,12 +506,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(UserBuiltinProxy) .esdt_local_mint(token_id, nonce, amount) - .prepare_async() .run() .await; } - async fn burn_token(&mut self, token_id: &[u8], nonce: u64, amount: RustBigUint) { + pub async fn burn_token(&mut self, token_id: &[u8], nonce: u64, amount: RustBigUint) { println!("Burning tokens..."); self.interactor @@ -526,12 +520,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(UserBuiltinProxy) .esdt_local_burn(token_id, nonce, amount) - .prepare_async() .run() .await; } - async fn pause_token(&mut self, token_id: &[u8]) { + pub async fn pause_token(&mut self, token_id: &[u8]) { println!("Pausing token..."); self.interactor @@ -541,12 +534,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .pause(token_id) - .prepare_async() .run() .await; } - async fn unpause_token(&mut self, token_id: &[u8]) { + pub async fn unpause_token(&mut self, token_id: &[u8]) { println!("Unpausing token..."); self.interactor @@ -556,12 +548,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .unpause(token_id) - .prepare_async() .run() .await; } - async fn freeze_token(&mut self, token_id: &[u8], address: &Bech32Address) { + pub async fn freeze_token(&mut self, token_id: &[u8], address: &Bech32Address) { println!("Freezing token..."); self.interactor @@ -571,12 +562,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .freeze(token_id, address) - .prepare_async() .run() .await; } - async fn unfreeze_token(&mut self, token_id: &[u8], address: &Bech32Address) { + pub async fn unfreeze_token(&mut self, token_id: &[u8], address: &Bech32Address) { println!("Unfreezing token..."); self.interactor @@ -586,12 +576,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .unfreeze(token_id, address) - .prepare_async() .run() .await; } - async fn freeze_nft(&mut self, token_id: &[u8], nonce: u64, address: &Bech32Address) { + pub async fn freeze_nft(&mut self, token_id: &[u8], nonce: u64, address: &Bech32Address) { println!("Freezing NFT/SFT/Meta-ESDT..."); self.interactor @@ -601,12 +590,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .freeze_nft(token_id, nonce, address) - .prepare_async() .run() .await; } - async fn unfreeze_nft(&mut self, token_id: &[u8], nonce: u64, address: &Bech32Address) { + pub async fn unfreeze_nft(&mut self, token_id: &[u8], nonce: u64, address: &Bech32Address) { println!("Unfreezing NFT/SFT/Meta-ESDT..."); self.interactor @@ -616,12 +604,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .unfreeze_nft(token_id, nonce, address) - .prepare_async() .run() .await; } - async fn wipe_token(&mut self, token_id: &[u8], address: &Bech32Address) { + pub async fn wipe_token(&mut self, token_id: &[u8], address: &Bech32Address) { println!("Wiping token..."); self.interactor @@ -631,12 +618,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .wipe(token_id, address) - .prepare_async() .run() .await; } - async fn wipe_nft(&mut self, token_id: &[u8], nonce: u64, address: &Bech32Address) { + pub async fn wipe_nft(&mut self, token_id: &[u8], nonce: u64, address: &Bech32Address) { println!("Wiping NFT/SFT/Meta-ESDT..."); self.interactor @@ -646,45 +632,41 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .wipe_nft(token_id, nonce, address) - .prepare_async() .run() .await; } - async fn mint_nft( + #[allow(clippy::too_many_arguments)] + pub async fn mint_nft( &mut self, token_id: &[u8], amount: RustBigUint, name: &[u8], royalties: u64, hash: &[u8], - ) { + attributes: &T, + uris: Vec, + ) -> u64 { println!("Minting NFT..."); + let uris = uris + .into_iter() + .map(ManagedBuffer::from) + .collect::>>(); + self.interactor .tx() .from(&self.wallet_address) .to(&self.wallet_address) .gas(100_000_000u64) .typed(UserBuiltinProxy) - .esdt_nft_create( - token_id, - amount, - name, - royalties, - hash, - &NftDummyAttributes { - creation_epoch: 2104, - cool_factor: 5, - }, - &ManagedVec::new(), - ) - .prepare_async() + .esdt_nft_create(token_id, amount, name, royalties, hash, attributes, &uris) + .returns(ReturnsResult) .run() - .await; + .await } - async fn unset_roles( + pub async fn unset_roles( &mut self, address: &Bech32Address, token_id: &[u8], @@ -699,12 +681,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .unset_special_roles(address, token_id, roles.into_iter()) - .prepare_async() .run() .await; } - async fn transfer_ownership(&mut self, token_id: &[u8], new_owner: &Bech32Address) { + pub async fn transfer_ownership(&mut self, token_id: &[u8], new_owner: &Bech32Address) { println!("Transferring token ownership..."); self.interactor @@ -714,12 +695,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .transfer_ownership(token_id, new_owner) - .prepare_async() .run() .await; } - async fn transfer_nft_create_role( + pub async fn transfer_nft_create_role( &mut self, token_id: &[u8], old_owner: &Bech32Address, @@ -734,12 +714,11 @@ impl SysFuncCallsInteract { .gas(100_000_000u64) .typed(ESDTSystemSCProxy) .transfer_nft_create_role(token_id, old_owner, new_owner) - .prepare_async() .run() .await; } - async fn control_changes(&mut self, token_id: &[u8]) { + pub async fn control_changes(&mut self, token_id: &[u8]) { println!("Control changes"); self.interactor @@ -762,7 +741,108 @@ impl SysFuncCallsInteract { can_add_special_roles: Some(true), }, ) - .prepare_async() + .run() + .await; + } + + pub async fn set_token_type(&mut self, token_id: &[u8], token_type: EsdtTokenType) { + println!("Setting token type to {token_type:?} for token {token_id:?}..."); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_set_token_type(token_id, token_type) + .run() + .await; + } + + pub async fn modify_royalties(&mut self, token_id: &[u8], nonce: u64, new_royalty: u64) { + println!("Modifying royalties for token {token_id:?} into {new_royalty:?}..."); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_modify_royalties(token_id, nonce, new_royalty) + .run() + .await; + } + + pub async fn set_new_uris(&mut self, token_id: &[u8], nonce: u64, new_uris: Vec) { + println!("Setting new uris for token {token_id:?} with nonce {nonce:?}..."); + + let uris = new_uris + .into_iter() + .map(ManagedBuffer::from) + .collect::>>(); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_nft_set_new_uris(token_id, nonce, &uris) + .run() + .await; + } + + // changes creator into caller + pub async fn modify_creator(&mut self, token_id: &[u8], nonce: u64) { + println!( + "Modifying the creator (into caller) for token {token_id:?} with nonce {nonce:?}..." + ); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_nft_modify_creator(token_id, nonce) + .run() + .await; + } + + pub async fn metadata_recreate( + &mut self, + token_id: &[u8], + nonce: u64, + new_attributes: T, + ) { + println!("Recreating the token {token_id:?} with nonce {nonce:?} with new attributes..."); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_metadata_recreate(token_id, nonce, &new_attributes) + .run() + .await; + } + + pub async fn metadata_update( + &mut self, + token_id: &[u8], + nonce: u64, + new_attributes: T, + ) { + println!("Updating the token {token_id:?} with nonce {nonce:?} with new attributes..."); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_metadata_update(token_id, nonce, &new_attributes) .run() .await; } diff --git a/tools/interactor-system-func-calls/src/system_sc_interact_config.rs b/tools/interactor-system-func-calls/src/system_sc_interact_config.rs index c61059d57e..f2a23a0da5 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact_config.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact_config.rs @@ -27,13 +27,20 @@ impl Config { 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 { + pub fn is_chain_simulator(&self) -> bool { match self.chain_type { ChainType::Real => false, ChainType::Simulator => true, diff --git a/tools/interactor-system-func-calls/src/system_sc_main.rs b/tools/interactor-system-func-calls/src/system_sc_main.rs new file mode 100644 index 0000000000..89a4ca0a28 --- /dev/null +++ b/tools/interactor-system-func-calls/src/system_sc_main.rs @@ -0,0 +1,6 @@ +extern crate system_sc_interact; + +#[tokio::main] +pub async fn main() { + system_sc_interact::system_sc_interact_cli().await; +} diff --git a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs new file mode 100644 index 0000000000..00db309334 --- /dev/null +++ b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs @@ -0,0 +1,54 @@ +use multiversx_sc_snippets::imports::{EsdtTokenType, RustBigUint}; +use system_sc_interact::{Config, NftDummyAttributes, SysFuncCallsInteract}; + +#[tokio::test] +#[ignore = "fixes needed"] +async fn cs_builtin_func_tokens_test() { + let mut interact = SysFuncCallsInteract::init(Config::chain_simulator_config()).await; + + // issue dynamic NFT + let dynamic_nft_token_id = interact + .issue_token( + RustBigUint::from(50000000000000000u64), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::DynamicNFT, + ) + .await; + + println!("Dynamic NFT token id issued: {dynamic_nft_token_id:?}"); + + // mint NFT + let nonce = interact + .mint_nft( + dynamic_nft_token_id.as_bytes(), + RustBigUint::from(1u64), + b"myNFT", + 30u64, + b"", + &NftDummyAttributes { + creation_epoch: 2u64, + cool_factor: 3u8, + }, + Vec::new(), + ) + .await; + + println!("Dynamic NFT minted at nonce {nonce:?}"); + + // modify royalties + interact + .modify_royalties(dynamic_nft_token_id.as_bytes(), nonce, 20u64) + .await; + + println!("Royalties changed for {dynamic_nft_token_id:?} with nonce {nonce:?}"); + + // set new uris + let uris = vec!["thisianuri.com".to_string()]; + interact + .set_new_uris(dynamic_nft_token_id.as_bytes(), nonce, uris) + .await; + + println!("New uris set for {dynamic_nft_token_id:?} with nonce {nonce:?}"); +} From e5b7db922d860db604cb46a7e254ec0d789d92e3 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Tue, 3 Dec 2024 17:38:33 +0100 Subject: [PATCH 05/17] bugfixing, interactor testing, new issue dynamic function, small interactor decode fix --- .../contract_base/wrappers/send_wrapper.rs | 16 +++- .../system_proxy/builtin_func_proxy.rs | 28 ++++++- .../system_proxy/esdt_system_sc_proxy.rs | 69 ++++++++++++++-- .../system_proxy/legacy_system_sc_proxy.rs | 49 ++++++++++- framework/snippets/src/network_response.rs | 5 ++ .../src/system_sc_interact.rs | 65 +++++++++++++-- .../tests/chain_simulator_token_tests.rs | 82 ++++++++++++++++++- 7 files changed, 287 insertions(+), 27 deletions(-) diff --git a/framework/base/src/contract_base/wrappers/send_wrapper.rs b/framework/base/src/contract_base/wrappers/send_wrapper.rs index 468d75c92c..09809956bb 100644 --- a/framework/base/src/contract_base/wrappers/send_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/send_wrapper.rs @@ -817,32 +817,42 @@ where } /// Recreates an ESDT token with the newly specified attributes. + #[allow(clippy::too_many_arguments)] pub fn esdt_metadata_recreate( &self, token_id: TokenIdentifier, nonce: u64, + name: ManagedBuffer, + royalties: u64, + hash: ManagedBuffer, new_attributes: &T, + uris: ManagedVec>, ) { Tx::new_tx_from_sc() .to(ToSelf) .gas(GasLeft) .typed(system_proxy::UserBuiltinProxy) - .esdt_metadata_recreate(token_id, nonce, new_attributes) + .esdt_metadata_recreate(token_id, nonce, name, royalties, hash, new_attributes, uris) .sync_call() } /// Updates an ESDT token with the newly specified attributes. + #[allow(clippy::too_many_arguments)] pub fn esdt_metadata_update( &self, - token_id: &TokenIdentifier, + token_id: TokenIdentifier, nonce: u64, + name: ManagedBuffer, + royalties: u64, + hash: ManagedBuffer, new_attributes: &T, + uris: ManagedVec>, ) { Tx::new_tx_from_sc() .to(ToSelf) .gas(GasLeft) .typed(system_proxy::UserBuiltinProxy) - .esdt_metadata_update(token_id, nonce, new_attributes) + .esdt_metadata_update(token_id, nonce, name, royalties, hash, new_attributes, uris) .sync_call() } } diff --git a/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs b/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs index 1612965f4b..8388332d75 100644 --- a/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs @@ -301,15 +301,23 @@ where tx.original_result() } + #[allow(clippy::too_many_arguments)] pub fn esdt_metadata_recreate< T: TopEncode, Arg0: ProxyArg>, Arg1: ProxyArg, + Arg2: ProxyArg>, + Arg3: ProxyArg, + Arg4: ProxyArg>, >( self, token_id: Arg0, nonce: Arg1, + name: Arg2, + royalties: Arg3, + hash: Arg4, new_attributes: &T, + uris: ManagedVec>, ) -> TxTypedCall { let tx = self .wrapped_tx @@ -317,20 +325,32 @@ where .raw_call(ESDT_METADATA_RECREATE_FUNC_NAME) .argument(&token_id) .argument(&nonce) - .argument(&new_attributes); + .argument(&name) + .argument(&royalties) + .argument(&hash) + .argument(&new_attributes) + .argument(&uris); tx.original_result() } + #[allow(clippy::too_many_arguments)] pub fn esdt_metadata_update< T: TopEncode, Arg0: ProxyArg>, Arg1: ProxyArg, + Arg2: ProxyArg>, + Arg3: ProxyArg, + Arg4: ProxyArg>, >( self, token_id: Arg0, nonce: Arg1, + name: Arg2, + royalties: Arg3, + hash: Arg4, new_attributes: &T, + uris: ManagedVec>, ) -> TxTypedCall { let tx = self .wrapped_tx @@ -338,7 +358,11 @@ where .raw_call(ESDT_METADATA_UPDATE_FUNC_NAME) .argument(&token_id) .argument(&nonce) - .argument(&new_attributes); + .argument(&name) + .argument(&royalties) + .argument(&hash) + .argument(&new_attributes) + .argument(&uris); tx.original_result() } diff --git a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs index ccea8494d3..e2f74ded4e 100644 --- a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs @@ -231,14 +231,70 @@ where EsdtTokenType::Invalid => "", }; - self.wrapped_tx + let mut tx = self + .wrapped_tx .raw_call(endpoint) .egld(issue_cost) .argument(&token_display_name) .argument(&token_ticker) - .argument(&token_type_name) - .argument(&num_decimals) - .original_result() + .argument(&token_type_name); + + if token_type_name == "META" { + tx = tx.argument(&num_decimals); + } else { + assert!( + num_decimals == 0usize, + "only META tokens accept number of decimals > 0" + ); + } + + tx.original_result() + } + + /// Issues dynamic ESDT tokens + pub fn issue_dynamic< + Arg0: ProxyArg>, + Arg1: ProxyArg>, + >( + self, + issue_cost: BigUint, + token_display_name: Arg0, + token_ticker: Arg1, + token_type: EsdtTokenType, + num_decimals: usize, + ) -> IssueCall { + let endpoint_name = match token_type { + EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { + REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME + }, + _ => "", + }; + + let token_type_name = match token_type { + EsdtTokenType::DynamicNFT => "NFT", + EsdtTokenType::DynamicSFT => "SFT", + EsdtTokenType::DynamicMeta => "META", + _ => "", + }; + + let mut tx = self + .wrapped_tx + .raw_call(endpoint_name) + .egld(issue_cost) + .argument(&token_display_name) + .argument(&token_ticker) + .argument(&token_type_name); + + if token_type_name == "META" { + tx = tx.argument(&num_decimals); + } else { + assert!( + num_decimals == 0usize, + "only META tokens accept number of decimals > 0" + ); + } + + tx.original_result() } /// Deduplicates code from all the possible issue functions @@ -260,10 +316,7 @@ where EsdtTokenType::NonFungible => ISSUE_NON_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::SemiFungible => ISSUE_SEMI_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::Meta => REGISTER_META_ESDT_ENDPOINT_NAME, - EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { - REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME - }, - EsdtTokenType::Invalid => "", + _ => "", }; let mut tx = self diff --git a/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs index a7cdeb4570..cbc06fb3b1 100644 --- a/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs @@ -213,6 +213,50 @@ where .argument(&num_decimals) } + /// Issues dynamic ESDT tokens + pub fn issue_dynamic( + self, + issue_cost: BigUint, + token_display_name: &ManagedBuffer, + token_ticker: &ManagedBuffer, + token_type: EsdtTokenType, + num_decimals: usize, + ) -> ContractCallWithEgld { + let esdt_system_sc_address = self.esdt_system_sc_address(); + + let endpoint_name = match token_type { + EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { + REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME + }, + _ => "", + }; + + let token_type_name = match token_type { + EsdtTokenType::DynamicNFT => "NFT", + EsdtTokenType::DynamicSFT => "SFT", + EsdtTokenType::DynamicMeta => "META", + _ => "", + }; + + let mut contract_call = + ContractCallWithEgld::new(esdt_system_sc_address, endpoint_name, issue_cost); + + contract_call.proxy_arg(token_display_name); + contract_call.proxy_arg(token_ticker); + contract_call.proxy_arg(&token_type_name); + + if token_type_name == "META" { + contract_call.proxy_arg(&num_decimals); + } else { + assert!( + num_decimals == 0usize, + "only META tokens accept number of decimals > 0" + ); + } + + contract_call + } + /// Deduplicates code from all the possible issue functions fn issue( self, @@ -230,10 +274,7 @@ where EsdtTokenType::NonFungible => ISSUE_NON_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::SemiFungible => ISSUE_SEMI_FUNGIBLE_ENDPOINT_NAME, EsdtTokenType::Meta => REGISTER_META_ESDT_ENDPOINT_NAME, - EsdtTokenType::DynamicNFT | EsdtTokenType::DynamicSFT | EsdtTokenType::DynamicMeta => { - REGISTER_DYNAMIC_ESDT_ENDPOINT_NAME - }, - EsdtTokenType::Invalid => "", + _ => "", }; let mut contract_call = diff --git a/framework/snippets/src/network_response.rs b/framework/snippets/src/network_response.rs index c17ae4456d..3e6bb2931d 100644 --- a/framework/snippets/src/network_response.rs +++ b/framework/snippets/src/network_response.rs @@ -173,12 +173,17 @@ fn process_new_issued_token_identifier(tx: &TransactionOnNetwork) -> Option { basic_interact - .issue_token( + .issue_token_all_roles( args.cost.clone(), args.display_name.as_bytes(), args.ticker.as_bytes(), @@ -360,7 +360,40 @@ impl SysFuncCallsInteract { println!("SFT Collection ID: {:?}", sft_collection_id); } - pub async fn issue_token( + pub async fn issue_dynamic_token( + &mut self, + issue_cost: RustBigUint, + token_display_name: &[u8], + token_ticker: &[u8], + token_type: EsdtTokenType, + num_decimals: usize, + ) -> String { + println!("Registering dynamic token {token_ticker:?} of type {token_type:?}..."); + + let token_id = self + .interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .issue_dynamic( + issue_cost.into(), + token_display_name, + token_ticker, + token_type, + num_decimals, + ) + .returns(ReturnsNewTokenIdentifier) + .run() + .await; + + println!("TOKEN ID: {:?}", token_id); + + token_id + } + + pub async fn issue_token_all_roles( &mut self, issue_cost: RustBigUint, token_display_name: &[u8], @@ -809,40 +842,60 @@ impl SysFuncCallsInteract { .await; } + #[allow(clippy::too_many_arguments)] pub async fn metadata_recreate( &mut self, token_id: &[u8], nonce: u64, - new_attributes: T, + name: &[u8], + royalties: u64, + hash: &[u8], + new_attributes: &T, + uris: Vec, ) { println!("Recreating the token {token_id:?} with nonce {nonce:?} with new attributes..."); + let uris = uris + .into_iter() + .map(ManagedBuffer::from) + .collect::>>(); + self.interactor .tx() .from(&self.wallet_address) .to(&self.wallet_address) .gas(100_000_000u64) .typed(UserBuiltinProxy) - .esdt_metadata_recreate(token_id, nonce, &new_attributes) + .esdt_metadata_recreate(token_id, nonce, name, royalties, hash, new_attributes, uris) .run() .await; } + #[allow(clippy::too_many_arguments)] pub async fn metadata_update( &mut self, token_id: &[u8], nonce: u64, - new_attributes: T, + name: &[u8], + royalties: u64, + hash: &[u8], + new_attributes: &T, + uris: Vec, ) { println!("Updating the token {token_id:?} with nonce {nonce:?} with new attributes..."); + let uris = uris + .into_iter() + .map(ManagedBuffer::from) + .collect::>>(); + self.interactor .tx() .from(&self.wallet_address) .to(&self.wallet_address) .gas(100_000_000u64) .typed(UserBuiltinProxy) - .esdt_metadata_update(token_id, nonce, &new_attributes) + .esdt_metadata_update(token_id, nonce, name, royalties, hash, new_attributes, uris) .run() .await; } diff --git a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs index 00db309334..a789ed9a92 100644 --- a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs +++ b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs @@ -1,15 +1,53 @@ use multiversx_sc_snippets::imports::{EsdtTokenType, RustBigUint}; use system_sc_interact::{Config, NftDummyAttributes, SysFuncCallsInteract}; +const ISSUE_COST: u64 = 50000000000000000u64; + +// real blockchain tests for now, fixes needed for chain simulator #[tokio::test] -#[ignore = "fixes needed"] +#[ignore = "run on demand"] async fn cs_builtin_func_tokens_test() { - let mut interact = SysFuncCallsInteract::init(Config::chain_simulator_config()).await; + // let mut interact = SysFuncCallsInteract::init(Config::chain_simulator_config()).await; + + let mut interact = SysFuncCallsInteract::init(Config::load_config()).await; // issue dynamic NFT + interact + .issue_dynamic_token( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + EsdtTokenType::DynamicNFT, + 0usize, + ) + .await; + + // issue dynamic SFT + interact + .issue_dynamic_token( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + EsdtTokenType::DynamicSFT, + 0usize, + ) + .await; + + // issue dynamic META + interact + .issue_dynamic_token( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + EsdtTokenType::DynamicMeta, + 18usize, + ) + .await; + + // issue dynamic NFT with all roles let dynamic_nft_token_id = interact - .issue_token( - RustBigUint::from(50000000000000000u64), + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), b"TESTNFT", b"TEST", 0usize, @@ -51,4 +89,40 @@ async fn cs_builtin_func_tokens_test() { .await; println!("New uris set for {dynamic_nft_token_id:?} with nonce {nonce:?}"); + + // metadata update + interact + .metadata_update( + dynamic_nft_token_id.as_bytes(), + nonce, + b"TESTNFT", + 30u64, + b"new_hash", + &NftDummyAttributes { + creation_epoch: 3u64, + cool_factor: 5u8, + }, + Vec::new(), + ) + .await; + + println!("Metadata updated for {dynamic_nft_token_id:?} with nonce {nonce:?}"); + + // metadata recreate + interact + .metadata_recreate( + dynamic_nft_token_id.as_bytes(), + nonce, + b"TESTNFT", + 30u64, + b"new_hash_recreated", + &NftDummyAttributes { + creation_epoch: 100u64, + cool_factor: 1u8, + }, + Vec::new(), + ) + .await; + + println!("Metadata recreated for {dynamic_nft_token_id:?} with nonce {nonce:?}. A new token has been created."); } From 4b8e7d05fee296c32cc25b9e49889c576b54e682 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Tue, 3 Dec 2024 19:18:23 +0100 Subject: [PATCH 06/17] change to dynamic impl, bugfixes, more tests --- .../system_proxy/esdt_system_sc_proxy.rs | 27 ++++---- .../system_proxy/legacy_system_sc_proxy.rs | 23 ++++--- .../src/system_sc_interact.rs | 14 ++++ .../tests/chain_simulator_token_tests.rs | 67 +++++++++++++++++++ 4 files changed, 108 insertions(+), 23 deletions(-) diff --git a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs index e2f74ded4e..468243d024 100644 --- a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs @@ -239,13 +239,8 @@ where .argument(&token_ticker) .argument(&token_type_name); - if token_type_name == "META" { + if token_type != EsdtTokenType::DynamicNFT && token_type != EsdtTokenType::DynamicSFT { tx = tx.argument(&num_decimals); - } else { - assert!( - num_decimals == 0usize, - "only META tokens accept number of decimals > 0" - ); } tx.original_result() @@ -285,13 +280,8 @@ where .argument(&token_ticker) .argument(&token_type_name); - if token_type_name == "META" { + if token_type != EsdtTokenType::DynamicNFT && token_type != EsdtTokenType::DynamicSFT { tx = tx.argument(&num_decimals); - } else { - assert!( - num_decimals == 0usize, - "only META tokens accept number of decimals > 0" - ); } tx.original_result() @@ -649,6 +639,19 @@ where append_token_property_arguments(&mut tx.data, property_arguments); tx.original_result() } + + /// Changes token to dynamic. + /// Does not work for: FungibleESDT, NonFungibleESDT, NonFungibleESDTv2. + pub fn change_to_dynamic>>( + self, + token_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("changeToDynamic") + .argument(&token_id) + .original_result() + } } const TRUE_STR: &str = "true"; diff --git a/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs index cbc06fb3b1..3f5d9aaccb 100644 --- a/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/legacy_system_sc_proxy.rs @@ -206,11 +206,17 @@ where EsdtTokenType::Invalid => "", }; - ContractCallWithEgld::new(esdt_system_sc_address, endpoint, issue_cost) - .argument(&token_display_name) - .argument(&token_ticker) - .argument(&token_type_name) - .argument(&num_decimals) + let mut contract_call = + ContractCallWithEgld::new(esdt_system_sc_address, endpoint, issue_cost) + .argument(&token_display_name) + .argument(&token_ticker) + .argument(&token_type_name); + + if token_type != EsdtTokenType::DynamicNFT { + contract_call = contract_call.argument(&num_decimals); + } + + contract_call } /// Issues dynamic ESDT tokens @@ -245,13 +251,8 @@ where contract_call.proxy_arg(token_ticker); contract_call.proxy_arg(&token_type_name); - if token_type_name == "META" { + if token_type != EsdtTokenType::DynamicNFT { contract_call.proxy_arg(&num_decimals); - } else { - assert!( - num_decimals == 0usize, - "only META tokens accept number of decimals > 0" - ); } contract_call diff --git a/tools/interactor-system-func-calls/src/system_sc_interact.rs b/tools/interactor-system-func-calls/src/system_sc_interact.rs index f29f82fa17..f98acaea98 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact.rs @@ -445,6 +445,20 @@ impl SysFuncCallsInteract { .await; } + pub async fn change_to_dynamic(&mut self, token_id: &[u8]) { + println!("Changing the following token {token_id:?} to dynamic..."); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .change_to_dynamic(TokenIdentifier::from(token_id)) + .run() + .await; + } + pub async fn mint_sft( &mut self, token_id: &[u8], diff --git a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs index a789ed9a92..57cb67dccd 100644 --- a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs +++ b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs @@ -44,6 +44,28 @@ async fn cs_builtin_func_tokens_test() { ) .await; + // issue dynamic META with all roles + let _ = interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::DynamicMeta, + ) + .await; + + // issue dynamic SFT with all roles + let _ = interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::DynamicSFT, + ) + .await; + // issue dynamic NFT with all roles let dynamic_nft_token_id = interact .issue_token_all_roles( @@ -126,3 +148,48 @@ async fn cs_builtin_func_tokens_test() { println!("Metadata recreated for {dynamic_nft_token_id:?} with nonce {nonce:?}. A new token has been created."); } + +#[tokio::test] +#[ignore = "run on demand"] +async fn change_to_dynamic_test() { + let mut interact = SysFuncCallsInteract::init(Config::load_config()).await; + + // issue NFT with all roles + let _ = interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::NonFungible, + ) + .await; + + // issue META token with all roles + let meta_token_id = interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 18usize, + EsdtTokenType::Meta, + ) + .await; + + // change META to dynamic + interact.change_to_dynamic(meta_token_id.as_bytes()).await; + + // issue SFT token with all roles + let sft_token_id = interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 18usize, + EsdtTokenType::SemiFungible, + ) + .await; + + // change SFT to dynamic + interact.change_to_dynamic(sft_token_id.as_bytes()).await; +} From e8dfee4c76c06c30f02182c64f1ec0e3d069bdb9 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Wed, 4 Dec 2024 14:41:23 +0100 Subject: [PATCH 07/17] update token endpoint, tests --- .../system_proxy/esdt_system_sc_proxy.rs | 12 +++++++++++ .../src/system_sc_interact.rs | 14 +++++++++++++ .../tests/chain_simulator_token_tests.rs | 20 +++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs index 468243d024..7e4e0fb4ed 100644 --- a/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/esdt_system_sc_proxy.rs @@ -652,6 +652,18 @@ where .argument(&token_id) .original_result() } + + /// Updates a specific token to the newest version. + pub fn update_token>>( + self, + token_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("updateTokenID") + .argument(&token_id) + .original_result() + } } const TRUE_STR: &str = "true"; diff --git a/tools/interactor-system-func-calls/src/system_sc_interact.rs b/tools/interactor-system-func-calls/src/system_sc_interact.rs index f98acaea98..28ecc05034 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact.rs @@ -459,6 +459,20 @@ impl SysFuncCallsInteract { .await; } + pub async fn update_token(&mut self, token_id: &[u8]) { + println!("Updating the following token {token_id:?} to the newest version..."); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .update_token(TokenIdentifier::from(token_id)) + .run() + .await; + } + pub async fn mint_sft( &mut self, token_id: &[u8], diff --git a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs index 57cb67dccd..ba0f83c9f7 100644 --- a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs +++ b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs @@ -193,3 +193,23 @@ async fn change_to_dynamic_test() { // change SFT to dynamic interact.change_to_dynamic(sft_token_id.as_bytes()).await; } + +#[tokio::test] +#[ignore = "run on demand"] +async fn update_token_test() { + let mut interact = SysFuncCallsInteract::init(Config::load_config()).await; + + // issue NFT with all roles + let nft_token_id = interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::NonFungible, + ) + .await; + + // update NFT + interact.update_token(nft_token_id.as_bytes()).await; +} From 675066cdd2a56685f045e3107f19b046cbccf79e Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Thu, 5 Dec 2024 15:20:20 +0100 Subject: [PATCH 08/17] system sc interaction and proxy, modify creator tests, set token type --- .../contract_base/wrappers/send_wrapper.rs | 26 +++--- .../base/src/types/interaction/markers.rs | 2 + .../interaction/markers/system_sc_address.rs | 75 ++++++++++++++++ .../src/types/interaction/system_proxy.rs | 2 + .../system_proxy/builtin_func_proxy.rs | 24 +----- .../system_proxy/system_sc_proxy.rs | 61 +++++++++++++ .../src/system_sc_interact.rs | 44 ++++++++-- .../tests/chain_simulator_token_tests.rs | 85 ++++++++++++++++++- 8 files changed, 278 insertions(+), 41 deletions(-) create mode 100644 framework/base/src/types/interaction/markers/system_sc_address.rs create mode 100644 framework/base/src/types/interaction/system_proxy/system_sc_proxy.rs diff --git a/framework/base/src/contract_base/wrappers/send_wrapper.rs b/framework/base/src/contract_base/wrappers/send_wrapper.rs index 09809956bb..a10041550a 100644 --- a/framework/base/src/contract_base/wrappers/send_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/send_wrapper.rs @@ -1,10 +1,8 @@ use core::marker::PhantomData; -use multiversx_chain_core::types::EsdtTokenType; - use crate::codec::Empty; -use crate::types::ManagedRef; +use crate::types::{ManagedRef, SystemSCAddress}; use crate::{ api::{BlockchainApi, CallTypeApi, StorageReadApi}, codec, @@ -55,7 +53,7 @@ where self.esdt_system_sc_tx() } - /// Prepares a proxy object to call the system SC. + /// Prepares a proxy object to call the ESDT system SC. /// It has the destination address set, as well as the contract type (as specified in the proxy). pub fn esdt_system_sc_tx( &self, @@ -65,6 +63,16 @@ where .typed(system_proxy::ESDTSystemSCProxy) } + /// Prepares a proxy object to call the system SC. + /// It has the destination address set, as well as the contract type (as specified in the proxy). + pub fn system_sc_tx( + &self, + ) -> system_proxy::SystemSCProxyMethods, (), SystemSCAddress, ()> { + Tx::new_tx_from_sc() + .to(SystemSCAddress) + .typed(system_proxy::SystemSCProxy) + } + /// Convenient way to quickly instance a minimal contract call (with no EGLD, no arguments, etc.) /// /// You can further configure this contract call by chaining methods to it. @@ -766,16 +774,6 @@ where .sync_call() } - /// Sets the token type for a specific token. - pub fn esdt_set_token_type(&self, token_id: &TokenIdentifier, token_type: EsdtTokenType) { - Tx::new_tx_from_sc() - .to(ToSelf) - .gas(GasLeft) - .typed(system_proxy::UserBuiltinProxy) - .esdt_set_token_type(token_id, token_type) - .sync_call() - } - /// Modifies royalties for a specific token. pub fn esdt_modify_royalties( &self, diff --git a/framework/base/src/types/interaction/markers.rs b/framework/base/src/types/interaction/markers.rs index 4ebce757cc..c804844400 100644 --- a/framework/base/src/types/interaction/markers.rs +++ b/framework/base/src/types/interaction/markers.rs @@ -1,9 +1,11 @@ mod esdt_system_sc_address; mod gas_left; +mod system_sc_address; mod to_caller; mod to_self; pub use esdt_system_sc_address::ESDTSystemSCAddress; pub use gas_left::GasLeft; +pub use system_sc_address::SystemSCAddress; pub use to_caller::ToCaller; pub use to_self::ToSelf; diff --git a/framework/base/src/types/interaction/markers/system_sc_address.rs b/framework/base/src/types/interaction/markers/system_sc_address.rs new file mode 100644 index 0000000000..e7d5ea1642 --- /dev/null +++ b/framework/base/src/types/interaction/markers/system_sc_address.rs @@ -0,0 +1,75 @@ +use hex_literal::hex; +use multiversx_chain_core::types::Address; +use multiversx_sc_codec::{EncodeErrorHandler, TopEncode, TopEncodeOutput}; + +use crate::{ + abi::TypeAbiFrom, + api::ManagedTypeApi, + types::{AnnotatedValue, ManagedAddress, ManagedBuffer, TxEnv, TxTo, TxToSpecified}, +}; + +/// Address of the system smart contract that manages ESDT. +const SYSTEM_SC_ADDRESS_BYTES: [u8; 32] = + hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01"); +const SYSTEM_SC_ADDRESS_BECH32: &str = + "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366"; +const SYSTEM_SC_ADDRESS_ANNOTATION: &str = + "bech32:erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366"; + +/// Indicates the system SC address, which is the same on any MultiversX blockchain. +pub struct SystemSCAddress; + +impl SystemSCAddress { + pub fn to_managed_address(self) -> ManagedAddress + where + Api: ManagedTypeApi, + { + ManagedAddress::from(SYSTEM_SC_ADDRESS_BYTES) + } + + pub fn to_address(&self) -> Address { + SYSTEM_SC_ADDRESS_BYTES.into() + } + + pub fn to_bech32_str(&self) -> &str { + SYSTEM_SC_ADDRESS_BECH32 + } + + pub fn to_bech32_string(&self) -> alloc::string::String { + SYSTEM_SC_ADDRESS_BECH32.into() + } +} + +impl AnnotatedValue> for SystemSCAddress +where + Env: TxEnv, +{ + fn annotation(&self, _env: &Env) -> ManagedBuffer { + ManagedBuffer::from(SYSTEM_SC_ADDRESS_ANNOTATION) + } + + fn to_value(&self, _env: &Env) -> ManagedAddress { + SystemSCAddress.to_managed_address() + } +} + +impl TxTo for SystemSCAddress where Env: TxEnv {} +impl TxToSpecified for SystemSCAddress where Env: TxEnv {} + +impl TopEncode for SystemSCAddress { + fn top_encode_or_handle_err(&self, output: O, h: H) -> Result<(), H::HandledErr> + where + O: TopEncodeOutput, + H: EncodeErrorHandler, + { + SYSTEM_SC_ADDRESS_BYTES.top_encode_or_handle_err(output, h) + } +} + +impl TypeAbiFrom for ManagedAddress where M: ManagedTypeApi {} + +impl core::fmt::Display for SystemSCAddress { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_str(SYSTEM_SC_ADDRESS_BECH32) + } +} diff --git a/framework/base/src/types/interaction/system_proxy.rs b/framework/base/src/types/interaction/system_proxy.rs index e86c9f32ff..d6a3e084be 100644 --- a/framework/base/src/types/interaction/system_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy.rs @@ -1,9 +1,11 @@ mod builtin_func_proxy; mod esdt_system_sc_proxy; mod legacy_system_sc_proxy; +mod system_sc_proxy; pub(crate) mod token_properties; pub use builtin_func_proxy::*; pub use esdt_system_sc_proxy::{ESDTSystemSCProxy, ESDTSystemSCProxyMethods, IssueCall}; pub use legacy_system_sc_proxy::ESDTSystemSmartContractProxy; +pub use system_sc_proxy::{SystemSCProxy, SystemSCProxyMethods}; pub use token_properties::*; diff --git a/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs b/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs index 8388332d75..601f978393 100644 --- a/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy/builtin_func_proxy.rs @@ -1,8 +1,8 @@ use multiversx_sc_codec::{Empty, TopEncode}; use crate::types::{ - BigUint, EsdtTokenType, ManagedAddress, ManagedBuffer, ManagedVec, NotPayable, ProxyArg, - TokenIdentifier, Tx, TxEnv, TxFrom, TxGas, TxProxyTrait, TxTo, TxTypedCall, + BigUint, ManagedAddress, ManagedBuffer, ManagedVec, NotPayable, ProxyArg, TokenIdentifier, Tx, + TxEnv, TxFrom, TxGas, TxProxyTrait, TxTo, TxTypedCall, }; use crate::chain_core::builtin_func_names::{ @@ -11,7 +11,7 @@ use crate::chain_core::builtin_func_names::{ ESDT_METADATA_UPDATE_FUNC_NAME, ESDT_MODIFY_CREATOR_FUNC_NAME, ESDT_MODIFY_ROYALTIES_FUNC_NAME, ESDT_NFT_ADD_QUANTITY_FUNC_NAME, ESDT_NFT_ADD_URI_FUNC_NAME, ESDT_NFT_BURN_FUNC_NAME, ESDT_NFT_CREATE_FUNC_NAME, ESDT_NFT_UPDATE_ATTRIBUTES_FUNC_NAME, ESDT_SET_NEW_URIS_FUNC_NAME, - ESDT_SET_TOKEN_TYPE_FUNC_NAME, SET_USERNAME_FUNC_NAME, + SET_USERNAME_FUNC_NAME, }; /// Proxy describing the user builtin function signatures. @@ -217,24 +217,6 @@ where tx.original_result() } - pub fn esdt_set_token_type< - Arg0: ProxyArg>, - Arg1: ProxyArg, - >( - self, - token_id: Arg0, - token_type: Arg1, - ) -> TxTypedCall { - let tx = self - .wrapped_tx - .payment(NotPayable) - .raw_call(ESDT_SET_TOKEN_TYPE_FUNC_NAME) - .argument(&token_id) - .argument(&token_type); - - tx.original_result() - } - pub fn esdt_modify_royalties< Arg0: ProxyArg>, Arg1: ProxyArg, diff --git a/framework/base/src/types/interaction/system_proxy/system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/system_sc_proxy.rs new file mode 100644 index 0000000000..1e5b3af66b --- /dev/null +++ b/framework/base/src/types/interaction/system_proxy/system_sc_proxy.rs @@ -0,0 +1,61 @@ +use multiversx_chain_core::builtin_func_names::ESDT_SET_TOKEN_TYPE_FUNC_NAME; + +use crate::types::{ + EsdtTokenType, NotPayable, ProxyArg, TokenIdentifier, Tx, TxEnv, TxFrom, TxGas, TxProxyTrait, + TxTo, TxTypedCall, +}; + +/// Proxy for the system smart contract. +pub struct SystemSCProxy; + +impl TxProxyTrait for SystemSCProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = SystemSCProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + SystemSCProxyMethods { wrapped_tx: tx } + } +} + +/// Method container of the ESDT system smart contract proxy. +pub struct SystemSCProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +impl SystemSCProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + /// Sets the token type for a specific token. + pub fn esdt_set_token_type< + Arg0: ProxyArg>, + Arg1: ProxyArg, + >( + self, + token_id: Arg0, + token_type: Arg1, + ) -> TxTypedCall { + let tx = self + .wrapped_tx + .payment(NotPayable) + .raw_call(ESDT_SET_TOKEN_TYPE_FUNC_NAME) + .argument(&token_id) + .argument(&token_type); + + tx.original_result() + } +} diff --git a/tools/interactor-system-func-calls/src/system_sc_interact.rs b/tools/interactor-system-func-calls/src/system_sc_interact.rs index 28ecc05034..c3a81c29de 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact.rs @@ -224,6 +224,7 @@ pub async fn system_sc_interact_cli() { pub struct SysFuncCallsInteract { interactor: Interactor, wallet_address: Bech32Address, + other_wallet_address: Bech32Address, #[allow(unused)] state: State, } @@ -236,6 +237,7 @@ impl SysFuncCallsInteract { interactor.set_current_dir_from_workspace("tools/interactor-system-func-calls"); let wallet_address = interactor.register_wallet(test_wallets::alice()).await; + let other_wallet_address = interactor.register_wallet(test_wallets::mike()).await; // generate blocks until ESDTSystemSCAddress is enabled interactor.generate_blocks_until_epoch(1).await.unwrap(); @@ -243,6 +245,7 @@ impl SysFuncCallsInteract { Self { interactor, wallet_address: wallet_address.into(), + other_wallet_address: other_wallet_address.into(), state: State::load_state(), } } @@ -426,6 +429,25 @@ impl SysFuncCallsInteract { token_id } + pub async fn set_roles_for_other(&mut self, token_id: &[u8], roles: Vec) { + let wallet_address = &self.other_wallet_address.clone().into_address(); + println!("Setting the following roles: {roles:?} for {token_id:?} for other_address"); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .set_special_roles( + ManagedAddress::from_address(wallet_address), + TokenIdentifier::from(token_id), + roles.into_iter(), + ) + .run() + .await; + } + pub async fn set_roles(&mut self, token_id: &[u8], roles: Vec) { let wallet_address = &self.wallet_address.clone().into_address(); println!("Setting the following roles: {roles:?} for {token_id:?}"); @@ -812,9 +834,9 @@ impl SysFuncCallsInteract { self.interactor .tx() .from(&self.wallet_address) - .to(&self.wallet_address) + .to(SystemSCAddress) .gas(100_000_000u64) - .typed(UserBuiltinProxy) + .typed(SystemSCProxy) .esdt_set_token_type(token_id, token_type) .run() .await; @@ -853,16 +875,28 @@ impl SysFuncCallsInteract { .await; } + pub async fn send_esdt(&mut self, token_id: &[u8], nonce: u64, amount: RustBigUint) { + println!("Sending token {token_id:?} with nonce {nonce:?} to other_wallet_address..."); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.other_wallet_address) + .single_esdt(&token_id.into(), nonce, &amount.into()) // .transfer() + .run() + .await; + } + // changes creator into caller pub async fn modify_creator(&mut self, token_id: &[u8], nonce: u64) { println!( - "Modifying the creator (into caller) for token {token_id:?} with nonce {nonce:?}..." + "Modifying the creator (into caller - other_wallet_address) for token {token_id:?} with nonce {nonce:?}..." ); self.interactor .tx() - .from(&self.wallet_address) - .to(&self.wallet_address) + .from(&self.other_wallet_address) + .to(&self.other_wallet_address) .gas(100_000_000u64) .typed(UserBuiltinProxy) .esdt_nft_modify_creator(token_id, nonce) diff --git a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs index ba0f83c9f7..42cb4fa5c8 100644 --- a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs +++ b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs @@ -1,4 +1,4 @@ -use multiversx_sc_snippets::imports::{EsdtTokenType, RustBigUint}; +use multiversx_sc_snippets::imports::{EsdtLocalRole, EsdtTokenType, RustBigUint}; use system_sc_interact::{Config, NftDummyAttributes, SysFuncCallsInteract}; const ISSUE_COST: u64 = 50000000000000000u64; @@ -213,3 +213,86 @@ async fn update_token_test() { // update NFT interact.update_token(nft_token_id.as_bytes()).await; } + +#[tokio::test] +#[ignore = "run on demand"] +async fn set_token_type_test() { + let mut interact = SysFuncCallsInteract::init(Config::load_config()).await; + + // issue dynamic SFT with all roles + let dynamic_sft_token_id = interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::DynamicSFT, + ) + .await; + + // set token type to dynamicMeta + interact + .set_token_type(dynamic_sft_token_id.as_bytes(), EsdtTokenType::DynamicMeta) + .await; +} + +#[tokio::test] +#[ignore = "run on demand"] +async fn modify_creator() { + let mut interact = SysFuncCallsInteract::init(Config::load_config()).await; + + // issue dynamic NFT + let dynamic_nft_token_id = interact + .issue_dynamic_token( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + EsdtTokenType::DynamicNFT, + 0usize, + ) + .await; + + // set roles + interact + .set_roles( + dynamic_nft_token_id.as_bytes(), + vec![EsdtLocalRole::NftCreate], + ) + .await; + + // mint NFT + let nonce = interact + .mint_nft( + dynamic_nft_token_id.as_bytes(), + RustBigUint::from(1u64), + b"myNFT", + 30u64, + b"", + &NftDummyAttributes { + creation_epoch: 2u64, + cool_factor: 3u8, + }, + Vec::new(), + ) + .await; + + println!("Dynamic NFT minted at nonce {nonce:?}"); + + // set roles for other_address + interact + .set_roles_for_other( + dynamic_nft_token_id.as_bytes(), + vec![EsdtLocalRole::ModifyCreator], + ) + .await; + + // send to other_address + interact + .send_esdt(dynamic_nft_token_id.as_bytes(), 1u64, 1u64.into()) + .await; + + // modify creator + interact + .modify_creator(dynamic_nft_token_id.as_bytes(), nonce) + .await; +} From a2e6d34b0643e8373eefd6541d17c44791e14f64 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 6 Dec 2024 10:51:59 +0100 Subject: [PATCH 09/17] removed system sc proxy and interaction along with setTokenType, can be called by meta only --- .../contract_base/wrappers/send_wrapper.rs | 12 +-- .../base/src/types/interaction/markers.rs | 2 - .../interaction/markers/system_sc_address.rs | 75 ------------------- .../src/system_sc_interact.rs | 14 ---- .../tests/chain_simulator_token_tests.rs | 22 ------ 5 files changed, 1 insertion(+), 124 deletions(-) delete mode 100644 framework/base/src/types/interaction/markers/system_sc_address.rs diff --git a/framework/base/src/contract_base/wrappers/send_wrapper.rs b/framework/base/src/contract_base/wrappers/send_wrapper.rs index a10041550a..9fe01f232a 100644 --- a/framework/base/src/contract_base/wrappers/send_wrapper.rs +++ b/framework/base/src/contract_base/wrappers/send_wrapper.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; use crate::codec::Empty; -use crate::types::{ManagedRef, SystemSCAddress}; +use crate::types::ManagedRef; use crate::{ api::{BlockchainApi, CallTypeApi, StorageReadApi}, codec, @@ -63,16 +63,6 @@ where .typed(system_proxy::ESDTSystemSCProxy) } - /// Prepares a proxy object to call the system SC. - /// It has the destination address set, as well as the contract type (as specified in the proxy). - pub fn system_sc_tx( - &self, - ) -> system_proxy::SystemSCProxyMethods, (), SystemSCAddress, ()> { - Tx::new_tx_from_sc() - .to(SystemSCAddress) - .typed(system_proxy::SystemSCProxy) - } - /// Convenient way to quickly instance a minimal contract call (with no EGLD, no arguments, etc.) /// /// You can further configure this contract call by chaining methods to it. diff --git a/framework/base/src/types/interaction/markers.rs b/framework/base/src/types/interaction/markers.rs index c804844400..4ebce757cc 100644 --- a/framework/base/src/types/interaction/markers.rs +++ b/framework/base/src/types/interaction/markers.rs @@ -1,11 +1,9 @@ mod esdt_system_sc_address; mod gas_left; -mod system_sc_address; mod to_caller; mod to_self; pub use esdt_system_sc_address::ESDTSystemSCAddress; pub use gas_left::GasLeft; -pub use system_sc_address::SystemSCAddress; pub use to_caller::ToCaller; pub use to_self::ToSelf; diff --git a/framework/base/src/types/interaction/markers/system_sc_address.rs b/framework/base/src/types/interaction/markers/system_sc_address.rs deleted file mode 100644 index e7d5ea1642..0000000000 --- a/framework/base/src/types/interaction/markers/system_sc_address.rs +++ /dev/null @@ -1,75 +0,0 @@ -use hex_literal::hex; -use multiversx_chain_core::types::Address; -use multiversx_sc_codec::{EncodeErrorHandler, TopEncode, TopEncodeOutput}; - -use crate::{ - abi::TypeAbiFrom, - api::ManagedTypeApi, - types::{AnnotatedValue, ManagedAddress, ManagedBuffer, TxEnv, TxTo, TxToSpecified}, -}; - -/// Address of the system smart contract that manages ESDT. -const SYSTEM_SC_ADDRESS_BYTES: [u8; 32] = - hex!("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01"); -const SYSTEM_SC_ADDRESS_BECH32: &str = - "erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366"; -const SYSTEM_SC_ADDRESS_ANNOTATION: &str = - "bech32:erd1llllllllllllllllllllllllllllllllllllllllllllllllluqsl6e366"; - -/// Indicates the system SC address, which is the same on any MultiversX blockchain. -pub struct SystemSCAddress; - -impl SystemSCAddress { - pub fn to_managed_address(self) -> ManagedAddress - where - Api: ManagedTypeApi, - { - ManagedAddress::from(SYSTEM_SC_ADDRESS_BYTES) - } - - pub fn to_address(&self) -> Address { - SYSTEM_SC_ADDRESS_BYTES.into() - } - - pub fn to_bech32_str(&self) -> &str { - SYSTEM_SC_ADDRESS_BECH32 - } - - pub fn to_bech32_string(&self) -> alloc::string::String { - SYSTEM_SC_ADDRESS_BECH32.into() - } -} - -impl AnnotatedValue> for SystemSCAddress -where - Env: TxEnv, -{ - fn annotation(&self, _env: &Env) -> ManagedBuffer { - ManagedBuffer::from(SYSTEM_SC_ADDRESS_ANNOTATION) - } - - fn to_value(&self, _env: &Env) -> ManagedAddress { - SystemSCAddress.to_managed_address() - } -} - -impl TxTo for SystemSCAddress where Env: TxEnv {} -impl TxToSpecified for SystemSCAddress where Env: TxEnv {} - -impl TopEncode for SystemSCAddress { - fn top_encode_or_handle_err(&self, output: O, h: H) -> Result<(), H::HandledErr> - where - O: TopEncodeOutput, - H: EncodeErrorHandler, - { - SYSTEM_SC_ADDRESS_BYTES.top_encode_or_handle_err(output, h) - } -} - -impl TypeAbiFrom for ManagedAddress where M: ManagedTypeApi {} - -impl core::fmt::Display for SystemSCAddress { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.write_str(SYSTEM_SC_ADDRESS_BECH32) - } -} diff --git a/tools/interactor-system-func-calls/src/system_sc_interact.rs b/tools/interactor-system-func-calls/src/system_sc_interact.rs index c3a81c29de..1e7c8ec1df 100644 --- a/tools/interactor-system-func-calls/src/system_sc_interact.rs +++ b/tools/interactor-system-func-calls/src/system_sc_interact.rs @@ -828,20 +828,6 @@ impl SysFuncCallsInteract { .await; } - pub async fn set_token_type(&mut self, token_id: &[u8], token_type: EsdtTokenType) { - println!("Setting token type to {token_type:?} for token {token_id:?}..."); - - self.interactor - .tx() - .from(&self.wallet_address) - .to(SystemSCAddress) - .gas(100_000_000u64) - .typed(SystemSCProxy) - .esdt_set_token_type(token_id, token_type) - .run() - .await; - } - pub async fn modify_royalties(&mut self, token_id: &[u8], nonce: u64, new_royalty: u64) { println!("Modifying royalties for token {token_id:?} into {new_royalty:?}..."); diff --git a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs index 42cb4fa5c8..f950dc7592 100644 --- a/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs +++ b/tools/interactor-system-func-calls/tests/chain_simulator_token_tests.rs @@ -214,28 +214,6 @@ async fn update_token_test() { interact.update_token(nft_token_id.as_bytes()).await; } -#[tokio::test] -#[ignore = "run on demand"] -async fn set_token_type_test() { - let mut interact = SysFuncCallsInteract::init(Config::load_config()).await; - - // issue dynamic SFT with all roles - let dynamic_sft_token_id = interact - .issue_token_all_roles( - RustBigUint::from(ISSUE_COST), - b"TESTNFT", - b"TEST", - 0usize, - EsdtTokenType::DynamicSFT, - ) - .await; - - // set token type to dynamicMeta - interact - .set_token_type(dynamic_sft_token_id.as_bytes(), EsdtTokenType::DynamicMeta) - .await; -} - #[tokio::test] #[ignore = "run on demand"] async fn modify_creator() { From 46a476dcf044edbf5cf30822b59a2579533d35df Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 9 Dec 2024 13:45:25 +0100 Subject: [PATCH 10/17] forwarder setup, cleanup --- chain/core/src/builtin_func_names.rs | 1 - .../forwarder/src/forwarder_main.rs | 2 + .../forwarder/src/fwd_dynamic.rs | 120 ++++++++++++++++++ .../composability/forwarder/wasm/src/lib.rs | 12 +- .../src/types/interaction/system_proxy.rs | 2 - .../system_proxy/system_sc_proxy.rs | 61 --------- 6 files changed, 132 insertions(+), 66 deletions(-) create mode 100644 contracts/feature-tests/composability/forwarder/src/fwd_dynamic.rs delete mode 100644 framework/base/src/types/interaction/system_proxy/system_sc_proxy.rs diff --git a/chain/core/src/builtin_func_names.rs b/chain/core/src/builtin_func_names.rs index 51777f201b..9ab2b202ed 100644 --- a/chain/core/src/builtin_func_names.rs +++ b/chain/core/src/builtin_func_names.rs @@ -14,7 +14,6 @@ pub const SET_USERNAME_FUNC_NAME: &str = "SetUserName"; pub const MIGRATE_USERNAME_FUNC_NAME: &str = "migrateUserName"; pub const DELETE_USERNAME_FUNC_NAME: &str = "DeleteUserName"; pub const UPGRADE_CONTRACT_FUNC_NAME: &str = "upgradeContract"; -pub const ESDT_SET_TOKEN_TYPE_FUNC_NAME: &str = "ESDTSetTokenType"; pub const ESDT_MODIFY_ROYALTIES_FUNC_NAME: &str = "ESDTModifyRoyalties"; pub const ESDT_SET_NEW_URIS_FUNC_NAME: &str = "ESDTSetNewURIs"; pub const ESDT_MODIFY_CREATOR_FUNC_NAME: &str = "ESDTModifyCreator"; diff --git a/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs b/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs index c6e9dcb443..fa75226891 100644 --- a/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs +++ b/contracts/feature-tests/composability/forwarder/src/forwarder_main.rs @@ -7,6 +7,7 @@ pub mod fwd_call_sync; pub mod fwd_call_transf_exec; pub mod fwd_change_owner; pub mod fwd_deploy; +pub mod fwd_dynamic; pub mod fwd_esdt; pub mod fwd_nft; pub mod fwd_roles; @@ -31,6 +32,7 @@ pub trait Forwarder: + fwd_sft::ForwarderSftModule + fwd_nft::ForwarderNftModule + fwd_roles::ForwarderRolesModule + + fwd_dynamic::ForwarderDynamicModule + fwd_storage::ForwarderStorageModule { #[init] diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_dynamic.rs b/contracts/feature-tests/composability/forwarder/src/fwd_dynamic.rs new file mode 100644 index 0000000000..f7a53c8f84 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder/src/fwd_dynamic.rs @@ -0,0 +1,120 @@ +use crate::fwd_nft::{CallbackProxy, Color}; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait ForwarderDynamicModule: + crate::fwd_nft::ForwarderNftModule + crate::fwd_storage::ForwarderStorageModule +{ + #[payable["EGLD"]] + #[endpoint] + fn issue_dynamic_token( + &self, + token_display_name: ManagedBuffer, + token_ticker: ManagedBuffer, + token_type: EsdtTokenType, + num_decimals: usize, + ) { + let issue_cost = self.call_value().egld_value().clone_value(); + let caller = self.blockchain().get_caller(); + + self.send() + .esdt_system_sc_proxy() + .issue_dynamic( + issue_cost, + token_display_name, + token_ticker, + token_type, + num_decimals, + ) + .callback(self.callbacks().nft_issue_callback(&caller)) + .async_call_and_exit(); + } + + #[endpoint] + fn change_to_dynamic(&self, token_id: TokenIdentifier) { + self.send() + .esdt_system_sc_proxy() + .change_to_dynamic(token_id) + .sync_call(); + } + + #[endpoint] + fn update_token(&self, token_id: TokenIdentifier) { + self.send() + .esdt_system_sc_proxy() + .update_token(token_id) + .sync_call(); + } + + #[endpoint] + fn modify_royalties(&self, token_id: TokenIdentifier, nonce: u64, new_royalty: u64) { + self.send() + .esdt_modify_royalties(&token_id, nonce, new_royalty); + } + + #[endpoint] + fn set_new_uris( + &self, + token_id: TokenIdentifier, + nonce: u64, + new_uris: MultiValueEncoded, + ) { + let new_uris = new_uris.to_vec(); + self.send() + .esdt_nft_set_new_uris(&token_id, nonce, &new_uris); + } + + #[endpoint] + fn modify_creator(&self, token_id: TokenIdentifier, nonce: u64) { + self.send().esdt_nft_modify_creator(&token_id, nonce); + } + + #[endpoint] + fn metadata_recreate( + &self, + token_id: TokenIdentifier, + nonce: u64, + name: ManagedBuffer, + royalties: u64, + hash: ManagedBuffer, + new_attributes: Color, + uris: MultiValueEncoded, + ) { + let uris = uris.to_vec(); + + self.send().esdt_metadata_recreate( + token_id, + nonce, + name, + royalties, + hash, + &new_attributes, + uris, + ); + } + + #[endpoint] + fn metadata_update( + &self, + token_id: TokenIdentifier, + nonce: u64, + name: ManagedBuffer, + royalties: u64, + hash: ManagedBuffer, + new_attributes: Color, + uris: MultiValueEncoded, + ) { + let uris = uris.to_vec(); + + self.send().esdt_metadata_update( + token_id, + nonce, + name, + royalties, + hash, + &new_attributes, + uris, + ); + } +} diff --git a/contracts/feature-tests/composability/forwarder/wasm/src/lib.rs b/contracts/feature-tests/composability/forwarder/wasm/src/lib.rs index 74d50dd752..7b6e32ddea 100644 --- a/contracts/feature-tests/composability/forwarder/wasm/src/lib.rs +++ b/contracts/feature-tests/composability/forwarder/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 69 +// Endpoints: 77 // Async Callback: 1 -// Total number of exported functions: 71 +// Total number of exported functions: 79 #![no_std] @@ -85,6 +85,14 @@ multiversx_sc_wasm_adapter::endpoints! { create_and_send => create_and_send setLocalRoles => set_local_roles unsetLocalRoles => unset_local_roles + issue_dynamic_token => issue_dynamic_token + change_to_dynamic => change_to_dynamic + update_token => update_token + modify_royalties => modify_royalties + set_new_uris => set_new_uris + modify_creator => modify_creator + metadata_recreate => metadata_recreate + metadata_update => metadata_update lastIssuedToken => last_issued_token lastErrorMessage => last_error_message ) diff --git a/framework/base/src/types/interaction/system_proxy.rs b/framework/base/src/types/interaction/system_proxy.rs index d6a3e084be..e86c9f32ff 100644 --- a/framework/base/src/types/interaction/system_proxy.rs +++ b/framework/base/src/types/interaction/system_proxy.rs @@ -1,11 +1,9 @@ mod builtin_func_proxy; mod esdt_system_sc_proxy; mod legacy_system_sc_proxy; -mod system_sc_proxy; pub(crate) mod token_properties; pub use builtin_func_proxy::*; pub use esdt_system_sc_proxy::{ESDTSystemSCProxy, ESDTSystemSCProxyMethods, IssueCall}; pub use legacy_system_sc_proxy::ESDTSystemSmartContractProxy; -pub use system_sc_proxy::{SystemSCProxy, SystemSCProxyMethods}; pub use token_properties::*; diff --git a/framework/base/src/types/interaction/system_proxy/system_sc_proxy.rs b/framework/base/src/types/interaction/system_proxy/system_sc_proxy.rs deleted file mode 100644 index 1e5b3af66b..0000000000 --- a/framework/base/src/types/interaction/system_proxy/system_sc_proxy.rs +++ /dev/null @@ -1,61 +0,0 @@ -use multiversx_chain_core::builtin_func_names::ESDT_SET_TOKEN_TYPE_FUNC_NAME; - -use crate::types::{ - EsdtTokenType, NotPayable, ProxyArg, TokenIdentifier, Tx, TxEnv, TxFrom, TxGas, TxProxyTrait, - TxTo, TxTypedCall, -}; - -/// Proxy for the system smart contract. -pub struct SystemSCProxy; - -impl TxProxyTrait for SystemSCProxy -where - Env: TxEnv, - From: TxFrom, - To: TxTo, - Gas: TxGas, -{ - type TxProxyMethods = SystemSCProxyMethods; - - fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { - SystemSCProxyMethods { wrapped_tx: tx } - } -} - -/// Method container of the ESDT system smart contract proxy. -pub struct SystemSCProxyMethods -where - Env: TxEnv, - From: TxFrom, - To: TxTo, - Gas: TxGas, -{ - wrapped_tx: Tx, -} - -impl SystemSCProxyMethods -where - Env: TxEnv, - From: TxFrom, - To: TxTo, - Gas: TxGas, -{ - /// Sets the token type for a specific token. - pub fn esdt_set_token_type< - Arg0: ProxyArg>, - Arg1: ProxyArg, - >( - self, - token_id: Arg0, - token_type: Arg1, - ) -> TxTypedCall { - let tx = self - .wrapped_tx - .payment(NotPayable) - .raw_call(ESDT_SET_TOKEN_TYPE_FUNC_NAME) - .argument(&token_id) - .argument(&token_type); - - tx.original_result() - } -} From e856a908ea066778b890a3fabf8c65461440319c Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 9 Dec 2024 14:06:30 +0100 Subject: [PATCH 11/17] proxy update --- .../forwarder/src/forwarder_proxy.rs | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs b/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs index d8ef19f3a4..964df0bf23 100644 --- a/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs +++ b/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs @@ -1171,6 +1171,169 @@ where .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> { From 9602c1015680f317f035c30bd43e947d2697e4e4 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 9 Dec 2024 14:56:18 +0100 Subject: [PATCH 12/17] 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, From e3888bdb321da56c8a77a8cb25717c97bff144c6 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 9 Dec 2024 17:23:16 +0100 Subject: [PATCH 13/17] interactor scenarios, mandos gen --- .../forwarder_builtin_scenario.scen.json | 312 ++++++++++++ ...arder_change_to_dynamic_scenario.scen.json | 173 +++++++ .../forwarder_deploy_scenario.scen.json | 28 ++ ...orwarder_modify_creator_scenario.scen.json | 153 ++++++ .../forwarder_update_token_scenario.scen.json | 87 ++++ .../forwarder-interactor/src/config.rs | 6 + .../forwarder-interactor/src/interact.rs | 445 ++++++++++++------ .../forwarder-interactor/src/proxy.rs | 21 + .../forwarder-interactor/state.toml | 2 +- .../tests/interact_cs_tests.rs | 4 +- .../tests/interact_tests.rs | 332 ++++++++++++- .../forwarder/src/forwarder_proxy.rs | 21 + .../forwarder/src/fwd_dynamic.rs | 29 +- .../composability/forwarder/wasm/src/lib.rs | 5 +- 14 files changed, 1472 insertions(+), 146 deletions(-) create mode 100644 contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_builtin_scenario.scen.json create mode 100644 contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_change_to_dynamic_scenario.scen.json create mode 100644 contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_deploy_scenario.scen.json create mode 100644 contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_modify_creator_scenario.scen.json create mode 100644 contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_update_token_scenario.scen.json diff --git a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_builtin_scenario.scen.json b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_builtin_scenario.scen.json new file mode 100644 index 0000000000..7bdf624811 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_builtin_scenario.scen.json @@ -0,0 +1,312 @@ +{ + "steps": [ + { + "step": "setState", + "newAddresses": [ + { + "creatorAddress": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "creatorNonce": "11899", + "newAddress": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv" + } + ] + }, + { + "step": "scDeploy", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "contractCode": "mxsc:../../forwarder/output/forwarder.mxsc.json", + "arguments": [], + "gasLimit": "300000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-d49726" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "egldValue": "50000000000000000", + "function": "issue_dynamic_token", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x04", + "0x" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-38e345" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "egldValue": "50000000000000000", + "function": "issue_dynamic_token", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x05", + "0x" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-f781d6" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "egldValue": "50000000000000000", + "function": "issue_dynamic_token", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x06", + "0x12" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-2b25f7" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "egldValue": "50000000000000000", + "function": "issue_token_all_roles", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x06", + "0x" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-d0c358" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "egldValue": "50000000000000000", + "function": "issue_token_all_roles", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x05", + "0x" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-712a3f" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "egldValue": "50000000000000000", + "function": "issue_token_all_roles", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x04", + "0x" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scQuery", + "id": "", + "tx": { + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "function": "lastIssuedToken", + "arguments": [] + }, + "expect": { + "out": [ + "0x544553542d373132613366" + ], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "function": "nft_create", + "arguments": [ + "0x544553542d373132613366", + "0x01", + "0x6d794e4654", + "0x1e", + "0x", + "0x010205", + "0x73616d706c655f757269" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "function": "modify_royalties", + "arguments": [ + "0x544553542d373132613366", + "0x01", + "0x14" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "function": "set_new_uris", + "arguments": [ + "0x544553542d373132613366", + "0x01", + "0x7468697369616e7572692e636f6d" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "function": "metadata_update", + "arguments": [ + "0x544553542d373132613366", + "0x01", + "0x544553544e4654", + "0x1e", + "0x6e65775f68617368", + "0x060708" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqwzty5wrdva7ymtwfrkj23ysdaauxx6j4d8sskh9qsv", + "function": "metadata_recreate", + "arguments": [ + "0x544553542d373132613366", + "0x01", + "0x544553544e4654", + "0x1e", + "0x6e65775f686173685f726563726561746564", + "0x080808" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + } + ] +} diff --git a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_change_to_dynamic_scenario.scen.json b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_change_to_dynamic_scenario.scen.json new file mode 100644 index 0000000000..ba64c01c26 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_change_to_dynamic_scenario.scen.json @@ -0,0 +1,173 @@ +{ + "steps": [ + { + "step": "setState", + "newAddresses": [ + { + "creatorAddress": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "creatorNonce": "11911", + "newAddress": "bech32:erd1qqqqqqqqqqqqqpgqkwwmszeln3cjlxewv0a3uwgxf2ver22rd8ssdgezus" + } + ] + }, + { + "step": "scDeploy", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "contractCode": "mxsc:../../forwarder/output/forwarder.mxsc.json", + "arguments": [], + "gasLimit": "300000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-34ddd9" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqkwwmszeln3cjlxewv0a3uwgxf2ver22rd8ssdgezus", + "egldValue": "50000000000000000", + "function": "issue_token_all_roles", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x01", + "0x" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-a0503d" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqkwwmszeln3cjlxewv0a3uwgxf2ver22rd8ssdgezus", + "egldValue": "50000000000000000", + "function": "issue_token_all_roles", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x03", + "0x12" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scQuery", + "id": "", + "tx": { + "to": "bech32:erd1qqqqqqqqqqqqqpgqkwwmszeln3cjlxewv0a3uwgxf2ver22rd8ssdgezus", + "function": "lastIssuedToken", + "arguments": [] + }, + "expect": { + "out": [ + "0x544553542d613035303364" + ], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqkwwmszeln3cjlxewv0a3uwgxf2ver22rd8ssdgezus", + "function": "change_to_dynamic", + "arguments": [ + "0x544553542d613035303364" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-45f8e0" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqkwwmszeln3cjlxewv0a3uwgxf2ver22rd8ssdgezus", + "egldValue": "50000000000000000", + "function": "issue_token_all_roles", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x02", + "0x12" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scQuery", + "id": "", + "tx": { + "to": "bech32:erd1qqqqqqqqqqqqqpgqkwwmszeln3cjlxewv0a3uwgxf2ver22rd8ssdgezus", + "function": "lastIssuedToken", + "arguments": [] + }, + "expect": { + "out": [ + "0x544553542d343566386530" + ], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqkwwmszeln3cjlxewv0a3uwgxf2ver22rd8ssdgezus", + "function": "change_to_dynamic", + "arguments": [ + "0x544553542d343566386530" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + } + ] +} diff --git a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_deploy_scenario.scen.json b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_deploy_scenario.scen.json new file mode 100644 index 0000000000..09281ed0f3 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_deploy_scenario.scen.json @@ -0,0 +1,28 @@ +{ + "steps": [ + { + "step": "setState", + "newAddresses": [ + { + "creatorAddress": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "creatorNonce": "11920", + "newAddress": "bech32:erd1qqqqqqqqqqqqqpgq3tjap9t5nnat46nwdz6mtyy60na7vptnd8ss7r0jp8" + } + ] + }, + { + "step": "scDeploy", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "contractCode": "mxsc:../../forwarder/output/forwarder.mxsc.json", + "arguments": [], + "gasLimit": "300000000" + }, + "expect": { + "out": [], + "status": "0" + } + } + ] +} diff --git a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_modify_creator_scenario.scen.json b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_modify_creator_scenario.scen.json new file mode 100644 index 0000000000..fe3e78431e --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_modify_creator_scenario.scen.json @@ -0,0 +1,153 @@ +{ + "steps": [ + { + "step": "setState", + "newAddresses": [ + { + "creatorAddress": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "creatorNonce": "11928", + "newAddress": "bech32:erd1qqqqqqqqqqqqqpgqm6d7cp70y7ft6xe78f7np9agdm7vpce6d8sskuuxnu" + } + ] + }, + { + "step": "scDeploy", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "contractCode": "mxsc:../../forwarder/output/forwarder.mxsc.json", + "arguments": [], + "gasLimit": "300000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-d3c4e5" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "egldValue": "50000000000000000", + "function": "registerDynamic", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x4e4654" + ], + "gasLimit": "100000000" + }, + "expect": { + "out": [ + "0x544553542d643363346535" + ], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "function": "setSpecialRole", + "arguments": [ + "0x544553542d643363346535", + "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "0x45534454526f6c654e4654437265617465" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "function": "ESDTNFTCreate", + "arguments": [ + "0x544553542d643363346535", + "0x01", + "0x6d794e4654", + "0x1e", + "0x", + "0x010203", + "0x" + ], + "gasLimit": "100000000" + }, + "expect": { + "out": [ + "0x01" + ], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u", + "function": "setSpecialRole", + "arguments": [ + "0x544553542d643363346535", + "0x00000000000000000500de9bec07cf2792bd1b3e3a7d3097a86efcc0e33a69e1", + "0x45534454526f6c654d6f6469667943726561746f72" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "transfer", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqm6d7cp70y7ft6xe78f7np9agdm7vpce6d8sskuuxnu", + "esdtValue": [ + { + "tokenIdentifier": "0x544553542d643363346535", + "nonce": "1", + "value": "1" + } + ], + "gasLimit": "5,000,000" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqm6d7cp70y7ft6xe78f7np9agdm7vpce6d8sskuuxnu", + "function": "modify_creator", + "arguments": [ + "0x544553542d643363346535", + "0x01" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + } + ] +} \ No newline at end of file diff --git a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_update_token_scenario.scen.json b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_update_token_scenario.scen.json new file mode 100644 index 0000000000..4ddfaab647 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_update_token_scenario.scen.json @@ -0,0 +1,87 @@ +{ + "steps": [ + { + "step": "setState", + "newAddresses": [ + { + "creatorAddress": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "creatorNonce": "11917", + "newAddress": "bech32:erd1qqqqqqqqqqqqqpgqyjhk2jz7rmv7hrdcnlzwtr3pcd69hw7nd8ssjv0ryz" + } + ] + }, + { + "step": "scDeploy", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "contractCode": "mxsc:../../forwarder/output/forwarder.mxsc.json", + "arguments": [], + "gasLimit": "300000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "setState", + "newTokenIdentifiers": [ + "TEST-4ec598" + ] + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqyjhk2jz7rmv7hrdcnlzwtr3pcd69hw7nd8ssjv0ryz", + "egldValue": "50000000000000000", + "function": "issue_token_all_roles", + "arguments": [ + "0x544553544e4654", + "0x54455354", + "0x01", + "0x" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + }, + { + "step": "scQuery", + "id": "", + "tx": { + "to": "bech32:erd1qqqqqqqqqqqqqpgqyjhk2jz7rmv7hrdcnlzwtr3pcd69hw7nd8ssjv0ryz", + "function": "lastIssuedToken", + "arguments": [] + }, + "expect": { + "out": [ + "0x544553542d346563353938" + ], + "status": "0" + } + }, + { + "step": "scCall", + "id": "", + "tx": { + "from": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", + "to": "bech32:erd1qqqqqqqqqqqqqpgqyjhk2jz7rmv7hrdcnlzwtr3pcd69hw7nd8ssjv0ryz", + "function": "update_token", + "arguments": [ + "0x544553542d346563353938" + ], + "gasLimit": "80000000" + }, + "expect": { + "out": [], + "status": "0" + } + } + ] +} \ No newline at end of file diff --git a/contracts/feature-tests/composability/forwarder-interactor/src/config.rs b/contracts/feature-tests/composability/forwarder-interactor/src/config.rs index 2d072b4bfb..4c4f034bb4 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/src/config.rs +++ b/contracts/feature-tests/composability/forwarder-interactor/src/config.rs @@ -20,6 +20,12 @@ pub struct Config { pub chain_type: ChainType, } +impl Default for Config { + fn default() -> Self { + Self::new() + } +} + impl Config { // Deserializes config from file pub fn new() -> Self { diff --git a/contracts/feature-tests/composability/forwarder-interactor/src/interact.rs b/contracts/feature-tests/composability/forwarder-interactor/src/interact.rs index b4ed599a3e..bce4d4798c 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/src/interact.rs +++ b/contracts/feature-tests/composability/forwarder-interactor/src/interact.rs @@ -3,9 +3,9 @@ mod config; mod proxy; -use config::Config; +pub use config::Config; use multiversx_sc_snippets::imports::*; -use proxy::Color; +pub use proxy::Color; use serde::{Deserialize, Serialize}; use std::{ io::{Read, Write}, @@ -13,6 +13,16 @@ use std::{ }; const STATE_FILE: &str = "state.toml"; +pub const FORWARDER_DEPLOY_INTERACTOR_TRACE_PATH: &str = + "scenarios/forwarder_deploy_scenario.scen.json"; +pub const FORWARDER_BUILTIN_INTERACTOR_TRACE_PATH: &str = + "scenarios/forwarder_builtin_scenario.scen.json"; +pub const FORWARDER_CHANGE_TO_DYNAMIC_INTERACTOR_TRACE_PATH: &str = + "scenarios/forwarder_change_to_dynamic_scenario.scen.json"; +pub const FORWARDER_UPDATE_TOKEN_INTERACTOR_TRACE_PATH: &str = + "scenarios/forwarder_update_token_scenario.scen.json"; +pub const FORWARDER_MODIFY_CREATOR_INTERACTOR_TRACE_PATH: &str = + "scenarios/forwarder_modify_creator_scenario.scen.json"; pub async fn forwarder_cli() { env_logger::init(); @@ -20,7 +30,7 @@ pub async fn forwarder_cli() { 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; + let mut interact = ContractInteract::new(Config::new(), None).await; match cmd.as_str() { "deploy" => interact.deploy().await, "send_egld" => interact.send_egld().await, @@ -108,7 +118,7 @@ pub async fn forwarder_cli() { "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" => 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, @@ -120,15 +130,15 @@ pub async fn forwarder_cli() { "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, + // "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), } @@ -176,18 +186,21 @@ impl Drop for State { pub struct ContractInteract { interactor: Interactor, - wallet_address: Address, + pub wallet_address: Address, contract_code: BytesValue, - state: State, + pub state: State, } impl ContractInteract { - pub async fn new() -> Self { - let config = Config::new(); + pub async fn new(config: Config, trace_path: Option<&str>) -> Self { let mut interactor = Interactor::new(config.gateway_uri()) .await .use_chain_simulator(config.use_chain_simulator()); + if let Some(path) = trace_path { + interactor = interactor.with_tracer(path).await; + } + interactor.set_current_dir_from_workspace("forwarder-interactor"); let wallet_address = interactor.register_wallet(test_wallets::alice()).await; @@ -237,7 +250,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .send_egld(to, amount) .returns(ReturnsResultUnmanaged) @@ -260,7 +273,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .echo_arguments_sync(to, args) .payment(( @@ -288,7 +301,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .echo_arguments_sync_twice(to, args) .payment(( @@ -315,7 +328,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_sync_accept_funds(to) .payment(( @@ -340,7 +353,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_sync_accept_funds_rh_egld(to) .egld(egld_amount) @@ -363,7 +376,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_sync_accept_funds_rh_single_esdt(to) .payment(( @@ -390,7 +403,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_sync_accept_funds_rh_multi_esdt(to) .payment(( @@ -418,7 +431,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_sync_accept_funds_with_fees(to, percentage_fees) .payment(( @@ -445,7 +458,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_sync_accept_funds_then_read(to) .payment(( @@ -471,7 +484,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_sync_retrieve_funds(to, token, token_nonce, amount) .returns(ReturnsResultUnmanaged) @@ -495,7 +508,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_sync_retrieve_funds_with_accept_func(to, token, amount) .payment(( @@ -520,7 +533,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .accept_funds_func() .payment(( @@ -552,7 +565,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_sync_accept_funds_multi_transfer(to, token_payments) .returns(ReturnsResultUnmanaged) @@ -571,7 +584,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .echo_args_async(to, args) .returns(ReturnsResultUnmanaged) @@ -593,7 +606,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_async_accept_funds(to) .payment(( @@ -620,7 +633,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_async_accept_funds_half_payment(to) .payment(( @@ -648,7 +661,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_async_accept_funds_with_fees(to, percentage_fees) .payment(( @@ -674,7 +687,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_async_retrieve_funds(to, token, token_nonce, amount) .returns(ReturnsResultUnmanaged) @@ -694,7 +707,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .send_funds_twice(to, token_identifier, amount) .returns(ReturnsResultUnmanaged) @@ -721,7 +734,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .send_async_accept_multi_transfer(to, token_payments) .returns(ReturnsResultUnmanaged) @@ -767,7 +780,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .clear_callback_data() .returns(ReturnsResultUnmanaged) @@ -789,7 +802,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_transf_exec_accept_funds(to) .payment(( @@ -817,7 +830,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_transf_execu_accept_funds_with_fees(to, percentage_fees) .payment(( @@ -844,7 +857,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_transf_exec_accept_funds_twice(to) .payment(( @@ -871,7 +884,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_transf_exec_accept_funds_return_values(to) .payment(( @@ -903,7 +916,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .transf_exec_multi_accept_funds(to, token_payments) .returns(ReturnsResultUnmanaged) @@ -930,7 +943,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .forward_transf_exec_reject_funds_multi_transfer(to, token_payments) .returns(ReturnsResultUnmanaged) @@ -957,7 +970,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .transf_exec_multi_reject_funds(to, token_payments) .returns(ReturnsResultUnmanaged) @@ -976,7 +989,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .change_owner(child_sc_address, new_owner) .returns(ReturnsResultUnmanaged) @@ -995,7 +1008,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .deploy_contract(code, opt_arg) .returns(ReturnsResultUnmanaged) @@ -1013,7 +1026,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .deploy_two_contracts(code) .returns(ReturnsResultUnmanaged) @@ -1032,7 +1045,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .deploy_vault_from_source(source_address, opt_arg) .returns(ReturnsResultUnmanaged) @@ -1052,7 +1065,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .upgrade_vault(child_sc_address, new_code, opt_arg) .returns(ReturnsResultUnmanaged) @@ -1072,7 +1085,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .upgrade_vault_from_source(child_sc_address, source_address, opt_arg) .returns(ReturnsResultUnmanaged) @@ -1124,7 +1137,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .send_esdt(to, token_id, amount) .returns(ReturnsResultUnmanaged) @@ -1147,7 +1160,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .send_esdt_with_fees(to, percentage_fees) .payment(( @@ -1173,7 +1186,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .send_esdt_twice(to, token_id, amount_first_time, amount_second_time) .returns(ReturnsResultUnmanaged) @@ -1200,7 +1213,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .send_esdt_direct_multi_transfer(to, token_payments) .returns(ReturnsResultUnmanaged) @@ -1222,7 +1235,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .issue_fungible_token(token_display_name, token_ticker, initial_supply) .egld(egld_amount) @@ -1242,7 +1255,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .local_mint(token_identifier, amount) .returns(ReturnsResultUnmanaged) @@ -1261,7 +1274,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .local_burn(token_identifier, amount) .returns(ReturnsResultUnmanaged) @@ -1382,7 +1395,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .sft_issue(token_display_name, token_ticker) .egld(egld_amount) @@ -1424,7 +1437,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .buy_nft(nft_id, nft_nonce, nft_amount) .payment(( @@ -1450,7 +1463,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .nft_issue(token_display_name, token_ticker) .egld(egld_amount) @@ -1461,23 +1474,35 @@ impl ContractInteract { 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""[..]); + #[allow(clippy::too_many_arguments)] + pub async fn nft_create( + &mut self, + token_id: &[u8], + amount: RustBigUint, + name: &[u8], + royalties: u64, + hash: &[u8], + attributes: &Color, + uri: &[u8], + ) { + println!("Minting NFT..."); let response = self .interactor .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) - .nft_create(token_identifier, amount, name, royalties, hash, color, uri) + .nft_create( + token_id, + amount, + name, + royalties, + hash, + attributes, + &ManagedBuffer::from(uri), + ) .returns(ReturnsResultUnmanaged) .run() .await; @@ -1495,7 +1520,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .nft_create_compact(token_identifier, amount, color) .returns(ReturnsResultUnmanaged) @@ -1515,7 +1540,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .nft_add_uris(token_identifier, nonce, uris) .returns(ReturnsResultUnmanaged) @@ -1535,7 +1560,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .nft_update_attributes(token_identifier, nonce, new_attributes) .returns(ReturnsResultUnmanaged) @@ -1571,7 +1596,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .nft_decode_complex_attributes( token_identifier, @@ -1599,7 +1624,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .nft_add_quantity(token_identifier, nonce, amount) .returns(ReturnsResultUnmanaged) @@ -1619,7 +1644,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .nft_burn(token_identifier, nonce, amount) .returns(ReturnsResultUnmanaged) @@ -1640,7 +1665,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .transfer_nft_via_async_call(to, token_identifier, nonce, amount) .returns(ReturnsResultUnmanaged) @@ -1663,7 +1688,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .transfer_nft_and_execute(to, token_identifier, nonce, amount, function, arguments) .returns(ReturnsResultUnmanaged) @@ -1688,7 +1713,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .create_and_send( to, @@ -1717,7 +1742,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .set_local_roles(address, token_identifier, roles) .returns(ReturnsResultUnmanaged) @@ -1737,7 +1762,7 @@ impl ContractInteract { .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .unset_local_roles(address, token_identifier, roles) .returns(ReturnsResultUnmanaged) @@ -1747,23 +1772,25 @@ impl ContractInteract { 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; + pub async fn issue_dynamic_token( + &mut self, + issue_cost: RustBigUint, + token_display_name: &[u8], + token_ticker: &[u8], + token_type: EsdtTokenType, + num_decimals: usize, + ) { + println!("Registering dynamic token {token_ticker:?} of type {token_type:?}..."); let response = self .interactor .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .issue_dynamic_token(token_display_name, token_ticker, token_type, num_decimals) - .egld(egld_amount) + .egld(BigUint::from(issue_cost)) .returns(ReturnsResultUnmanaged) .run() .await; @@ -1771,17 +1798,43 @@ impl ContractInteract { println!("Result: {response:?}"); } - pub async fn change_to_dynamic(&mut self) { - let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); + pub async fn issue_token_all_roles( + &mut self, + issue_cost: RustBigUint, + token_display_name: &[u8], + token_ticker: &[u8], + num_decimals: usize, + token_type: EsdtTokenType, + ) { + println!("Registering and setting all roles for token {token_ticker:?} of type {token_type:?}..."); + + let result = self + .interactor + .tx() + .from(&self.wallet_address) + .to(self.state.current_address()) + .gas(80_000_000u64) + .typed(proxy::ForwarderProxy) + .issue_token_all_roles(token_display_name, token_ticker, token_type, num_decimals) + .egld(BigUint::from(issue_cost)) + .returns(ReturnsResultUnmanaged) + .run() + .await; + + println!("Result: {result:?}"); + } + + pub async fn change_to_dynamic(&mut self, token_id: &[u8]) { + println!("Changing the following token {token_id:?} to dynamic..."); let response = self .interactor .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) - .change_to_dynamic(token_id) + .change_to_dynamic(TokenIdentifier::from(token_id)) .returns(ReturnsResultUnmanaged) .run() .await; @@ -1789,17 +1842,15 @@ impl ContractInteract { println!("Result: {response:?}"); } - pub async fn update_token(&mut self) { - let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); - + pub async fn update_token(&mut self, token_id: &[u8]) { let response = self .interactor .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) - .update_token(token_id) + .update_token(TokenIdentifier::from(token_id)) .returns(ReturnsResultUnmanaged) .run() .await; @@ -1807,19 +1858,17 @@ impl ContractInteract { 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; + pub async fn modify_royalties(&mut self, token_id: &[u8], nonce: u64, new_royalty: u64) { + println!("Modifying royalties for token {token_id:?} into {new_royalty:?}..."); let response = self .interactor .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) - .modify_royalties(token_id, nonce, new_royalty) + .modify_royalties(TokenIdentifier::from(token_id), nonce, new_royalty) .returns(ReturnsResultUnmanaged) .run() .await; @@ -1827,19 +1876,20 @@ impl ContractInteract { 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""[..])]); + pub async fn set_new_uris(&mut self, token_id: &[u8], nonce: u64, new_uris: Vec) { + let uris = new_uris + .into_iter() + .map(ManagedBuffer::from) + .collect::>>(); let response = self .interactor .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) - .set_new_uris(token_id, nonce, new_uris) + .set_new_uris(token_id, nonce, uris) .returns(ReturnsResultUnmanaged) .run() .await; @@ -1847,18 +1897,15 @@ impl ContractInteract { println!("Result: {response:?}"); } - pub async fn modify_creator(&mut self) { - let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); - let nonce = 0u64; - + pub async fn modify_creator(&mut self, token_id: &[u8], nonce: u64) { let response = self .interactor .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) - .modify_creator(token_id, nonce) + .modify_creator(TokenIdentifier::from(token_id), nonce) .returns(ReturnsResultUnmanaged) .run() .await; @@ -1866,21 +1913,30 @@ impl ContractInteract { 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""[..])]); + #[allow(clippy::too_many_arguments)] + pub async fn metadata_recreate( + &mut self, + token_id: &[u8], + nonce: u64, + name: &[u8], + royalties: u64, + hash: &[u8], + new_attributes: &Color, + uris: Vec, + ) { + println!("Recreating the token {token_id:?} with nonce {nonce:?} with new attributes..."); + + let uris = uris + .into_iter() + .map(ManagedBuffer::from) + .collect::>>(); let response = self .interactor .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .metadata_recreate(token_id, nonce, name, royalties, hash, new_attributes, uris) .returns(ReturnsResultUnmanaged) @@ -1890,21 +1946,30 @@ impl ContractInteract { 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""[..])]); + #[allow(clippy::too_many_arguments)] + pub async fn metadata_update( + &mut self, + token_id: &[u8], + nonce: u64, + name: &[u8], + royalties: u64, + hash: &[u8], + new_attributes: &Color, + uris: Vec, + ) { + println!("Updating the token {token_id:?} with nonce {nonce:?} with new attributes..."); + + let uris = uris + .into_iter() + .map(ManagedBuffer::from) + .collect::>>(); let response = self .interactor .tx() .from(&self.wallet_address) .to(self.state.current_address()) - .gas(30_000_000u64) + .gas(80_000_000u64) .typed(proxy::ForwarderProxy) .metadata_update(token_id, nonce, name, royalties, hash, new_attributes, uris) .returns(ReturnsResultUnmanaged) @@ -1914,7 +1979,7 @@ impl ContractInteract { println!("Result: {response:?}"); } - pub async fn last_issued_token(&mut self) { + pub async fn last_issued_token(&mut self) -> String { let result_value = self .interactor .query() @@ -1926,6 +1991,8 @@ impl ContractInteract { .await; println!("Result: {result_value:?}"); + + result_value.as_managed_buffer().to_string() } pub async fn last_error_message(&mut self) { @@ -1941,4 +2008,108 @@ impl ContractInteract { println!("Result: {result_value:?}"); } + + pub async fn issue_dynamic_token_from_wallet( + &mut self, + issue_cost: RustBigUint, + token_display_name: &[u8], + token_ticker: &[u8], + token_type: EsdtTokenType, + num_decimals: usize, + ) -> String { + println!("Registering dynamic token {token_ticker:?} of type {token_type:?} from the test wallet..."); + + let token_id = self + .interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress) + .gas(100_000_000u64) + .typed(ESDTSystemSCProxy) + .issue_dynamic( + issue_cost.into(), + token_display_name, + token_ticker, + token_type, + num_decimals, + ) + .returns(ReturnsNewTokenIdentifier) + .run() + .await; + + println!("TOKEN ID: {:?}", token_id); + + token_id + } + + pub async fn set_roles_from_wallet( + &mut self, + for_address: &Address, + token_id: &[u8], + roles: Vec, + ) { + println!("Setting the following roles: {roles:?} for {token_id:?}"); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(ESDTSystemSCAddress) + .gas(80_000_000u64) + .typed(ESDTSystemSCProxy) + .set_special_roles( + ManagedAddress::from_address(for_address), + TokenIdentifier::from(token_id), + roles.into_iter(), + ) + .run() + .await; + } + + #[allow(clippy::too_many_arguments)] + pub async fn mint_nft_from_wallet( + &mut self, + token_id: &[u8], + amount: RustBigUint, + name: &[u8], + royalties: u64, + hash: &[u8], + attributes: &T, + uris: Vec, + ) -> u64 { + println!("Minting NFT..."); + + let uris = uris + .into_iter() + .map(ManagedBuffer::from) + .collect::>>(); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(&self.wallet_address) + .gas(100_000_000u64) + .typed(UserBuiltinProxy) + .esdt_nft_create(token_id, amount, name, royalties, hash, attributes, &uris) + .returns(ReturnsResult) + .run() + .await + } + + pub async fn send_esdt_from_wallet( + &mut self, + to: &Address, + token_id: &[u8], + nonce: u64, + amount: RustBigUint, + ) { + println!("Sending token {token_id:?} with nonce {nonce:?} to other_wallet_address..."); + + self.interactor + .tx() + .from(&self.wallet_address) + .to(to) + .single_esdt(&token_id.into(), nonce, &amount.into()) // .transfer() + .run() + .await; + } } diff --git a/contracts/feature-tests/composability/forwarder-interactor/src/proxy.rs b/contracts/feature-tests/composability/forwarder-interactor/src/proxy.rs index b27ce77f88..efa27be50f 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/src/proxy.rs +++ b/contracts/feature-tests/composability/forwarder-interactor/src/proxy.rs @@ -1192,6 +1192,27 @@ where .original_result() } + pub fn issue_token_all_roles< + 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_token_all_roles") + .argument(&token_display_name) + .argument(&token_ticker) + .argument(&token_type) + .argument(&num_decimals) + .original_result() + } + pub fn change_to_dynamic< Arg0: ProxyArg>, >( diff --git a/contracts/feature-tests/composability/forwarder-interactor/state.toml b/contracts/feature-tests/composability/forwarder-interactor/state.toml index 0bf61e6358..2db4efcb4e 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/state.toml +++ b/contracts/feature-tests/composability/forwarder-interactor/state.toml @@ -1 +1 @@ -contract_address = "erd1qqqqqqqqqqqqqpgqcr2nq237tg5vr3ezjvr750spkmtsjstjd8ssfp6eun" +contract_address = "erd1qqqqqqqqqqqqqpgqm6d7cp70y7ft6xe78f7np9agdm7vpce6d8sskuuxnu" 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 index b85fc01bf3..62a9c9d1a0 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/tests/interact_cs_tests.rs +++ b/contracts/feature-tests/composability/forwarder-interactor/tests/interact_cs_tests.rs @@ -1,4 +1,4 @@ -use forwarder_interact::ContractInteract; +use forwarder_interact::{Config, ContractInteract}; use multiversx_sc_snippets::imports::*; // Simple deploy test that runs using the chain simulator configuration. @@ -9,7 +9,7 @@ use multiversx_sc_snippets::imports::*; #[tokio::test] #[cfg_attr(not(feature = "chain-simulator-tests"), ignore)] async fn deploy_test_forwarder_cs() { - let mut interactor = ContractInteract::new().await; + let mut interactor = ContractInteract::new(Config::chain_simulator_config(), None).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 index 2005f0176f..59edcbbac0 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/tests/interact_tests.rs +++ b/contracts/feature-tests/composability/forwarder-interactor/tests/interact_tests.rs @@ -1,13 +1,341 @@ -use forwarder_interact::ContractInteract; +use forwarder_interact::{ + Color, Config, ContractInteract, FORWARDER_BUILTIN_INTERACTOR_TRACE_PATH, + FORWARDER_CHANGE_TO_DYNAMIC_INTERACTOR_TRACE_PATH, FORWARDER_DEPLOY_INTERACTOR_TRACE_PATH, + FORWARDER_MODIFY_CREATOR_INTERACTOR_TRACE_PATH, FORWARDER_UPDATE_TOKEN_INTERACTOR_TRACE_PATH, +}; use multiversx_sc_snippets::imports::*; +const ISSUE_COST: u64 = 50000000000000000u64; + // 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; + let mut interactor = + ContractInteract::new(Config::new(), Some(FORWARDER_DEPLOY_INTERACTOR_TRACE_PATH)).await; interactor.deploy().await; } + +#[tokio::test] +#[ignore = "run on demand"] +async fn builtin_func_tokens_test() { + let mut interact = + ContractInteract::new(Config::new(), Some(FORWARDER_BUILTIN_INTERACTOR_TRACE_PATH)).await; + + // deploy forwarder + interact.deploy().await; + + // issue dynamic NFT + interact + .issue_dynamic_token( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + EsdtTokenType::DynamicNFT, + 0usize, + ) + .await; + + // issue dynamic SFT + interact + .issue_dynamic_token( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + EsdtTokenType::DynamicSFT, + 0usize, + ) + .await; + + // issue dynamic META + interact + .issue_dynamic_token( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + EsdtTokenType::DynamicMeta, + 18usize, + ) + .await; + + // issue dynamic META with all roles + interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::DynamicMeta, + ) + .await; + + // issue dynamic SFT with all roles + interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::DynamicSFT, + ) + .await; + + // issue dynamic NFT with all roles + interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::DynamicNFT, + ) + .await; + + let dynamic_nft_token_id = interact.last_issued_token().await; + + println!("Dynamic NFT token id issued: {dynamic_nft_token_id:?}"); + + // mint NFT + interact + .nft_create( + dynamic_nft_token_id.as_bytes(), + RustBigUint::from(1u64), + b"myNFT", + 30u64, + b"", + &Color { + r: 1u8, + g: 2u8, + b: 5u8, + }, + b"sample_uri", + ) + .await; + + let nonce = 1u64; + + println!("Dynamic NFT minted at nonce {nonce:?}"); + + // modify royalties + interact + .modify_royalties(dynamic_nft_token_id.as_bytes(), nonce, 20u64) + .await; + + println!("Royalties changed for {dynamic_nft_token_id:?} with nonce {nonce:?}"); + + // set new uris + let uris = vec!["thisianuri.com".to_string()]; + interact + .set_new_uris(dynamic_nft_token_id.as_bytes(), nonce, uris) + .await; + + println!("New uris set for {dynamic_nft_token_id:?} with nonce {nonce:?}"); + + // metadata update + interact + .metadata_update( + dynamic_nft_token_id.as_bytes(), + nonce, + b"TESTNFT", + 30u64, + b"new_hash", + &Color { + r: 6u8, + g: 7u8, + b: 8u8, + }, + Vec::new(), + ) + .await; + + println!("Metadata updated for {dynamic_nft_token_id:?} with nonce {nonce:?}"); + + // metadata recreate + interact + .metadata_recreate( + dynamic_nft_token_id.as_bytes(), + nonce, + b"TESTNFT", + 30u64, + b"new_hash_recreated", + &Color { + r: 8u8, + g: 8u8, + b: 8u8, + }, + Vec::new(), + ) + .await; + + println!("Metadata recreated for {dynamic_nft_token_id:?} with nonce {nonce:?}. A new token has been created."); +} + +#[tokio::test] +#[ignore = "run on demand"] +async fn change_to_dynamic_test() { + let mut interact = ContractInteract::new( + Config::new(), + Some(FORWARDER_CHANGE_TO_DYNAMIC_INTERACTOR_TRACE_PATH), + ) + .await; + + // deploy forwarder + interact.deploy().await; + + // issue NFT with all roles + interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::NonFungible, + ) + .await; + + // issue META token with all roles + interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 18usize, + EsdtTokenType::Meta, + ) + .await; + + // get token id from the contract + let meta_token_id = interact.last_issued_token().await; + + // change META to dynamic + interact.change_to_dynamic(meta_token_id.as_bytes()).await; + + // issue SFT token with all roles + interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 18usize, + EsdtTokenType::SemiFungible, + ) + .await; + + // get token id from the contract + let sft_token_id = interact.last_issued_token().await; + + // change SFT to dynamic + interact.change_to_dynamic(sft_token_id.as_bytes()).await; +} + +#[tokio::test] +#[ignore = "run on demand"] +async fn update_token_test() { + let mut interact = ContractInteract::new( + Config::new(), + Some(FORWARDER_UPDATE_TOKEN_INTERACTOR_TRACE_PATH), + ) + .await; + + // deploy forwarder + interact.deploy().await; + + // issue NFT with all roles + interact + .issue_token_all_roles( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + 0usize, + EsdtTokenType::NonFungible, + ) + .await; + + // get token id from the contract + let nft_token_id = interact.last_issued_token().await; + + // update NFT + interact.update_token(nft_token_id.as_bytes()).await; +} + +#[tokio::test] +#[ignore = "run on demand"] +async fn modify_creator() { + let mut interact = ContractInteract::new( + Config::new(), + Some(FORWARDER_MODIFY_CREATOR_INTERACTOR_TRACE_PATH), + ) + .await; + + // deploy forwarder + interact.deploy().await; + + let wallet_address = interact.wallet_address.clone(); + let sc_address = interact.state.current_address().clone(); + + // issue dynamic NFT + let dynamic_nft_token_id = interact + .issue_dynamic_token_from_wallet( + RustBigUint::from(ISSUE_COST), + b"TESTNFT", + b"TEST", + EsdtTokenType::DynamicNFT, + 0usize, + ) + .await; + + // set roles for self to mint + interact + .set_roles_from_wallet( + &wallet_address, + dynamic_nft_token_id.as_bytes(), + vec![EsdtLocalRole::NftCreate], + ) + .await; + + // mint NFT + let nonce = interact + .mint_nft_from_wallet( + dynamic_nft_token_id.as_bytes(), + RustBigUint::from(1u64), + b"myNFT", + 30u64, + b"", + &Color { + r: 1u8, + g: 2u8, + b: 3u8, + }, + Vec::new(), + ) + .await; + + println!("Dynamic NFT minted at nonce {nonce:?}"); + + // set modify creator role for the contract + interact + .set_roles_from_wallet( + &sc_address.to_address(), + dynamic_nft_token_id.as_bytes(), + vec![EsdtLocalRole::ModifyCreator], + ) + .await; + + // send nft to the contract + interact + .send_esdt_from_wallet( + &sc_address.to_address(), + dynamic_nft_token_id.as_bytes(), + 1u64, + 1u64.into(), + ) + .await; + + // modify creator into the contract (from wallet to SC through a SC call) + interact + .modify_creator(dynamic_nft_token_id.as_bytes(), nonce) + .await; +} diff --git a/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs b/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs index b27ce77f88..efa27be50f 100644 --- a/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs +++ b/contracts/feature-tests/composability/forwarder/src/forwarder_proxy.rs @@ -1192,6 +1192,27 @@ where .original_result() } + pub fn issue_token_all_roles< + 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_token_all_roles") + .argument(&token_display_name) + .argument(&token_ticker) + .argument(&token_type) + .argument(&num_decimals) + .original_result() + } + pub fn change_to_dynamic< Arg0: ProxyArg>, >( diff --git a/contracts/feature-tests/composability/forwarder/src/fwd_dynamic.rs b/contracts/feature-tests/composability/forwarder/src/fwd_dynamic.rs index f7a53c8f84..14549d99ad 100644 --- a/contracts/feature-tests/composability/forwarder/src/fwd_dynamic.rs +++ b/contracts/feature-tests/composability/forwarder/src/fwd_dynamic.rs @@ -31,12 +31,37 @@ pub trait ForwarderDynamicModule: .async_call_and_exit(); } + #[payable["EGLD"]] + #[endpoint] + fn issue_token_all_roles( + &self, + token_display_name: ManagedBuffer, + token_ticker: ManagedBuffer, + token_type: EsdtTokenType, + num_decimals: usize, + ) { + let issue_cost = self.call_value().egld_value().clone_value(); + let caller = self.blockchain().get_caller(); + + self.send() + .esdt_system_sc_proxy() + .issue_and_set_all_roles( + issue_cost, + token_display_name, + token_ticker, + token_type, + num_decimals, + ) + .callback(self.callbacks().nft_issue_callback(&caller)) + .async_call_and_exit(); + } + #[endpoint] fn change_to_dynamic(&self, token_id: TokenIdentifier) { self.send() .esdt_system_sc_proxy() .change_to_dynamic(token_id) - .sync_call(); + .async_call_and_exit(); } #[endpoint] @@ -44,7 +69,7 @@ pub trait ForwarderDynamicModule: self.send() .esdt_system_sc_proxy() .update_token(token_id) - .sync_call(); + .async_call_and_exit(); } #[endpoint] diff --git a/contracts/feature-tests/composability/forwarder/wasm/src/lib.rs b/contracts/feature-tests/composability/forwarder/wasm/src/lib.rs index 7b6e32ddea..b9be382059 100644 --- a/contracts/feature-tests/composability/forwarder/wasm/src/lib.rs +++ b/contracts/feature-tests/composability/forwarder/wasm/src/lib.rs @@ -5,9 +5,9 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 77 +// Endpoints: 78 // Async Callback: 1 -// Total number of exported functions: 79 +// Total number of exported functions: 80 #![no_std] @@ -86,6 +86,7 @@ multiversx_sc_wasm_adapter::endpoints! { setLocalRoles => set_local_roles unsetLocalRoles => unset_local_roles issue_dynamic_token => issue_dynamic_token + issue_token_all_roles => issue_token_all_roles change_to_dynamic => change_to_dynamic update_token => update_token modify_royalties => modify_royalties From 9182948db6040e49383ce796499b70326b52f76d Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 9 Dec 2024 17:34:16 +0100 Subject: [PATCH 14/17] scenarios go tests --- .../tests/scenarios_go_tests.rs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 contracts/feature-tests/composability/forwarder-interactor/tests/scenarios_go_tests.rs diff --git a/contracts/feature-tests/composability/forwarder-interactor/tests/scenarios_go_tests.rs b/contracts/feature-tests/composability/forwarder-interactor/tests/scenarios_go_tests.rs new file mode 100644 index 0000000000..5af1edc7d5 --- /dev/null +++ b/contracts/feature-tests/composability/forwarder-interactor/tests/scenarios_go_tests.rs @@ -0,0 +1,30 @@ +use multiversx_sc_snippets::multiversx_sc_scenario::*; + +fn world() -> ScenarioWorld { + ScenarioWorld::vm_go() +} + +#[test] +fn deploy_go() { + world().run("scenarios/forwarder_deploy_scenario.scen.json"); +} + +#[test] +fn builtin_func_go() { + world().run("scenarios/forwarder_builtin_scenario.scen.json"); +} + +#[test] +fn change_to_dynamic_go() { + world().run("scenarios/forwarder_change_to_dynamic_scenario.scen.json"); +} + +#[test] +fn update_token_go() { + world().run("scenarios/forwarder_update_token_scenario.scen.json"); +} + +#[test] +fn modify_creator_go() { + world().run("scenarios/forwarder_modify_creator_scenario.scen.json"); +} From bc71228b7946df0b4c7a4aca80230aecd8cdf491 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Mon, 9 Dec 2024 18:04:23 +0100 Subject: [PATCH 15/17] ignore tests (missing syntax), accounts fix --- .../scenarios/forwarder_builtin_scenario.scen.json | 8 +++++++- .../forwarder_change_to_dynamic_scenario.scen.json | 8 +++++++- .../scenarios/forwarder_deploy_scenario.scen.json | 8 +++++++- .../scenarios/forwarder_modify_creator_scenario.scen.json | 6 ++++++ .../scenarios/forwarder_update_token_scenario.scen.json | 6 ++++++ .../forwarder-interactor/tests/scenarios_go_tests.rs | 4 ++++ 6 files changed, 37 insertions(+), 3 deletions(-) diff --git a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_builtin_scenario.scen.json b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_builtin_scenario.scen.json index 7bdf624811..29820bc45e 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_builtin_scenario.scen.json +++ b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_builtin_scenario.scen.json @@ -2,6 +2,12 @@ "steps": [ { "step": "setState", + "accounts": { + "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1": { + "nonce": "11899", + "balance": "100" + } + }, "newAddresses": [ { "creatorAddress": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", @@ -309,4 +315,4 @@ } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_change_to_dynamic_scenario.scen.json b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_change_to_dynamic_scenario.scen.json index ba64c01c26..5833c698a2 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_change_to_dynamic_scenario.scen.json +++ b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_change_to_dynamic_scenario.scen.json @@ -2,6 +2,12 @@ "steps": [ { "step": "setState", + "accounts": { + "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1": { + "nonce": "11911", + "balance": "100" + } + }, "newAddresses": [ { "creatorAddress": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", @@ -170,4 +176,4 @@ } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_deploy_scenario.scen.json b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_deploy_scenario.scen.json index 09281ed0f3..d105846d4f 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_deploy_scenario.scen.json +++ b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_deploy_scenario.scen.json @@ -2,6 +2,12 @@ "steps": [ { "step": "setState", + "accounts": { + "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1": { + "nonce": "11920", + "balance": "100" + } + }, "newAddresses": [ { "creatorAddress": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", @@ -25,4 +31,4 @@ } } ] -} +} \ No newline at end of file diff --git a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_modify_creator_scenario.scen.json b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_modify_creator_scenario.scen.json index fe3e78431e..2319138ca6 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_modify_creator_scenario.scen.json +++ b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_modify_creator_scenario.scen.json @@ -2,6 +2,12 @@ "steps": [ { "step": "setState", + "accounts": { + "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1": { + "nonce": "11928", + "balance": "100" + } + }, "newAddresses": [ { "creatorAddress": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", diff --git a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_update_token_scenario.scen.json b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_update_token_scenario.scen.json index 4ddfaab647..9724dab7d0 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_update_token_scenario.scen.json +++ b/contracts/feature-tests/composability/forwarder-interactor/scenarios/forwarder_update_token_scenario.scen.json @@ -2,6 +2,12 @@ "steps": [ { "step": "setState", + "accounts": { + "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1": { + "nonce": "11917", + "balance": "100" + } + }, "newAddresses": [ { "creatorAddress": "0x0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", diff --git a/contracts/feature-tests/composability/forwarder-interactor/tests/scenarios_go_tests.rs b/contracts/feature-tests/composability/forwarder-interactor/tests/scenarios_go_tests.rs index 5af1edc7d5..6950bf2f5c 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/tests/scenarios_go_tests.rs +++ b/contracts/feature-tests/composability/forwarder-interactor/tests/scenarios_go_tests.rs @@ -10,21 +10,25 @@ fn deploy_go() { } #[test] +#[ignore = "missing 'newTokenIdentifiers' syntax"] fn builtin_func_go() { world().run("scenarios/forwarder_builtin_scenario.scen.json"); } #[test] +#[ignore = "missing 'newTokenIdentifiers' syntax"] fn change_to_dynamic_go() { world().run("scenarios/forwarder_change_to_dynamic_scenario.scen.json"); } #[test] +#[ignore = "missing 'newTokenIdentifiers' syntax"] fn update_token_go() { world().run("scenarios/forwarder_update_token_scenario.scen.json"); } #[test] +#[ignore = "missing 'newTokenIdentifiers' syntax"] fn modify_creator_go() { world().run("scenarios/forwarder_modify_creator_scenario.scen.json"); } From c73b9cc37e33f0ec85be02966a2ca331964d933a Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 20 Dec 2024 09:02:05 +0100 Subject: [PATCH 16/17] replaced bech32::decode() with Address::zero() to avoid panics --- .../forwarder-interactor/src/interact.rs | 96 +++++++++---------- 1 file changed, 43 insertions(+), 53 deletions(-) diff --git a/contracts/feature-tests/composability/forwarder-interactor/src/interact.rs b/contracts/feature-tests/composability/forwarder-interactor/src/interact.rs index bce4d4798c..83921f981a 100644 --- a/contracts/feature-tests/composability/forwarder-interactor/src/interact.rs +++ b/contracts/feature-tests/composability/forwarder-interactor/src/interact.rs @@ -118,7 +118,6 @@ pub async fn forwarder_cli() { "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, @@ -130,15 +129,6 @@ pub async fn forwarder_cli() { "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), } @@ -242,7 +232,7 @@ impl ContractInteract { } pub async fn send_egld(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let amount = BigUint::::from(0u128); let response = self @@ -265,7 +255,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let args = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); let response = self @@ -293,7 +283,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let args = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); let response = self @@ -321,7 +311,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let response = self .interactor @@ -346,7 +336,7 @@ impl ContractInteract { pub async fn forward_sync_accept_funds_rh_egld(&mut self) { let egld_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let response = self .interactor @@ -369,7 +359,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let response = self .interactor @@ -396,7 +386,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let response = self .interactor @@ -423,7 +413,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let percentage_fees = BigUint::::from(0u128); let response = self @@ -451,7 +441,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let response = self .interactor @@ -474,7 +464,7 @@ impl ContractInteract { } pub async fn forward_sync_retrieve_funds(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token = EgldOrEsdtTokenIdentifier::esdt(&b""[..]); let token_nonce = 0u64; let amount = BigUint::::from(0u128); @@ -499,7 +489,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let token = TokenIdentifier::from_esdt_bytes(&b""[..]); let amount = BigUint::::from(0u128); @@ -549,7 +539,7 @@ impl ContractInteract { } pub async fn forward_sync_accept_funds_multi_transfer(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_payments = MultiValueVec::from(vec![MultiValue3::< TokenIdentifier, u64, @@ -576,7 +566,7 @@ impl ContractInteract { } pub async fn echo_args_async(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let args = MultiValueVec::from(vec![ManagedBuffer::new_from_bytes(&b""[..])]); let response = self @@ -599,7 +589,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let response = self .interactor @@ -626,7 +616,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let response = self .interactor @@ -653,7 +643,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let percentage_fees = BigUint::::from(0u128); let response = self @@ -677,7 +667,7 @@ impl ContractInteract { } pub async fn forward_async_retrieve_funds(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token = EgldOrEsdtTokenIdentifier::esdt(&b""[..]); let token_nonce = 0u64; let amount = BigUint::::from(0u128); @@ -698,7 +688,7 @@ impl ContractInteract { } pub async fn send_funds_twice(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_identifier = EgldOrEsdtTokenIdentifier::esdt(&b""[..]); let amount = BigUint::::from(0u128); @@ -718,7 +708,7 @@ impl ContractInteract { } pub async fn send_async_accept_multi_transfer(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_payments = MultiValueVec::from(vec![MultiValue3::< TokenIdentifier, u64, @@ -795,7 +785,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let response = self .interactor @@ -822,7 +812,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let percentage_fees = BigUint::::from(0u128); let response = self @@ -850,7 +840,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let response = self .interactor @@ -877,7 +867,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let response = self .interactor @@ -900,7 +890,7 @@ impl ContractInteract { } pub async fn transf_exec_multi_accept_funds(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_payments = MultiValueVec::from(vec![MultiValue3::< TokenIdentifier, u64, @@ -927,7 +917,7 @@ impl ContractInteract { } pub async fn forward_transf_exec_reject_funds_multi_transfer(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_payments = MultiValueVec::from(vec![MultiValue3::< TokenIdentifier, u64, @@ -954,7 +944,7 @@ impl ContractInteract { } pub async fn transf_exec_multi_reject_funds(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_payments = MultiValueVec::from(vec![MultiValue3::< TokenIdentifier, u64, @@ -981,8 +971,8 @@ impl ContractInteract { } pub async fn change_owner(&mut self) { - let child_sc_address = bech32::decode(""); - let new_owner = bech32::decode(""); + let child_sc_address = Address::zero(); + let new_owner = Address::zero(); let response = self .interactor @@ -1037,7 +1027,7 @@ impl ContractInteract { } pub async fn deploy_vault_from_source(&mut self) { - let source_address = bech32::decode(""); + let source_address = Address::zero(); let opt_arg = OptionalValue::Some(ManagedBuffer::new_from_bytes(&b""[..])); let response = self @@ -1056,7 +1046,7 @@ impl ContractInteract { } pub async fn upgrade_vault(&mut self) { - let child_sc_address = bech32::decode(""); + let child_sc_address = Address::zero(); let new_code = ManagedBuffer::new_from_bytes(&b""[..]); let opt_arg = OptionalValue::Some(ManagedBuffer::new_from_bytes(&b""[..])); @@ -1076,8 +1066,8 @@ impl ContractInteract { } pub async fn upgrade_vault_from_source(&mut self) { - let child_sc_address = bech32::decode(""); - let source_address = bech32::decode(""); + let child_sc_address = Address::zero(); + let source_address = Address::zero(); let opt_arg = OptionalValue::Some(ManagedBuffer::new_from_bytes(&b""[..])); let response = self @@ -1128,7 +1118,7 @@ impl ContractInteract { } pub async fn send_esdt(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); let amount = BigUint::::from(0u128); @@ -1152,7 +1142,7 @@ impl ContractInteract { let token_nonce = 0u64; let token_amount = BigUint::::from(0u128); - let to = bech32::decode(""); + let to = Address::zero(); let percentage_fees = BigUint::::from(0u128); let response = self @@ -1176,7 +1166,7 @@ impl ContractInteract { } pub async fn send_esdt_twice(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); let amount_first_time = BigUint::::from(0u128); let amount_second_time = BigUint::::from(0u128); @@ -1197,7 +1187,7 @@ impl ContractInteract { } pub async fn send_esdt_direct_multi_transfer(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_payments = MultiValueVec::from(vec![MultiValue3::< TokenIdentifier, u64, @@ -1301,7 +1291,7 @@ impl ContractInteract { } pub async fn get_esdt_token_data(&mut self) { - let address = bech32::decode(""); + let address = Address::zero(); let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); let nonce = 0u64; @@ -1319,7 +1309,7 @@ impl ContractInteract { } pub async fn is_esdt_frozen(&mut self) { - let address = bech32::decode(""); + let address = Address::zero(); let token_id = TokenIdentifier::from_esdt_bytes(&b""[..]); let nonce = 0u64; @@ -1655,7 +1645,7 @@ impl ContractInteract { } pub async fn transfer_nft_via_async_call(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); let nonce = 0u64; let amount = BigUint::::from(0u128); @@ -1676,7 +1666,7 @@ impl ContractInteract { } pub async fn transfer_nft_and_execute(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); let nonce = 0u64; let amount = BigUint::::from(0u128); @@ -1699,7 +1689,7 @@ impl ContractInteract { } pub async fn create_and_send(&mut self) { - let to = bech32::decode(""); + let to = Address::zero(); let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); let amount = BigUint::::from(0u128); let name = ManagedBuffer::new_from_bytes(&b""[..]); @@ -1733,7 +1723,7 @@ impl ContractInteract { } pub async fn set_local_roles(&mut self) { - let address = bech32::decode(""); + let address = Address::zero(); let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); let roles = MultiValueVec::::new(); @@ -1753,7 +1743,7 @@ impl ContractInteract { } pub async fn unset_local_roles(&mut self) { - let address = bech32::decode(""); + let address = Address::zero(); let token_identifier = TokenIdentifier::from_esdt_bytes(&b""[..]); let roles = MultiValueVec::::new(); From 24ddb51e80e30c3eabf6ffe67a32275d71e00bc2 Mon Sep 17 00:00:00 2001 From: Mihai Calin Luca Date: Fri, 20 Dec 2024 10:41:19 +0100 Subject: [PATCH 17/17] force home package version for nightly builds ci/cd fix --- framework/meta/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/meta/Cargo.toml b/framework/meta/Cargo.toml index 3d92426f81..1b07fca11b 100644 --- a/framework/meta/Cargo.toml +++ b/framework/meta/Cargo.toml @@ -40,7 +40,8 @@ copy_dir = "0.1.2" pathdiff = "0.2.1" common-path = "1.0.0" bip39 = "2.0.0" -home = "0.5.2" +# TODO: 0.5.11 doesn't support rustc 1.80, needs >= 1.81 (issue on ci/cd for nightly builds) +home = "=0.5.5" [dependencies.multiversx-sc-meta-lib] version = "=0.54.5"