diff --git a/contracts/examples/adder/src/adder_proxy.rs b/contracts/examples/adder/src/adder_proxy.rs index c1b5195101..72e85655f8 100644 --- a/contracts/examples/adder/src/adder_proxy.rs +++ b/contracts/examples/adder/src/adder_proxy.rs @@ -4,7 +4,7 @@ #![allow(clippy::all)] -use multiversx_sc::imports::*; +use multiversx_sc::proxy_imports::*; pub struct AdderProxy; @@ -39,15 +39,26 @@ where From: TxFrom, Gas: TxGas, { - pub fn init>>( + pub fn init< + Arg0: CodecInto>, + >( self, initial_value: Arg0, - ) -> Tx, OriginalResultMarker<()>> { + ) -> Tx< + Env, + From, + (), + (), + Gas, + DeployCall, + OriginalResultMarker<()>, + > { self.wrapped_tx .raw_deploy() .argument(&initial_value) .original_result() } + } impl AdderProxyMethods where @@ -66,7 +77,7 @@ where (), Gas, FunctionCall, - OriginalResultMarker>, + OriginalResultMarker>, > { self.wrapped_tx .raw_call() @@ -74,15 +85,26 @@ where .original_result() } - /// Add desired amount to the storage variable. - pub fn add>>( + /// Add desired amount to the storage variable. + pub fn add< + Arg0: CodecInto>, + >( self, value: Arg0, - ) -> Tx, OriginalResultMarker<()>> { + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { self.wrapped_tx .raw_call() .function_name("add") .argument(&value) .original_result() } + } diff --git a/contracts/examples/crowdfunding-esdt/sc-config.toml b/contracts/examples/crowdfunding-esdt/sc-config.toml new file mode 100644 index 0000000000..6539909c96 --- /dev/null +++ b/contracts/examples/crowdfunding-esdt/sc-config.toml @@ -0,0 +1,2 @@ +[settings] +proxy-paths = ["src/crowdfunding_esdt_proxy.rs"] diff --git a/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs b/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs index 8fa04d2e46..abe8420d82 100644 --- a/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs +++ b/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt.rs @@ -1,8 +1,10 @@ #![no_std] use multiversx_sc::{derive_imports::*, imports::*}; +pub mod crowdfunding_esdt_proxy; -#[derive(TopEncode, TopDecode, TypeAbi, PartialEq, Eq, Clone, Copy, Debug)] +#[type_abi] +#[derive(TopEncode, TopDecode, PartialEq, Eq, Clone, Copy, Debug)] pub enum Status { FundingPeriod, Successful, diff --git a/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt_proxy.rs b/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt_proxy.rs new file mode 100644 index 0000000000..fbbcec61d4 --- /dev/null +++ b/contracts/examples/crowdfunding-esdt/src/crowdfunding_esdt_proxy.rs @@ -0,0 +1,224 @@ +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct CrowdfundingProxy; + +impl TxProxyTrait for CrowdfundingProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = CrowdfundingProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + CrowdfundingProxyMethods { wrapped_tx: tx } + } +} + +pub struct CrowdfundingProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +impl CrowdfundingProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init< + Arg0: CodecInto>, + Arg1: CodecInto, + Arg2: CodecInto>, + >( + self, + target: Arg0, + deadline: Arg1, + token_identifier: Arg2, + ) -> Tx< + Env, + From, + (), + (), + Gas, + DeployCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_deploy() + .argument(&target) + .argument(&deadline) + .argument(&token_identifier) + .original_result() + } + +} +impl CrowdfundingProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn fund( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("fund") + .original_result() + } + + pub fn status( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("status") + .original_result() + } + + pub fn get_current_funds( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("getCurrentFunds") + .original_result() + } + + pub fn claim( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("claim") + .original_result() + } + + pub fn target( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("getTarget") + .original_result() + } + + pub fn deadline( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("getDeadline") + .original_result() + } + + pub fn deposit< + Arg0: CodecInto>, + >( + self, + donor: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("getDeposit") + .argument(&donor) + .original_result() + } + + pub fn cf_token_identifier( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("getCrowdfundingTokenIdentifier") + .original_result() + } + +} +#[derive(TopEncode, TopDecode, PartialEq, Eq, Clone, Copy, Debug)] +pub enum Status { + FundingPeriod, + Successful, + Failed, +} + diff --git a/contracts/examples/crypto-zombies/sc-config.toml b/contracts/examples/crypto-zombies/sc-config.toml new file mode 100644 index 0000000000..d43702bdfa --- /dev/null +++ b/contracts/examples/crypto-zombies/sc-config.toml @@ -0,0 +1,2 @@ +[settings] +proxy-paths = ["src/proxy_crypto_zombies.rs"] \ No newline at end of file diff --git a/contracts/examples/crypto-zombies/src/lib.rs b/contracts/examples/crypto-zombies/src/lib.rs index f2f47688ad..05364f6f31 100644 --- a/contracts/examples/crypto-zombies/src/lib.rs +++ b/contracts/examples/crypto-zombies/src/lib.rs @@ -3,6 +3,7 @@ use multiversx_sc::imports::*; mod crypto_kitties_proxy; +pub mod proxy_crypto_zombies; mod storage; mod zombie; mod zombie_attack; diff --git a/contracts/examples/crypto-zombies/src/proxy_crypto_zombies.rs b/contracts/examples/crypto-zombies/src/proxy_crypto_zombies.rs new file mode 100644 index 0000000000..ea1a1ef4a6 --- /dev/null +++ b/contracts/examples/crypto-zombies/src/proxy_crypto_zombies.rs @@ -0,0 +1,425 @@ +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct CryptoZombiesProxy; + +impl TxProxyTrait for CryptoZombiesProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = CryptoZombiesProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + CryptoZombiesProxyMethods { wrapped_tx: tx } + } +} + +pub struct CryptoZombiesProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +impl CryptoZombiesProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init( + self, + ) -> Tx< + Env, + From, + (), + (), + Gas, + DeployCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_deploy() + .original_result() + } + +} +impl CryptoZombiesProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn set_crypto_kitties_sc_address< + Arg0: CodecInto>, + >( + self, + address: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("set_crypto_kitties_sc_address") + .argument(&address) + .original_result() + } + + pub fn generate_random_dna( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("generate_random_dna") + .original_result() + } + + pub fn create_random_zombie< + Arg0: CodecInto>, + >( + self, + name: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("create_random_zombie") + .argument(&name) + .original_result() + } + + pub fn is_ready< + Arg0: CodecInto, + >( + self, + zombie_id: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("is_ready") + .argument(&zombie_id) + .original_result() + } + + pub fn feed_on_kitty< + Arg0: CodecInto, + Arg1: CodecInto, + >( + self, + zombie_id: Arg0, + kitty_id: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("feed_on_kitty") + .argument(&zombie_id) + .argument(&kitty_id) + .original_result() + } + + pub fn dna_digits( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("dna_digits") + .original_result() + } + + pub fn zombies_count( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("zombies_count") + .original_result() + } + + pub fn zombies< + Arg0: CodecInto, + >( + self, + id: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("zombies") + .argument(&id) + .original_result() + } + + pub fn zombie_owner< + Arg0: CodecInto, + >( + self, + id: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("zombie_owner") + .argument(&id) + .original_result() + } + + pub fn crypto_kitties_sc_address( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("crypto_kitties_sc_address") + .original_result() + } + + pub fn cooldown_time( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("cooldown_time") + .original_result() + } + + pub fn owned_zombies< + Arg0: CodecInto>, + >( + self, + owner: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("owned_zombies") + .argument(&owner) + .original_result() + } + + pub fn level_up< + Arg0: CodecInto, + >( + self, + zombie_id: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("level_up") + .argument(&zombie_id) + .original_result() + } + + pub fn withdraw( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("withdraw") + .original_result() + } + + pub fn change_name< + Arg0: CodecInto, + Arg1: CodecInto>, + >( + self, + zombie_id: Arg0, + name: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("change_name") + .argument(&zombie_id) + .argument(&name) + .original_result() + } + + pub fn change_dna< + Arg0: CodecInto, + Arg1: CodecInto, + >( + self, + zombie_id: Arg0, + dna: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("change_dna") + .argument(&zombie_id) + .argument(&dna) + .original_result() + } + + pub fn attack< + Arg0: CodecInto, + Arg1: CodecInto, + >( + self, + zombie_id: Arg0, + target_id: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("attack") + .argument(&zombie_id) + .argument(&target_id) + .original_result() + } + +} +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct Zombie +where + Api: ManagedTypeApi, +{ + pub name: ManagedBuffer, + pub dna: u64, + pub level: u16, + pub ready_time: u64, + pub win_count: usize, + pub loss_count: usize, +} + diff --git a/contracts/examples/crypto-zombies/src/zombie.rs b/contracts/examples/crypto-zombies/src/zombie.rs index 414c343f28..bfe3fd22ad 100644 --- a/contracts/examples/crypto-zombies/src/zombie.rs +++ b/contracts/examples/crypto-zombies/src/zombie.rs @@ -1,6 +1,7 @@ use multiversx_sc::{derive_imports::*, imports::*}; -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct Zombie { pub name: ManagedBuffer, pub dna: u64, diff --git a/contracts/examples/crypto-zombies/wasm/src/lib.rs b/contracts/examples/crypto-zombies/wasm/src/lib.rs index 44f5f426c8..ffc350bc7d 100644 --- a/contracts/examples/crypto-zombies/wasm/src/lib.rs +++ b/contracts/examples/crypto-zombies/wasm/src/lib.rs @@ -5,9 +5,10 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 18 +// Upgrade: 1 +// Endpoints: 17 // Async Callback: 1 -// Total number of exported functions: 20 +// Total number of exported functions: 19 #![no_std] #![allow(internal_features)] diff --git a/contracts/examples/digital-cash/sc-config.toml b/contracts/examples/digital-cash/sc-config.toml new file mode 100644 index 0000000000..e33ce56689 --- /dev/null +++ b/contracts/examples/digital-cash/sc-config.toml @@ -0,0 +1,2 @@ +[settings] +proxy-paths = ["src/digital_cash_proxy.rs"] \ No newline at end of file diff --git a/contracts/examples/digital-cash/src/deposit_info.rs b/contracts/examples/digital-cash/src/deposit_info.rs index 9fb14661ea..daef136feb 100644 --- a/contracts/examples/digital-cash/src/deposit_info.rs +++ b/contracts/examples/digital-cash/src/deposit_info.rs @@ -1,6 +1,7 @@ use multiversx_sc::{derive_imports::*, imports::*}; -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct DepositInfo { pub depositor_address: ManagedAddress, pub esdt_funds: ManagedVec>, @@ -24,7 +25,8 @@ where } } -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct Fee { pub num_token_to_transfer: usize, pub value: EgldOrEsdtTokenPayment, diff --git a/contracts/examples/digital-cash/src/digital_cash.rs b/contracts/examples/digital-cash/src/digital_cash.rs index b46c2b7331..052faca2ef 100644 --- a/contracts/examples/digital-cash/src/digital_cash.rs +++ b/contracts/examples/digital-cash/src/digital_cash.rs @@ -5,6 +5,7 @@ use multiversx_sc::imports::*; mod constants; mod deposit_info; +pub mod digital_cash_proxy; mod helpers; mod pay_fee_and_fund; mod signature_operations; diff --git a/contracts/examples/digital-cash/src/digital_cash_proxy.rs b/contracts/examples/digital-cash/src/digital_cash_proxy.rs new file mode 100644 index 0000000000..75dc624b92 --- /dev/null +++ b/contracts/examples/digital-cash/src/digital_cash_proxy.rs @@ -0,0 +1,371 @@ +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct DigitalCashProxy; + +impl TxProxyTrait for DigitalCashProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = DigitalCashProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + DigitalCashProxyMethods { wrapped_tx: tx } + } +} + +pub struct DigitalCashProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +impl DigitalCashProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn init< + Arg0: CodecInto>, + Arg1: CodecInto>, + >( + self, + fee: Arg0, + token: Arg1, + ) -> Tx< + Env, + From, + (), + (), + Gas, + DeployCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_deploy() + .argument(&fee) + .argument(&token) + .original_result() + } + +} +impl DigitalCashProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn whitelist_fee_token< + Arg0: CodecInto>, + Arg1: CodecInto>, + >( + self, + fee: Arg0, + token: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("whitelistFeeToken") + .argument(&fee) + .argument(&token) + .original_result() + } + + pub fn blacklist_fee_token< + Arg0: CodecInto>, + >( + self, + token: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("blacklistFeeToken") + .argument(&token) + .original_result() + } + + pub fn claim_fees( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("claimFees") + .original_result() + } + + pub fn get_amount< + Arg0: CodecInto>, + Arg1: CodecInto>, + Arg2: CodecInto, + >( + self, + address: Arg0, + token: Arg1, + nonce: Arg2, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("getAmount") + .argument(&address) + .argument(&token) + .argument(&nonce) + .original_result() + } + + pub fn pay_fee_and_fund_esdt< + Arg0: CodecInto>, + Arg1: CodecInto, + >( + self, + address: Arg0, + valability: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("payFeeAndFundESDT") + .argument(&address) + .argument(&valability) + .original_result() + } + + pub fn pay_fee_and_fund_egld< + Arg0: CodecInto>, + Arg1: CodecInto, + >( + self, + address: Arg0, + valability: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("payFeeAndFundEGLD") + .argument(&address) + .argument(&valability) + .original_result() + } + + pub fn fund< + Arg0: CodecInto>, + Arg1: CodecInto, + >( + self, + address: Arg0, + valability: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("fund") + .argument(&address) + .argument(&valability) + .original_result() + } + + pub fn deposit_fees< + Arg0: CodecInto>, + >( + self, + address: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("depositFees") + .argument(&address) + .original_result() + } + + pub fn withdraw< + Arg0: CodecInto>, + >( + self, + address: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("withdraw") + .argument(&address) + .original_result() + } + + pub fn claim< + Arg0: CodecInto>, + Arg1: CodecInto>, + >( + self, + address: Arg0, + signature: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("claim") + .argument(&address) + .argument(&signature) + .original_result() + } + + pub fn forward< + Arg0: CodecInto>, + Arg1: CodecInto>, + Arg2: CodecInto>, + >( + self, + address: Arg0, + forward_address: Arg1, + signature: Arg2, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("forward") + .argument(&address) + .argument(&forward_address) + .argument(&signature) + .original_result() + } + + pub fn deposit< + Arg0: CodecInto>, + >( + self, + donor: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("deposit") + .argument(&donor) + .original_result() + } + +} +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct DepositInfo +where + Api: ManagedTypeApi, +{ + pub depositor_address: ManagedAddress, + pub esdt_funds: ManagedVec>, + pub egld_funds: BigUint, + pub valability: u64, + pub expiration_round: u64, + pub fees: Fee, +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct Fee +where + Api: ManagedTypeApi, +{ + pub num_token_to_transfer: usize, + pub value: EgldOrEsdtTokenPayment, +} + diff --git a/contracts/examples/multisig/sc-config.toml b/contracts/examples/multisig/sc-config.toml index ca6a294c4f..00417afac7 100644 --- a/contracts/examples/multisig/sc-config.toml +++ b/contracts/examples/multisig/sc-config.toml @@ -1,4 +1,5 @@ [settings] +proxy-paths = ["src/multisig_proxy.rs"] main = "main" [contracts.main] diff --git a/contracts/examples/multisig/src/action.rs b/contracts/examples/multisig/src/action.rs index d36af70f90..c26c83259a 100644 --- a/contracts/examples/multisig/src/action.rs +++ b/contracts/examples/multisig/src/action.rs @@ -5,7 +5,8 @@ use multiversx_sc::{ use multiversx_sc::derive_imports::*; -#[derive(NestedEncode, NestedDecode, TypeAbi, Clone)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, Clone)] pub struct CallActionData { pub to: ManagedAddress, pub egld_amount: BigUint, @@ -13,7 +14,8 @@ pub struct CallActionData { pub arguments: ManagedVec>, } -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi, Clone)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, Clone)] pub enum Action { Nothing, AddBoardMember(ManagedAddress), @@ -47,7 +49,8 @@ impl Action { } /// Not used internally, just to retrieve results via endpoint. -#[derive(TopEncode, TypeAbi)] +#[type_abi] +#[derive(TopEncode)] pub struct ActionFullInfo { pub action_id: usize, pub action_data: Action, diff --git a/contracts/examples/multisig/src/multisig.rs b/contracts/examples/multisig/src/multisig.rs index da8c81d21f..96d3d5cdfa 100644 --- a/contracts/examples/multisig/src/multisig.rs +++ b/contracts/examples/multisig/src/multisig.rs @@ -4,8 +4,8 @@ pub mod action; pub mod multisig_events; pub mod multisig_perform; pub mod multisig_propose; +pub mod multisig_proxy; pub mod multisig_state; -pub mod proxy; pub mod user_role; use action::ActionFullInfo; diff --git a/contracts/examples/multisig/src/proxy.rs b/contracts/examples/multisig/src/multisig_proxy.rs similarity index 91% rename from contracts/examples/multisig/src/proxy.rs rename to contracts/examples/multisig/src/multisig_proxy.rs index 73b99ea08c..330637de69 100644 --- a/contracts/examples/multisig/src/proxy.rs +++ b/contracts/examples/multisig/src/multisig_proxy.rs @@ -4,8 +4,7 @@ #![allow(clippy::all)] -use multiversx_sc::imports::*; -use crate as multisig; +use multiversx_sc::proxy_imports::*; pub struct MultisigProxy; @@ -104,7 +103,7 @@ where (), Gas, FunctionCall, - OriginalResultMarker>>, + OriginalResultMarker>>, > { self.wrapped_tx .raw_call() @@ -154,7 +153,7 @@ where (), Gas, FunctionCall, - OriginalResultMarker, + OriginalResultMarker, > { self.wrapped_tx .raw_call() @@ -356,7 +355,7 @@ where (), Gas, FunctionCall, - OriginalResultMarker>, + OriginalResultMarker>, > { self.wrapped_tx .raw_call() @@ -722,3 +721,58 @@ where } } +#[derive(TopEncode)] +pub struct ActionFullInfo +where + Api: ManagedTypeApi, +{ + pub action_id: usize, + pub action_data: Action, + pub signers: ManagedVec>, +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, Clone)] +pub enum Action +where + Api: ManagedTypeApi, +{ + Nothing, + AddBoardMember(ManagedAddress), + AddProposer(ManagedAddress), + RemoveUser(ManagedAddress), + ChangeQuorum(usize), + SendTransferExecute(CallActionData), + SendAsyncCall(CallActionData), + SCDeployFromSource { + amount: BigUint, + source: ManagedAddress, + code_metadata: CodeMetadata, + arguments: ManagedVec>, + }, + SCUpgradeFromSource { + sc_address: ManagedAddress, + amount: BigUint, + source: ManagedAddress, + code_metadata: CodeMetadata, + arguments: ManagedVec>, + }, +} + +#[derive(NestedEncode, NestedDecode, Clone)] +pub struct CallActionData +where + Api: ManagedTypeApi, +{ + pub to: ManagedAddress, + pub egld_amount: BigUint, + pub endpoint_name: ManagedBuffer, + pub arguments: ManagedVec>, +} + +#[derive(TopEncode, TopDecode)] +pub enum UserRole { + None, + Proposer, + BoardMember, +} + diff --git a/contracts/feature-tests/abi-tester/sc-config.toml b/contracts/feature-tests/abi-tester/sc-config.toml index 5a61f68d47..20d63c86b8 100644 --- a/contracts/feature-tests/abi-tester/sc-config.toml +++ b/contracts/feature-tests/abi-tester/sc-config.toml @@ -1,6 +1,7 @@ # Abi-tester multi-contract config, used for testing. [settings] +proxy-paths = ["src/abi_proxy.rs"] main = "main" [contracts.main] diff --git a/contracts/feature-tests/abi-tester/src/abi_proxy.rs b/contracts/feature-tests/abi-tester/src/abi_proxy.rs new file mode 100644 index 0000000000..fe87bd79a6 --- /dev/null +++ b/contracts/feature-tests/abi-tester/src/abi_proxy.rs @@ -0,0 +1,802 @@ +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct AbiTesterProxy; + +impl TxProxyTrait for AbiTesterProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = AbiTesterProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + AbiTesterProxyMethods { wrapped_tx: tx } + } +} + +pub struct AbiTesterProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +impl AbiTesterProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + /// Contract constructor. + pub fn init< + Arg0: CodecInto, + Arg1: CodecInto, + >( + self, + _constructor_arg_1: Arg0, + _constructor_arg_2: Arg1, + ) -> Tx< + Env, + From, + (), + (), + Gas, + DeployCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_deploy() + .argument(&_constructor_arg_1) + .argument(&_constructor_arg_2) + .original_result() + } + +} +impl AbiTesterProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + /// Example endpoint docs. + pub fn echo_abi_test_type< + Arg0: CodecInto, + >( + self, + att: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("echo_abi_test_type") + .argument(&att) + .original_result() + } + + pub fn echo_enum< + Arg0: CodecInto, + >( + self, + e: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("echo_enum") + .argument(&e) + .original_result() + } + + pub fn take_managed_type< + Arg0: CodecInto>, + >( + self, + _arg: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("take_managed_type") + .argument(&_arg) + .original_result() + } + + pub fn multi_result_3( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("multi_result_3") + .original_result() + } + + pub fn multi_result_4( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("multi_result_4") + .original_result() + } + + pub fn var_args< + Arg0: CodecInto, + Arg1: CodecInto>>, + >( + self, + _simple_arg: Arg0, + _var_args: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("var_args") + .argument(&_simple_arg) + .argument(&_var_args) + .original_result() + } + + pub fn multi_result_vec( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>>, + > { + self.wrapped_tx + .raw_call() + .function_name("multi_result_vec") + .original_result() + } + + pub fn optional_arg< + Arg0: CodecInto, + Arg1: CodecInto>, + >( + self, + _simple_arg: Arg0, + _opt_args: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("optional_arg") + .argument(&_simple_arg) + .argument(&_opt_args) + .original_result() + } + + pub fn optional_result( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("optional_result") + .original_result() + } + + pub fn address_vs_h256< + Arg0: CodecInto
, + Arg1: CodecInto, + >( + self, + address: Arg0, + h256: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("address_vs_h256") + .argument(&address) + .argument(&h256) + .original_result() + } + + pub fn managed_address_vs_byte_array< + Arg0: CodecInto>, + Arg1: CodecInto>, + >( + self, + address: Arg0, + byte_array: Arg1, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, ManagedByteArray>>, + > { + self.wrapped_tx + .raw_call() + .function_name("managed_address_vs_byte_array") + .argument(&address) + .argument(&byte_array) + .original_result() + } + + pub fn esdt_local_role( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("esdt_local_role") + .original_result() + } + + pub fn esdt_token_payment( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("esdt_token_payment") + .original_result() + } + + pub fn esdt_token_data( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("esdt_token_data") + .original_result() + } + + pub fn sample_storage_mapper( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker, + > { + self.wrapped_tx + .raw_call() + .function_name("sample_storage_mapper") + .original_result() + } + + pub fn item_for_vec( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("item_for_vec") + .original_result() + } + + pub fn item_for_array_vec( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("item_for_array_vec") + .original_result() + } + + pub fn item_for_managed_vec( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("item_for_managed_vec") + .original_result() + } + + pub fn item_for_array< + Arg0: CodecInto<[OnlyShowsUpAsNestedInArray; 5]>, + >( + self, + _array: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("item_for_array") + .argument(&_array) + .original_result() + } + + pub fn item_for_box( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("item_for_box") + .original_result() + } + + pub fn item_for_boxed_slice( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("item_for_boxed_slice") + .original_result() + } + + pub fn item_for_ref< + Arg0: CodecInto, + >( + self, + _ref: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("item_for_ref") + .argument(&_ref) + .original_result() + } + + pub fn item_for_slice< + Arg0: CodecInto>, + >( + self, + _ref: Arg0, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("item_for_slice") + .argument(&_ref) + .original_result() + } + + pub fn item_for_option( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker>, + > { + self.wrapped_tx + .raw_call() + .function_name("item_for_option") + .original_result() + } + + pub fn payable_egld( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("payable_egld") + .original_result() + } + + pub fn payable_some_token( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("payable_some_token") + .original_result() + } + + pub fn payable_any_token( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("payable_any_token") + .original_result() + } + + pub fn external_view( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("external_view") + .original_result() + } + + pub fn label_a( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("label_a") + .original_result() + } + + pub fn label_b( + self, + ) -> Tx< + Env, + From, + To, + (), + Gas, + FunctionCall, + OriginalResultMarker<()>, + > { + self.wrapped_tx + .raw_call() + .function_name("label_b") + .original_result() + } + +} +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpInConstructor { + pub something: (), +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct AbiTestType { + pub nested: OnlyShowsUpAsNested01, + pub next: Option>, + pub tuple_madness: (OnlyShowsUpAsNested02, Option>), +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNested01 { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNested02 { + pub something: [u8; 0], +} + +#[derive(TopEncode, TopDecode)] +pub enum AbiEnum { + Nothing, + Something(i32), + SomethingMore(u8, OnlyShowsUpAsNested08), + SomeStruct { + a: u16, + b: OnlyShowsUpAsNested09, + }, +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNested08 { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNested09 { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct AbiManagedType +where + Api: ManagedTypeApi, +{ + pub big_uint: BigUint, + pub integer: i32, + pub managed_buffer: ManagedBuffer, +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNested03 { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNested04 { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNested05 { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNested06 { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNested07 { +} + +#[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug, Copy)] +pub enum EsdtLocalRole { + None, + Mint, + Burn, + NftCreate, + NftAddQuantity, + NftBurn, + NftAddUri, + NftUpdateAttributes, + Transfer, +} + +#[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug, ManagedVecItem)] +pub enum EsdtTokenType { + Fungible, + NonFungible, + SemiFungible, + Meta, + Invalid, +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNestedInSingleValueMapper { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNestedInVec { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNestedInArrayVec { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, ManagedVecItem)] +pub struct AbiManagedVecItem { + pub value1: u32, + pub value2: u32, +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNestedInArray { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNestedInBox { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNestedInBoxedSlice { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNestedInRef { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNestedInSlice { +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNestedInOption { +} + +#[derive(TopEncode, TopDecode)] +pub struct OnlyShowsUpInEsdtAttr { + pub field: OnlyShowsUpAsNested10, +} + +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] +pub struct OnlyShowsUpAsNested10 { +} + +#[derive(TopEncode, TopDecode)] +pub enum ExplicitDiscriminant { + Zero, + Thirty, + Twelve, + Fifty, + FiftyOne, +} + +#[derive(TopEncode, TopDecode)] +pub enum ExplicitDiscriminantMixed { + Zero, + Unit, + Tuple(u16), + Five, + Struct { + a: u8, + b: u16, + }, +} + diff --git a/contracts/feature-tests/abi-tester/src/abi_test_type.rs b/contracts/feature-tests/abi-tester/src/abi_test_type.rs index 2cc1fc4db4..ff4f76b744 100644 --- a/contracts/feature-tests/abi-tester/src/abi_test_type.rs +++ b/contracts/feature-tests/abi-tester/src/abi_test_type.rs @@ -6,7 +6,8 @@ use multiversx_sc::{ multiversx_sc::derive_imports!(); /// Its only purpose is to test that the ABI generator works fine. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct AbiTestType { /// This type should only appear here. pub nested: OnlyShowsUpAsNested01, @@ -20,7 +21,8 @@ pub struct AbiTestType { } /// Its only purpose is to test that the ABI generator works fine. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct AbiManagedType { pub big_uint: BigUint, pub integer: i32, @@ -28,13 +30,14 @@ pub struct AbiManagedType { } /// Its only purpose is to test that the ABI generator works fine. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi, ManagedVecItem)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, ManagedVecItem)] pub struct AbiManagedVecItem { pub value1: u32, pub value2: u32, } -#[derive(TypeAbi)] +#[type_abi] pub struct OnlyShowsUpInEsdtAttr { pub field: OnlyShowsUpAsNested10, } diff --git a/contracts/feature-tests/abi-tester/src/abi_tester.rs b/contracts/feature-tests/abi-tester/src/abi_tester.rs index 15fe5f3c4a..1d7226c0f9 100644 --- a/contracts/feature-tests/abi-tester/src/abi_tester.rs +++ b/contracts/feature-tests/abi-tester/src/abi_tester.rs @@ -3,6 +3,7 @@ multiversx_sc::imports!(); mod abi_enum; +pub mod abi_proxy; mod abi_test_type; mod only_nested; diff --git a/contracts/feature-tests/abi-tester/src/only_nested.rs b/contracts/feature-tests/abi-tester/src/only_nested.rs index d1e19441d0..5c960cc95a 100644 --- a/contracts/feature-tests/abi-tester/src/only_nested.rs +++ b/contracts/feature-tests/abi-tester/src/only_nested.rs @@ -1,85 +1,105 @@ multiversx_sc::derive_imports!(); /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpInConstructor { pub something: (), } /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNested01; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNested02 { pub something: [u8; 0], } /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNested03(); /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNested04; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNested05; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNested06; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNested07; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNested08; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNested09; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNested10; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNestedInSingleValueMapper; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNestedInVec; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNestedInArrayVec; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNestedInArray; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNestedInBox; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNestedInBoxedSlice; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNestedInRef; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNestedInSlice; /// Tests that the ABI generator also fetches types that only appear as fields. -#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, TypeAbi)] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode)] pub struct OnlyShowsUpAsNestedInOption; diff --git a/contracts/feature-tests/basic-features/src/types/codec_err_test_type.rs b/contracts/feature-tests/basic-features/src/types/codec_err_test_type.rs index 16350f3a5a..41c1524c41 100644 --- a/contracts/feature-tests/basic-features/src/types/codec_err_test_type.rs +++ b/contracts/feature-tests/basic-features/src/types/codec_err_test_type.rs @@ -4,11 +4,11 @@ use multiversx_sc::{ NestedDecodeInput, NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput, }, - derive::TypeAbi, + derive::type_abi, }; /// Helper type to explore encode/decode errors. -#[derive(TypeAbi)] +#[type_abi] pub struct CodecErrorTestType; impl TopEncode for CodecErrorTestType { diff --git a/framework/base/src/abi/type_abi.rs b/framework/base/src/abi/type_abi.rs index 62633e2a70..94213e7705 100644 --- a/framework/base/src/abi/type_abi.rs +++ b/framework/base/src/abi/type_abi.rs @@ -29,6 +29,7 @@ pub trait TypeAbi { docs: Vec::new(), names: Self::type_names(), contents: TypeContents::NotSpecified, + macro_attributes: Vec::new(), }, ); } diff --git a/framework/base/src/abi/type_abi_impl_basic.rs b/framework/base/src/abi/type_abi_impl_basic.rs index f2e6586e2f..c14447b2ba 100644 --- a/framework/base/src/abi/type_abi_impl_basic.rs +++ b/framework/base/src/abi/type_abi_impl_basic.rs @@ -35,7 +35,7 @@ impl TypeAbi for Box { } fn type_name_rust() -> TypeName { - T::type_name_rust() + format!("Box<{}>", T::type_name_rust()) } fn provide_type_descriptions(accumulator: &mut TDC) { @@ -56,7 +56,8 @@ impl TypeAbi for &[T] { } fn type_name_rust() -> TypeName { - format!("&[{}]", T::type_name_rust()) + // we need to convert to an owned type + format!("Box<[{}]>", T::type_name_rust()) } fn provide_type_descriptions(accumulator: &mut TDC) { @@ -98,7 +99,7 @@ impl TypeAbi for Box<[T]> { } fn type_name_rust() -> TypeName { - <&[T]>::type_name_rust() + format!("Box<[{}]>", T::type_name_rust()) } fn provide_type_descriptions(accumulator: &mut TDC) { @@ -118,7 +119,8 @@ impl TypeAbi for &str { } fn type_name_rust() -> TypeName { - "&str".into() + // we need to convert to an owned type + "Box".into() } } @@ -204,8 +206,7 @@ macro_rules! tuple_impls { $($name: TypeAbi,)+ { fn type_name() -> TypeName { - let mut repr = TypeName::from("tuple"); - repr.push_str("<"); + let mut repr = TypeName::from("tuple<"); $( if $n > 0 { repr.push(','); @@ -216,6 +217,18 @@ macro_rules! tuple_impls { repr } + fn type_name_rust() -> TypeName { + let mut repr = TypeName::from("("); + $( + if $n > 0 { + repr.push_str(", "); + } + repr.push_str($name::type_name_rust().as_str()); + )+ + repr.push(')'); + repr + } + fn provide_type_descriptions(accumulator: &mut TDC) { $( $name::provide_type_descriptions(accumulator); @@ -255,6 +268,15 @@ impl TypeAbi for [T; N] { repr } + fn type_name_rust() -> TypeName { + let mut repr = TypeName::from("["); + repr.push_str(T::type_name_rust().as_str()); + repr.push_str("; "); + repr.push_str(N.to_string().as_str()); + repr.push(']'); + repr + } + fn provide_type_descriptions(accumulator: &mut TDC) { T::provide_type_descriptions(accumulator); } diff --git a/framework/base/src/abi/type_abi_impl_codec_multi.rs b/framework/base/src/abi/type_abi_impl_codec_multi.rs index 9d34d8b5f9..9d3cce98db 100644 --- a/framework/base/src/abi/type_abi_impl_codec_multi.rs +++ b/framework/base/src/abi/type_abi_impl_codec_multi.rs @@ -12,7 +12,7 @@ impl TypeAbi for crate::codec::multi_types::MultiValueVec { } fn type_name_rust() -> TypeName { - format!("MultiValueVec<$API, {}>", T::type_name_rust()) + format!("MultiValueVec<{}>", T::type_name_rust()) } fn provide_type_descriptions(accumulator: &mut TDC) { @@ -76,6 +76,19 @@ macro_rules! multi_arg_impls { repr } + fn type_name_rust() -> TypeName { + let mut repr = TypeName::from(stringify!($mval_struct)); + repr.push('<'); + $( + if $n > 0 { + repr.push_str(", "); + } + repr.push_str($name::type_name_rust().as_str()); + )+ + repr.push('>'); + repr + } + fn provide_type_descriptions(accumulator: &mut TDC) { $( $name::provide_type_descriptions(accumulator); diff --git a/framework/base/src/abi/type_description.rs b/framework/base/src/abi/type_description.rs index b9755fcaae..f7e78ccef7 100644 --- a/framework/base/src/abi/type_description.rs +++ b/framework/base/src/abi/type_description.rs @@ -10,6 +10,7 @@ pub struct TypeDescription { pub docs: Vec, pub names: TypeNames, pub contents: TypeContents, + pub macro_attributes: Vec, } impl TypeDescription { @@ -24,16 +25,23 @@ impl TypeDescription { rust: String::new(), }, contents: TypeContents::NotSpecified, + macro_attributes: Vec::new(), }; } impl TypeDescription { /// Used in code generation. - pub fn new(docs: &[&str], names: TypeNames, contents: TypeContents) -> Self { + pub fn new( + docs: &[&str], + names: TypeNames, + contents: TypeContents, + macro_attributes: &[&str], + ) -> Self { TypeDescription { docs: docs.iter().map(|s| s.to_string()).collect(), names, contents, + macro_attributes: macro_attributes.iter().map(|s| s.to_string()).collect(), } } } @@ -83,12 +91,12 @@ impl EnumVariantDescription { pub struct StructFieldDescription { pub docs: Vec, pub name: String, - pub field_type: String, + pub field_type: TypeNames, } impl StructFieldDescription { /// Used in code generation. - pub fn new(docs: &[&str], name: &str, field_type: String) -> Self { + pub fn new(docs: &[&str], name: &str, field_type: TypeNames) -> Self { Self { docs: docs.iter().map(|s| s.to_string()).collect(), name: name.to_string(), diff --git a/framework/base/src/lib.rs b/framework/base/src/lib.rs index 7f2a8b1c2b..aa1d477897 100644 --- a/framework/base/src/lib.rs +++ b/framework/base/src/lib.rs @@ -73,6 +73,11 @@ pub mod derive_imports { NestedDecode, NestedEncode, TopDecode, TopDecodeOrDefault, TopEncode, TopEncodeOrDefault, }, - derive::{ManagedVecItem, TypeAbi}, + derive::{type_abi, ManagedVecItem, TypeAbi}, }; } + +/// Conveniently groups all imports required for generated proxies. +pub mod proxy_imports { + pub use crate::{derive_imports::*, imports::*}; +} diff --git a/framework/base/src/types/flags/esdt_local_role.rs b/framework/base/src/types/flags/esdt_local_role.rs index f0f241d931..9bc5edfc68 100644 --- a/framework/base/src/types/flags/esdt_local_role.rs +++ b/framework/base/src/types/flags/esdt_local_role.rs @@ -5,7 +5,7 @@ use crate::{ use super::EsdtLocalRoleFlags; use crate as multiversx_sc; -use crate::{derive::TypeAbi, types::ManagedVecItem}; +use crate::{derive::type_abi, types::ManagedVecItem}; static ESDT_ROLE_NONE: &[u8] = &[]; static ESDT_ROLE_LOCAL_MINT: &[u8] = b"ESDTRoleLocalMint"; @@ -17,9 +17,8 @@ static ESDT_ROLE_NFT_ADD_URI: &[u8] = b"ESDTRoleNFTAddURI"; static ESDT_ROLE_NFT_UPDATE_ATTRIBUTES: &[u8] = b"ESDTRoleNFTUpdateAttributes"; static ESDT_ROLE_TRANSFER: &[u8] = b"ESDTTransferRole"; -#[derive( - TopDecode, TopEncode, NestedDecode, NestedEncode, TypeAbi, Clone, PartialEq, Eq, Debug, Copy, -)] +#[type_abi] +#[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug, Copy)] pub enum EsdtLocalRole { None, Mint, diff --git a/framework/base/src/types/flags/esdt_token_type.rs b/framework/base/src/types/flags/esdt_token_type.rs index 2348254455..1993fd1cfa 100644 --- a/framework/base/src/types/flags/esdt_token_type.rs +++ b/framework/base/src/types/flags/esdt_token_type.rs @@ -1,6 +1,9 @@ use multiversx_sc_derive::ManagedVecItem; -use crate::codec::*; +use crate::{ + codec, + codec::derive::{NestedDecode, NestedEncode, TopDecode, TopEncode}, +}; const ESDT_TYPE_FUNGIBLE: &[u8] = b"FungibleESDT"; const ESDT_TYPE_NON_FUNGIBLE: &[u8] = b"NonFungibleESDT"; @@ -9,10 +12,14 @@ const ESDT_TYPE_META: &[u8] = b"MetaESDT"; const ESDT_TYPE_INVALID: &[u8] = &[]; use crate as multiversx_sc; // needed by the TypeAbi generated code -use crate::derive::TypeAbi; +use crate::derive::type_abi; // Note: In the current implementation, SemiFungible is never returned -#[derive(Clone, PartialEq, Eq, Debug, TypeAbi, ManagedVecItem)] + +#[type_abi] +#[derive( + TopDecode, TopEncode, NestedDecode, NestedEncode, Clone, PartialEq, Eq, Debug, ManagedVecItem, +)] pub enum EsdtTokenType { Fungible, NonFungible, @@ -80,45 +87,3 @@ impl<'a> From<&'a [u8]> for EsdtTokenType { } } } - -impl NestedEncode for EsdtTokenType { - #[inline] - fn dep_encode_or_handle_err(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr> - where - O: NestedEncodeOutput, - H: EncodeErrorHandler, - { - self.as_u8().dep_encode_or_handle_err(dest, h) - } -} - -impl TopEncode for EsdtTokenType { - #[inline] - fn top_encode_or_handle_err(&self, output: O, h: H) -> Result<(), H::HandledErr> - where - O: TopEncodeOutput, - H: EncodeErrorHandler, - { - self.as_u8().top_encode_or_handle_err(output, h) - } -} - -impl NestedDecode for EsdtTokenType { - fn dep_decode_or_handle_err(input: &mut I, h: H) -> Result - where - I: NestedDecodeInput, - H: DecodeErrorHandler, - { - Ok(Self::from(u8::dep_decode_or_handle_err(input, h)?)) - } -} - -impl TopDecode for EsdtTokenType { - fn top_decode_or_handle_err(input: I, h: H) -> Result - where - I: TopDecodeInput, - H: DecodeErrorHandler, - { - Ok(Self::from(u8::top_decode_or_handle_err(input, h)?)) - } -} diff --git a/framework/base/src/types/heap/boxed_bytes.rs b/framework/base/src/types/heap/boxed_bytes.rs index 24c08d1199..1b7c2b35e7 100644 --- a/framework/base/src/types/heap/boxed_bytes.rs +++ b/framework/base/src/types/heap/boxed_bytes.rs @@ -244,6 +244,10 @@ impl TypeAbi for BoxedBytes { fn type_name() -> TypeName { "bytes".into() } + + fn type_name_rust() -> TypeName { + "BoxedBytes".into() + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/framework/base/src/types/heap/h256.rs b/framework/base/src/types/heap/h256.rs index 5dd0a2786b..a097b0d08d 100644 --- a/framework/base/src/types/heap/h256.rs +++ b/framework/base/src/types/heap/h256.rs @@ -228,6 +228,10 @@ impl TypeAbi for H256 { fn type_name() -> TypeName { "H256".into() } + + fn type_name_rust() -> TypeName { + "H256".into() + } } #[cfg(test)] diff --git a/framework/base/src/types/heap/h256_address.rs b/framework/base/src/types/heap/h256_address.rs index e4c9b055d2..5e4712df7a 100644 --- a/framework/base/src/types/heap/h256_address.rs +++ b/framework/base/src/types/heap/h256_address.rs @@ -206,6 +206,10 @@ impl TypeAbi for Address { fn type_name() -> TypeName { "Address".into() } + + fn type_name_rust() -> TypeName { + "Address".into() + } } #[cfg(test)] diff --git a/framework/base/src/types/io/operation_completion_status.rs b/framework/base/src/types/io/operation_completion_status.rs index 207b9d760f..b69af9624a 100644 --- a/framework/base/src/types/io/operation_completion_status.rs +++ b/framework/base/src/types/io/operation_completion_status.rs @@ -98,6 +98,7 @@ impl TypeAbi for OperationCompletionStatus { INTERRUPTED_STR, ) ].to_vec()), + macro_attributes: Vec::new() }, ); } diff --git a/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs b/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs index ed2c7083a7..3635ddaba2 100644 --- a/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs +++ b/framework/base/src/types/managed/wrapped/egld_or_esdt_token_identifier.rs @@ -214,6 +214,10 @@ impl TypeAbi for EgldOrEsdtTokenIdentifier { fn type_name() -> TypeName { "EgldOrEsdtTokenIdentifier".into() } + + fn type_name_rust() -> TypeName { + "EgldOrEsdtTokenIdentifier<$API>".into() + } } impl SCDisplay for EgldOrEsdtTokenIdentifier { diff --git a/framework/base/src/types/managed/wrapped/esdt_token_data.rs b/framework/base/src/types/managed/wrapped/esdt_token_data.rs index d4b13afdbe..5bbd550299 100644 --- a/framework/base/src/types/managed/wrapped/esdt_token_data.rs +++ b/framework/base/src/types/managed/wrapped/esdt_token_data.rs @@ -12,13 +12,12 @@ use crate::{ }; use crate as multiversx_sc; // needed by the TypeAbi generated code -use crate::derive::TypeAbi; +use crate::derive::type_abi; const DECODE_ATTRIBUTE_ERROR_PREFIX: &[u8] = b"error decoding ESDT attributes: "; -#[derive( - Clone, TopDecode, TopEncode, NestedDecode, NestedEncode, TypeAbi, Debug, ManagedVecItem, -)] +#[type_abi] +#[derive(Clone, TopDecode, TopEncode, NestedDecode, NestedEncode, Debug, ManagedVecItem)] pub struct EsdtTokenData { pub token_type: EsdtTokenType, pub amount: BigUint, diff --git a/framework/base/src/types/managed/wrapped/esdt_token_payment.rs b/framework/base/src/types/managed/wrapped/esdt_token_payment.rs index 29391f5381..246b28de1d 100644 --- a/framework/base/src/types/managed/wrapped/esdt_token_payment.rs +++ b/framework/base/src/types/managed/wrapped/esdt_token_payment.rs @@ -10,12 +10,13 @@ use crate::{ derive::{NestedEncode, TopEncode}, IntoMultiValue, NestedDecode, TopDecode, }, - derive::TypeAbi, + derive::type_abi, }; use super::ManagedVec; -#[derive(TopEncode, NestedEncode, TypeAbi, Clone, PartialEq, Eq, Debug)] +#[type_abi] +#[derive(TopEncode, NestedEncode, Clone, PartialEq, Eq, Debug)] pub struct EsdtTokenPayment { pub token_identifier: TokenIdentifier, pub token_nonce: u64, diff --git a/framework/base/src/types/managed/wrapped/token_identifier.rs b/framework/base/src/types/managed/wrapped/token_identifier.rs index 329b3f2b3d..af113dbc4e 100644 --- a/framework/base/src/types/managed/wrapped/token_identifier.rs +++ b/framework/base/src/types/managed/wrapped/token_identifier.rs @@ -171,6 +171,10 @@ impl TypeAbi for TokenIdentifier { fn type_name() -> TypeName { "TokenIdentifier".into() } + + fn type_name_rust() -> TypeName { + "TokenIdentifier<$API>".into() + } } impl SCDisplay for TokenIdentifier { diff --git a/framework/derive/src/lib.rs b/framework/derive/src/lib.rs index a68d493c97..917ecb2159 100644 --- a/framework/derive/src/lib.rs +++ b/framework/derive/src/lib.rs @@ -48,8 +48,16 @@ pub fn proxy( #[proc_macro_derive(TypeAbi)] pub fn type_abi_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { - let ast = syn::parse(input).unwrap(); - type_abi_derive::type_abi_derive(&ast) + type_abi_derive::type_abi_derive(input).into() +} + +#[proc_macro_attribute] +pub fn type_abi( + args: proc_macro::TokenStream, + input: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + assert!(args.is_empty(), "#[type_abi] attribute takes no args"); + type_abi_derive::type_abi_full(input).into() } #[proc_macro_derive(ManagedVecItem)] diff --git a/framework/derive/src/parse/attributes/doc_attr.rs b/framework/derive/src/parse/attributes/doc_attr.rs index c2a670abb5..5c5ed4d41b 100644 --- a/framework/derive/src/parse/attributes/doc_attr.rs +++ b/framework/derive/src/parse/attributes/doc_attr.rs @@ -45,6 +45,24 @@ pub fn extract_doc(attrs: &[syn::Attribute]) -> Vec { .collect() } +pub fn extract_macro_attributes(attrs: &[syn::Attribute]) -> Vec { + let mut macro_attributes = Vec::new(); + + for a in attrs { + if let syn::Meta::List(list) = &a.meta { + if list.path.is_ident("derive") { + for token in list.tokens.clone().into_iter() { + if let proc_macro2::TokenTree::Ident(ident) = token { + macro_attributes.push(ident.to_string()); + } + } + } + } + } + + macro_attributes +} + fn remove_backslashes(input: &str) -> String { input .trim_matches('\"') diff --git a/framework/derive/src/parse/attributes/mod.rs b/framework/derive/src/parse/attributes/mod.rs index e355c78e61..e58c1a912e 100644 --- a/framework/derive/src/parse/attributes/mod.rs +++ b/framework/derive/src/parse/attributes/mod.rs @@ -11,7 +11,7 @@ mod trait_prop_names; mod util; pub use argument_attr::*; -pub use doc_attr::{extract_doc, OutputNameAttribute}; +pub use doc_attr::{extract_doc, extract_macro_attributes, OutputNameAttribute}; pub use endpoint_attr::*; pub use event_attr::*; pub use label_attr::*; diff --git a/framework/derive/src/type_abi_derive.rs b/framework/derive/src/type_abi_derive.rs index 2d5848cc2d..56bd71d600 100644 --- a/framework/derive/src/type_abi_derive.rs +++ b/framework/derive/src/type_abi_derive.rs @@ -1,6 +1,7 @@ +use crate::parse::attributes::extract_macro_attributes; + use super::parse::attributes::extract_doc; -use proc_macro::TokenStream; -use quote::quote; +use quote::{quote, ToTokens}; pub struct ExplicitDiscriminant { pub variant_index: usize, @@ -19,7 +20,7 @@ fn field_snippet(index: usize, field: &syn::Field) -> proc_macro2::TokenStream { field_descriptions.push(multiversx_sc::abi::StructFieldDescription::new( &[ #(#field_docs),* ], #field_name_str, - <#field_ty>::type_name(), + <#field_ty>::type_names(), )); <#field_ty>::provide_type_descriptions(accumulator); } @@ -43,8 +44,11 @@ fn fields_snippets(fields: &syn::Fields) -> Vec { } } -pub fn type_abi_derive(ast: &syn::DeriveInput) -> TokenStream { +pub fn type_abi_derive(input: proc_macro::TokenStream) -> proc_macro2::TokenStream { + let ast: syn::DeriveInput = syn::parse(input).unwrap(); let type_docs = extract_doc(ast.attrs.as_slice()); + let macro_attributes = extract_macro_attributes(ast.attrs.as_slice()); + let type_description_impl = match &ast.data { syn::Data::Struct(data_struct) => { let struct_field_snippets = fields_snippets(&data_struct.fields); @@ -61,6 +65,7 @@ pub fn type_abi_derive(ast: &syn::DeriveInput) -> TokenStream { &[ #(#type_docs),* ], type_names, multiversx_sc::abi::TypeContents::Struct(field_descriptions), + &[ #(#macro_attributes),* ], ), ); } @@ -104,6 +109,7 @@ pub fn type_abi_derive(ast: &syn::DeriveInput) -> TokenStream { &[ #(#type_docs),* ], type_names, multiversx_sc::abi::TypeContents::Enum(variant_descriptions), + &[ #(#macro_attributes),* ], ), ); } @@ -116,16 +122,29 @@ pub fn type_abi_derive(ast: &syn::DeriveInput) -> TokenStream { let name = &ast.ident; let name_str = name.to_string(); let (impl_generics, ty_generics, where_clause) = &ast.generics.split_for_impl(); - let type_abi_impl = quote! { + let name_rust = extract_rust_type(ty_generics, name_str.clone()); + quote! { impl #impl_generics multiversx_sc::abi::TypeAbi for #name #ty_generics #where_clause { fn type_name() -> multiversx_sc::abi::TypeName { #name_str.into() } + fn type_name_rust() -> multiversx_sc::abi::TypeName { + #name_rust.into() + } + #type_description_impl } - }; - type_abi_impl.into() + } +} + +pub fn type_abi_full(input: proc_macro::TokenStream) -> proc_macro2::TokenStream { + let input_conv = proc_macro2::TokenStream::from(input.clone()); + let derive_code = type_abi_derive(input); + quote! { + #input_conv + #derive_code + } } pub fn get_discriminant( @@ -170,3 +189,15 @@ pub fn get_discriminant( quote! { #next_value} } + +fn extract_rust_type(ty_generics: &syn::TypeGenerics<'_>, mut output_name: String) -> String { + let mut ty_generics_tokens = proc_macro2::TokenStream::new(); + ty_generics.to_tokens(&mut ty_generics_tokens); + + if ty_generics_tokens.to_string().is_empty() { + return output_name; + } + + output_name.push_str("<$API>"); + output_name +} diff --git a/framework/meta/src/abi_json/type_abi_json.rs b/framework/meta/src/abi_json/type_abi_json.rs index c7735f04d6..f26cc7086d 100644 --- a/framework/meta/src/abi_json/type_abi_json.rs +++ b/framework/meta/src/abi_json/type_abi_json.rs @@ -87,6 +87,7 @@ impl TypeDescriptionJson { ), _ => TypeContents::NotSpecified, }, + macro_attributes: Vec::new(), } } } @@ -108,7 +109,7 @@ impl From<&StructFieldDescription> for StructFieldDescriptionJson { StructFieldDescriptionJson { docs: abi.docs.iter().map(|d| d.to_string()).collect(), name: abi.name.to_string(), - field_type: abi.field_type.clone(), + field_type: abi.field_type.abi.clone(), } } } @@ -118,7 +119,10 @@ impl StructFieldDescriptionJson { StructFieldDescription { docs: self.docs.clone(), name: self.name.clone(), - field_type: self.field_type.clone(), + field_type: TypeNames { + abi: self.field_type.clone(), + rust: "".into(), + }, } } } diff --git a/framework/meta/src/cmd/contract/generate_proxy.rs b/framework/meta/src/cmd/contract/generate_proxy.rs index d8f689c428..4538ae77d4 100644 --- a/framework/meta/src/cmd/contract/generate_proxy.rs +++ b/framework/meta/src/cmd/contract/generate_proxy.rs @@ -3,3 +3,4 @@ pub mod proxy_gen_main; mod proxy_naming; pub mod proxy_sc_functions_gen; pub mod proxy_template_gen; +pub mod proxy_gen_struct_enum; diff --git a/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs b/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs index de47b3bc2d..a55fa334f5 100644 --- a/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs +++ b/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs @@ -5,6 +5,7 @@ use multiversx_sc::abi::ContractAbi; use super::{ super::meta_config::MetaConfig, proxy_crate_gen::create_file, + proxy_gen_struct_enum::write_types, proxy_sc_functions_gen::write_content, proxy_template_gen::{ write_header, write_impl_for_tx_proxy, write_struct_template, write_struct_tx_proxy_methods, @@ -33,4 +34,5 @@ fn write_proxy_to_file(mut file: File, abi: &ContractAbi) { write_impl_for_tx_proxy(&mut file, &abi.name); write_struct_tx_proxy_methods(&mut file, &abi.name); write_content(&mut file, abi.clone()); + write_types(&mut file, &abi.type_descriptions); } diff --git a/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_struct_enum.rs b/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_struct_enum.rs new file mode 100644 index 0000000000..2179ce4a42 --- /dev/null +++ b/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_struct_enum.rs @@ -0,0 +1,138 @@ +use std::{fs::File, io::Write}; + +use multiversx_sc::abi::{ + EnumVariantDescription, StructFieldDescription, TypeContents, TypeDescription, + TypeDescriptionContainerImpl, +}; + +use crate::cmd::contract::generate_snippets::snippet_gen_common::write_newline; + +const ZERO: &str = "0"; + +/// Types defined in the framework don't need to be generated again in the proxy. +const TYPES_FROM_FRAMEWORK: &[&str] = &[ + "EsdtTokenPayment<$API>", + "EgldOrEsdtTokenPayment<$API>", + "EsdtTokenData<$API>", + "EgldOrEsdtTokenIdentifier<$API>", + "EgldOrEsdtTokenPayment<$API>", + "EgldOrMultiEsdtPayment<$API>", + "EsdtTokenData<$API>", +]; + +pub(crate) fn write_types(file: &mut File, types: &TypeDescriptionContainerImpl) { + for (_, type_description) in &types.0 { + if TYPES_FROM_FRAMEWORK.contains(&type_description.names.rust.as_str()) { + continue; + } + + match &type_description.contents { + TypeContents::Enum(enum_variants) => write_enum(file, enum_variants, type_description), + TypeContents::Struct(struct_fields) => { + write_struct(file, struct_fields, type_description) + }, + TypeContents::NotSpecified => {}, + TypeContents::ExplicitEnum(_) => {}, + } + } +} + +fn start_write_type(file: &mut File, type_type: &str, type_description: &TypeDescription) { + let struct_name = type_description.names.rust.replace("$API", "Api"); + write_macro_attributes(file, &type_description.macro_attributes); + write!(file, r#"pub {type_type} {struct_name}"#).unwrap(); + + if struct_name.contains("") { + writeln!( + file, + r#" +where + Api: ManagedTypeApi,"# + ) + .unwrap(); + } else { + write!(file, " ").unwrap(); + } + + writeln!(file, r#"{{"#).unwrap(); +} + +fn write_struct( + file: &mut File, + struct_fields: &Vec, + type_description: &TypeDescription, +) { + start_write_type(file, "struct", type_description); + + for field in struct_fields { + writeln!( + file, + " pub {}: {},", + field.name, + field.field_type.rust.replace("$API", "Api") + ) + .unwrap(); + } + + writeln!(file, "}}").unwrap(); + write_newline(file); +} + +fn write_enum( + file: &mut File, + enum_variants: &Vec, + type_description: &TypeDescription, +) { + start_write_type(file, "enum", type_description); + + for variant in enum_variants { + write!(file, " {}", variant.name).unwrap(); + if variant.fields.is_empty() { + writeln!(file, ",").unwrap(); + continue; + } + + if variant.fields[0].name == ZERO { + write_tuple_in_variant(file, &variant.fields); + } else { + write_struct_in_variant(file, &variant.fields); + } + } + writeln!(file, "}}").unwrap(); + write_newline(file); +} + +fn write_macro_attributes(file: &mut File, macro_attributes: &[String]) { + if macro_attributes.is_empty() { + writeln!(file, "#[derive(TopEncode, TopDecode)]").unwrap(); + } else { + writeln!(file, "#[derive({})]", macro_attributes.join(", ")).unwrap(); + } +} + +fn write_struct_in_variant(file: &mut File, fields: &[StructFieldDescription]) { + writeln!(file, " {{").unwrap(); + + for field in fields { + writeln!( + file, + " {}: {},", + field.name, + field.field_type.rust.replace("$API", "Api") + ) + .unwrap(); + } + + writeln!(file, " }},").unwrap(); +} + +fn write_tuple_in_variant(file: &mut File, fields: &[StructFieldDescription]) { + write!(file, "(").unwrap(); + write!(file, "{}", fields[0].field_type.rust.replace("$API", "Api")).unwrap(); + + for field in &fields[1..] { + write!(file, ", {}", field.field_type.rust.replace("$API", "Api")).unwrap(); + } + + writeln!(file, "),").unwrap(); +} diff --git a/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs b/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs index d1909b25c6..8198bbe325 100644 --- a/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs +++ b/framework/meta/src/cmd/contract/generate_proxy/proxy_sc_functions_gen.rs @@ -210,6 +210,16 @@ fn parse_and_write_outputs(file: &mut File, outputs: Vec) { let adjusted = adjust_type_name(&outputs[0].type_names.rust); write!(file, "{adjusted}").unwrap(); }, - _ => panic!("multiple outputs not yet supported"), + _ => { + write!(file, "MultiValue{}<", outputs.len()).unwrap(); + for (i, output) in outputs.iter().enumerate() { + if i > 0 { + write!(file, ", ").unwrap(); + } + let adjusted = adjust_type_name(&output.type_names.rust); + write!(file, "{adjusted}").unwrap(); + } + write!(file, ">").unwrap(); + }, } } diff --git a/framework/meta/src/cmd/contract/generate_proxy/proxy_template_gen.rs b/framework/meta/src/cmd/contract/generate_proxy/proxy_template_gen.rs index 71dc2e2287..71b673e3a5 100644 --- a/framework/meta/src/cmd/contract/generate_proxy/proxy_template_gen.rs +++ b/framework/meta/src/cmd/contract/generate_proxy/proxy_template_gen.rs @@ -9,13 +9,13 @@ const PREFIX_AUTO_GENERATED: &str = "/////////////////////////////////////////// //////////////////////////////////////////////////// "; -const IMPORTS: &str = "#![allow(clippy::all)] +const PRELUDE: &str = "#![allow(clippy::all)] -use multiversx_sc::imports::*;"; +use multiversx_sc::proxy_imports::*;"; pub(crate) fn write_header(file: &mut File) { writeln!(file, "{PREFIX_AUTO_GENERATED}").unwrap(); - writeln!(file, r#"{IMPORTS}"#).unwrap(); + writeln!(file, r#"{PRELUDE}"#).unwrap(); write_newline(file); }