Skip to content

Commit

Permalink
EsdtTokenPaymentRefs, tx.esdt_refs, direct_esdt unified syntax impl
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-marinica committed Mar 22, 2024
1 parent 0c234ab commit 051fecf
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 29 deletions.
9 changes: 5 additions & 4 deletions framework/base/src/contract_base/wrappers/send_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,16 +188,17 @@ where
}

/// Sends a single ESDT transfer to target address.
#[inline]
#[allow(clippy::too_many_arguments)]
pub fn direct_esdt(
&self,
to: &ManagedAddress<A>,
token_identifier: &TokenIdentifier<A>,
nonce: u64,
token_nonce: u64,
amount: &BigUint<A>,
) {
self.direct_esdt_with_gas_limit(to, token_identifier, nonce, amount, 0, Empty, &[]);
Tx::new_tx_from_sc()
.to(to)
.esdt_refs(token_identifier, token_nonce, amount)
.transfer();
}

/// Sends a single ESDT transfer to target address.
Expand Down
4 changes: 2 additions & 2 deletions framework/base/src/types/interaction/contract_call_convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ where
function_call: self
.basic
.function_call
.convert_to_single_transfer_fungible_call(&payment),
.convert_to_single_transfer_fungible_call(payment.as_refs()),
explicit_gas_limit: self.basic.explicit_gas_limit,
_return_type: PhantomData,
},
Expand All @@ -55,7 +55,7 @@ where
function_call: self
.basic
.function_call
.convert_to_single_transfer_nft_call(&self.basic.to, &payment),
.convert_to_single_transfer_nft_call(&self.basic.to, payment.as_refs()),
explicit_gas_limit: self.basic.explicit_gas_limit,
_return_type: PhantomData,
},
Expand Down
9 changes: 6 additions & 3 deletions framework/base/src/types/interaction/function_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use crate::{
CallTypeApi, ManagedTypeApi, ESDT_MULTI_TRANSFER_FUNC_NAME, ESDT_NFT_TRANSFER_FUNC_NAME,
ESDT_TRANSFER_FUNC_NAME,
},
types::{EsdtTokenPayment, ManagedAddress, ManagedBuffer, ManagedVec, MultiValueEncoded},
types::{
EsdtTokenPayment, EsdtTokenPaymentRefs, ManagedAddress, ManagedBuffer, ManagedVec,
MultiValueEncoded,
},
};

use super::{ContractCallNoPayment, ManagedArgBuffer, TypedFunctionCall};
Expand Down Expand Up @@ -159,7 +162,7 @@ where
/// Constructs `ESDTTransfer` builtin function call.
pub(super) fn convert_to_single_transfer_fungible_call(
self,
payment: &EsdtTokenPayment<Api>,
payment: EsdtTokenPaymentRefs<'_, Api>,
) -> FunctionCall<Api> {
FunctionCall::new(ESDT_TRANSFER_FUNC_NAME)
.argument(&payment.token_identifier)
Expand All @@ -177,7 +180,7 @@ where
pub(super) fn convert_to_single_transfer_nft_call(
self,
to: &ManagedAddress<Api>,
payment: &EsdtTokenPayment<Api>,
payment: EsdtTokenPaymentRefs<'_, Api>,
) -> FunctionCall<Api> {
FunctionCall::new(ESDT_NFT_TRANSFER_FUNC_NAME)
.argument(&payment.token_identifier)
Expand Down
25 changes: 25 additions & 0 deletions framework/base/src/types/interaction/tx.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
api::CallTypeApi,
contract_base::BlockchainWrapper,
proxy_imports::{EsdtTokenPaymentRefs, TokenIdentifier},
types::{
BigUint, CodeMetadata, EgldOrEsdtTokenPayment, EsdtTokenPayment, ManagedAddress,
ManagedBuffer, ManagedOption, ManagedVec, MultiEsdtPayment,
Expand Down Expand Up @@ -203,6 +204,30 @@ where
}
}

/// Sets a single token payment, with the token identifier and amount kept as references.
///
/// This is handy whem we only want one ESDT transfer and we want to avoid unnecessary object clones.
pub fn esdt_refs<'a>(
self,
token_identifier: &'a TokenIdentifier<Env::Api>,
token_nonce: u64,
amount: &'a BigUint<Env::Api>,
) -> Tx<Env, From, To, EsdtTokenPaymentRefs<'a, Env::Api>, Gas, Data, RH> {
Tx {
env: self.env,
from: self.from,
to: self.to,
payment: EsdtTokenPaymentRefs {
token_identifier,
token_nonce,
amount,
},
gas: self.gas,
data: self.data,
result_handler: self.result_handler,
}
}

