multiPairSwap modified
unknown
rust
2 years ago
5.3 kB
6
Indexable
Never
#![no_std] elrond_wasm::imports!(); elrond_wasm::derive_imports!(); type SwapOperationType<M> = MultiValue4<ManagedAddress<M>, ManagedBuffer<M>, TokenIdentifier<M>, BigUint<M>>; pub const SWAP_TOKENS_FIXED_INPUT_FUNC_NAME: &[u8] = b"swapTokensFixedInput"; pub const SWAP_TOKENS_FIXED_OUTPUT_FUNC_NAME: &[u8] = b"swapTokensFixedOutput"; mod pair { elrond_wasm::imports!(); #[elrond_wasm::proxy] pub trait PairProxy { #[payable("*")] #[endpoint(swapTokensFixedInput)] fn swap_tokens_fixed_input( &self, token_out: TokenIdentifier, amount_out_min: BigUint, ); #[payable("*")] #[endpoint(swapTokensFixedOutput)] fn swap_tokens_fixed_output( &self, token_out: TokenIdentifier, amount_out: BigUint, ); } } #[elrond_wasm::module] pub trait MultiPairSwap { #[init] fn init(&self) { } #[payable("*")] #[endpoint(multiPairSwap)] fn multi_pair_swap(&self, swap_operations: MultiValueEncoded<SwapOperationType<Self::Api>>) { let (token_id, nonce, amount) = self.call_value().single_esdt().into_tuple(); let swap_fixed_input_endpoint = ManagedBuffer::from(SWAP_TOKENS_FIXED_INPUT_FUNC_NAME); let swap_fixed_output_endpoint = ManagedBuffer::from(SWAP_TOKENS_FIXED_OUTPUT_FUNC_NAME); let caller = self.blockchain().get_caller(); let mut payments = ManagedVec::new(); let mut last_payment = OldEsdtTokenPayment::new(token_id, nonce, amount); for entry in swap_operations.into_iter() { let (pair_address, function, token_wanted, amount_wanted) = entry.into_tuple(); if function == swap_fixed_input_endpoint { last_payment = self.actual_swap_fixed_input( pair_address, last_payment.token_identifier, last_payment.amount, token_wanted, amount_wanted, ); } else if function == swap_fixed_output_endpoint { let (payment, residuum) = self.actual_swap_fixed_output( pair_address, last_payment.token_identifier, last_payment.amount, token_wanted, amount_wanted, ); last_payment = payment; payments.push(residuum); } else { sc_panic!("Invalid function to call"); } } payments.push(last_payment); self.send().direct_multi(&caller, &payments); } fn actual_swap_fixed_input( &self, pair_address: ManagedAddress, token_in: TokenIdentifier, amount_in: BigUint, token_out: TokenIdentifier, amount_out_min: BigUint, ) -> OldEsdtTokenPayment<Self::Api> { self.pair_contract_proxy(pair_address) .swap_tokens_fixed_input(token_out, amount_out_min) .add_esdt_token_transfer(token_in, 0, amount_in) .execute_on_dest_context() } fn actual_swap_fixed_output( &self, pair_address: ManagedAddress, token_in: TokenIdentifier, amount_in_max: BigUint, token_out: TokenIdentifier, amount_out: BigUint, ) -> (OldEsdtTokenPayment<Self::Api>, OldEsdtTokenPayment<Self::Api>) { let call_result: MultiValue2<OldEsdtTokenPayment<Self::Api>, OldEsdtTokenPayment<Self::Api>> = self.pair_contract_proxy(pair_address) .swap_tokens_fixed_output(token_out, amount_out) .add_esdt_token_transfer(token_in, 0, amount_in_max) .execute_on_dest_context(); call_result.into_tuple() } #[proxy] fn pair_contract_proxy(&self, to: ManagedAddress) -> pair::Proxy<Self::Api>; } #[derive(TopDecode, TopEncode, NestedDecode, NestedEncode, TypeAbi, Clone, PartialEq, Debug)] pub struct OldEsdtTokenPayment<M: ManagedTypeApi> { pub token_type: EsdtTokenType, pub token_identifier: TokenIdentifier<M>, pub token_nonce: u64, pub amount: BigUint<M>, } impl<M: ManagedTypeApi> OldEsdtTokenPayment<M> { pub fn no_payment(api: M) -> Self { OldEsdtTokenPayment { token_type: EsdtTokenType::Invalid, token_identifier: TokenIdentifier::egld(), token_nonce: 0, amount: BigUint::zero(), } } pub fn new(token_identifier: TokenIdentifier<M>, token_nonce: u64, amount: BigUint<M>) -> Self { let token_type = if amount != 0 && token_identifier.is_valid_esdt_identifier() { if token_nonce == 0 { EsdtTokenType::Fungible } else if amount == 1u64 { EsdtTokenType::NonFungible } else { EsdtTokenType::SemiFungible } } else { EsdtTokenType::Invalid }; OldEsdtTokenPayment { token_type, token_identifier, token_nonce, amount, } } }