/// Adds a collection of ESDT payments to a transaction.
pub fn multi_esdt(
self,
Expand Down
1 change: 1 addition & 0 deletions framework/base/src/types/interaction/tx_payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod tx_payment_multi_esdt;
mod tx_payment_none;
mod tx_payment_other;
mod tx_payment_single_esdt;
mod tx_payment_single_esdt_ref;

pub use tx_payment_egld::{Egld, EgldPayment};
pub use tx_payment_egld_value::TxEgldValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,27 @@ where

fn perform_transfer_execute(
self,
_env: &Env,
env: &Env,
to: &ManagedAddress<Env::Api>,
gas_limit: u64,
fc: FunctionCall<Env::Api>,
) {
let _ = SendRawWrapper::<Env::Api>::new().multi_esdt_transfer_execute(
to,
self,
gas_limit,
&fc.function_name,
&fc.arg_buffer,
);
match self.len() {
0 => ().perform_transfer_execute(env, to, gas_limit, fc),
1 => self
.get(0)
.as_refs()
.perform_transfer_execute(env, to, gas_limit, fc),
_ => {
let _ = SendRawWrapper::<Env::Api>::new().multi_esdt_transfer_execute(
to,
self,
gas_limit,
&fc.function_name,
&fc.arg_buffer,
);
},
}
}

fn with_normalized<From, To, F, R>(
Expand All @@ -44,7 +53,7 @@ where
{
match self.len() {
0 => ().with_normalized(env, from, to, fc, f),
1 => self.get(0).with_normalized(env, from, to, fc, f),
1 => self.get(0).as_refs().with_normalized(env, from, to, fc, f),
_ => to.with_address_ref(env, |to_addr| {
let fc_conv = fc.convert_to_multi_transfer_esdt_call(to_addr, self);
f(&from.resolve_address(env), &BigUint::zero(), &fc_conv)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ where
gas_limit: u64,
fc: FunctionCall<Env::Api>,
) {
MultiEsdtPayment::from_single_item(self).perform_transfer_execute(env, to, gas_limit, fc);
self.as_refs()
.perform_transfer_execute(env, to, gas_limit, fc);
}

fn with_normalized<From, To, F, R>(
Expand All @@ -39,15 +40,7 @@ where
To: TxToSpecified<Env>,
F: FnOnce(&ManagedAddress<Env::Api>, &BigUint<Env::Api>, &FunctionCall<Env::Api>) -> R,
{
to.with_address_ref(env, |to_addr| {
if self.token_nonce == 0 {
let fc_conv = fc.convert_to_single_transfer_fungible_call(&self);
f(to_addr, &BigUint::zero(), &fc_conv)
} else {
let fc_conv = fc.convert_to_single_transfer_nft_call(to_addr, &self);
f(&from.resolve_address(env), &BigUint::zero(), &fc_conv)
}
})
self.as_refs().with_normalized(env, from, to, fc, f)
}

fn into_full_payment_data(self, _env: &Env) -> FullPaymentData<Env::Api> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use crate::{
api::ManagedTypeApi,
contract_base::SendRawWrapper,
types::{
BigUint, EsdtTokenPayment, EsdtTokenPaymentRefs, ManagedAddress, ManagedVec,
MultiEsdtPayment, TokenIdentifier, TxFrom, TxToSpecified,
},
};

use super::{AnnotatedEgldPayment, FullPaymentData, FunctionCall, TxEgldValue, TxEnv, TxPayment};

impl<'a, Env> TxPayment<Env> for EsdtTokenPaymentRefs<'a, Env::Api>
where
Env: TxEnv,
{
fn is_no_payment(&self) -> bool {
self.amount == &0u32
}

fn perform_transfer_execute(
self,
env: &Env,
to: &ManagedAddress<Env::Api>,
gas_limit: u64,
fc: FunctionCall<Env::Api>,
) {
if self.token_nonce == 0 {
// fungible ESDT
let _ = SendRawWrapper::<Env::Api>::new().transfer_esdt_execute(
to,
self.token_identifier,
self.amount,
gas_limit,
&fc.function_name,
&fc.arg_buffer,
);
} else {
// non-fungible/semi-fungible ESDT
let _ = SendRawWrapper::<Env::Api>::new().transfer_esdt_nft_execute(
to,
self.token_identifier,
self.token_nonce,
self.amount,
gas_limit,
&fc.function_name,
&fc.arg_buffer,
);
}
}

fn with_normalized<From, To, F, R>(
self,
env: &Env,
from: &From,
to: To,
fc: FunctionCall<Env::Api>,
f: F,
) -> R
where
From: TxFrom<Env>,
To: TxToSpecified<Env>,
F: FnOnce(&ManagedAddress<Env::Api>, &BigUint<Env::Api>, &FunctionCall<Env::Api>) -> R,
{
to.with_address_ref(env, |to_addr| {
if self.token_nonce == 0 {
let fc_conv = fc.convert_to_single_transfer_fungible_call(self);
f(to_addr, &BigUint::zero(), &fc_conv)
} else {
let fc_conv = fc.convert_to_single_transfer_nft_call(to_addr, self);
f(&from.resolve_address(env), &BigUint::zero(), &fc_conv)
}
})
}

fn into_full_payment_data(self, _env: &Env) -> FullPaymentData<Env::Api> {
FullPaymentData {
egld: None,
multi_esdt: MultiEsdtPayment::from_single_item(self.to_owned_payment()),
}
}
}
28 changes: 28 additions & 0 deletions framework/base/src/types/managed/wrapped/esdt_token_payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,31 @@ impl<M: ManagedTypeApi> ManagedVecItem for EsdtTokenPayment<M> {
writer(&arr[..])
}
}

/// The version of `EsdtTokenPayment` that contains referrences instead of owned fields.
pub struct EsdtTokenPaymentRefs<'a, M: ManagedTypeApi> {
pub token_identifier: &'a TokenIdentifier<M>,
pub token_nonce: u64,
pub amount: &'a BigUint<M>,
}

impl<M: ManagedTypeApi> EsdtTokenPayment<M> {
pub fn as_refs(&self) -> EsdtTokenPaymentRefs<'_, M> {
EsdtTokenPaymentRefs {
token_identifier: &self.token_identifier,
token_nonce: self.token_nonce,
amount: &self.amount,
}
}
}

impl<'a, M: ManagedTypeApi> EsdtTokenPaymentRefs<'a, M> {
/// Will clone the referenced values.
pub fn to_owned_payment(&self) -> EsdtTokenPayment<M> {
EsdtTokenPayment {
token_identifier: self.token_identifier.clone(),
token_nonce: self.token_nonce,
amount: self.amount.clone(),
}
}
}
2 changes: 1 addition & 1 deletion framework/base/src/types/managed/wrapped/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub use egld_or_esdt_token_payment::EgldOrEsdtTokenPayment;
pub use egld_or_multi_esdt_payment::EgldOrMultiEsdtPayment;
pub(crate) use encoded_managed_vec_item::EncodedManagedVecItem;
pub use esdt_token_data::EsdtTokenData;
pub use esdt_token_payment::{EsdtTokenPayment, MultiEsdtPayment};
pub use esdt_token_payment::{EsdtTokenPayment, EsdtTokenPaymentRefs, MultiEsdtPayment};
pub use managed_address::ManagedAddress;
pub use managed_buffer_cached_builder::ManagedBufferCachedBuilder;
pub(crate) use managed_byte_array::ManagedBufferSizeContext;
Expand Down

0 comments on commit 051fecf

Please sign in to comment.