â–Ģī¸Swapping tokens

To swap tokens, you can follow the steps outlined in this section to first determine the pool contract address to interact with and the form of swap (AZERO to PSP22 token or PSP22 token to AZERO).

To swap between tokens, there are many steps that must be taken, depending on which sort of pool is involved. In this situation, we'll cover the AZERO/PSP22 and PSP22/PSP22 pairs.

Note that any given pair must exist for the swap to go through successfully, so you may have to confirm before integrating the associated swap functions.

Swapping AZERO/PSP22 Pairs

There are two methods in this scenario: swapping from AZERO to a PSP22 token or swapping from a PSP22 token to AZERO.

Note that the methods making the AZERO/PSP22 calls must be payable to allow sending and receiving AZERO.

We'll address them in very straightforward ways thus:

Swap AZERO for PSP22

To swap AZERO for a PSP22 token, we can follow these steps:

  • Determine the pair contract address

  • Initiate swap

To determine the pair contract, we can call the appropriate method as we did before and store its result in a variable PAIR_ADDRESS (we won't go into detail, since this has been explained already in the previous section).

The next step would be the one to get the estimated amount out and construct the slippage as explained in the introductory section.

We can then initiate the swap in a complete solution by creating a method thus:

fn swap_azero_for_psp22(&self, azero_amount:u128) {
    let psp22_amount_out = self.get_psp22_output(azero_amount); // Method defined in previous section
    let slippage = 100 * 10u128.pow(12); //allow any output to avoid transaction failures
    let swap: Result<Result<(), LangError>, Error> = build_call::<DefaultEnvironment>()
        .call_type(
            Call::new().callee(AZERO_PAIR_ADDRESS)
            .transferred_value(azero_amount)
        )
        .exec_input(
            ExecutionInput::new(Selector::new(
                [0x92, 0xb0, 0xce, 0x2b]
            ))
            .push_arg(psp22_amount_out)
            .push_arg(slippage)
        )
        .call_flags(CallFlags::default().set_allow_reentry(true)) //Ignore this line or set to false if it's not a reentrant call
        .returns::<Result<(), LangError>>()
        .fire();
    
    match swap {
        Err(_) => {
            panic!("Failed call")
        }
        Ok(Err(_)) => {
            panic!("Failed call")
        }
        Ok(Ok(())) => {/*Swap successful*/}
    }
}

Swap PSP22 for AZERO

To swap a PSP22 token for AZERO, we can follow these steps:

  • Determine the pair contract address

  • Approve the input PSP22 token

  • Initiate swap

We can determine the pair contract address as we did with the previous example.

We also get the allowance of the callee contract to spend from the caller, offer extra allowance and then approve the PSP22 token for a transfer to be possible on their behalf.

The next step also would be the one to get the estimated amount out and construct the slippage as explained in the introductory section.

We can then initiate the swap in a complete solution by creating a method thus:

fn swap_psp22_for_azero(&self, psp22_amount:u128) {
    let azero_amount_out = self.get_azero_output(psp22_amount); // Method defined in previous section
    let slippage = 100 * 10u128.pow(12); //allow any output to avoid transaction failures
    let old_allowance = self.get_allowance(PSP22_TOKEN, AZERO_PAIR_ADDRESS);
    let new_allowance = allowance + psp22_amount;
    self.approve_tokens(PSP22_TOKEN, AZERO_PAIR_ADDRESS, new_allowance);
    let swap: Result<Result<(), LangError>, Error> = build_call::<DefaultEnvironment>()
        .call_type(
            Call::new().callee(AZERO_PAIR_ADDRESS)
        )
        .exec_input(
            ExecutionInput::new(Selector::new(
                [0x7a, 0xfc, 0x21, 0x94]
            ))
            .push_arg(psp22_amount)
            .push_arg(azero_amount_out)
            .push_arg(slippage)
        )
        .call_flags(CallFlags::default().set_allow_reentry(true)) //Ignore this line or set to false if it's not a reentrant call
        .returns::<Result<(), LangError>>()
        .fire();
    
    match swap {
        Err(_) => {
            panic!("Failed call")
        }
        Ok(Err(_)) => {
            panic!("Failed call")
        }
        Ok(Ok(())) => {/*Swap successful*/}
    }
}

Swap PSP22 for PSP22

To swap a PSP22 token for another PSP22 token in the same pool, we can follow these steps:

  • Determine the pair contract address

  • Approve the input PSP22 token

  • Initiate swap

We can determine the pair contract address as we did with the previous example.

We also get the allowance of the callee contract to spend from the caller, offer extra allowance and then approve the PSP22 token for a transfer to be possible on their behalf.

The next step also would be the one to get the estimated amount out and construct the slippage as explained in the introductory section.

We can then initiate the swap in a complete solution by creating a method thus (The ASSOCIATED_SELECTOR variable holds the selector in the case where it is PSP22 A for PSP22 B and vice versa):

fn swap_psp22_for_psp22(&self, psp22_amount:u128) {
    let psp22_amount_out = self.get_psp22_output(psp22_amount); // Method defined in previous section
    let slippage = 100 * 10u128.pow(12); //allow any output to avoid transaction failures
    let old_allowance = self.get_allowance(PSP22_TOKEN, PSP22_PAIR_ADDRESS);
    let new_allowance = allowance + psp22_amount;
    self.approve_tokens(PSP22_TOKEN, PSP22_PAIR_ADDRESS, new_allowance);
    let swap: Result<Result<(), LangError>, Error> = build_call::<DefaultEnvironment>()
        .call_type(
            Call::new().callee(PSP22_PAIR_ADDRESS)
        )
        .exec_input(
            ExecutionInput::new(Selector::new(
                ASSOCIATED SELECTOR
            ))
            .push_arg(psp22_amount)
            .push_arg(psp22_amount_out)
            .push_arg(slippage)
        )
        .call_flags(CallFlags::default().set_allow_reentry(true)) //Ignore this line or set to false if it's not a reentrant call
        .returns::<Result<(), LangError>>()
        .fire();
    
    match swap {
        Err(_) => {
            panic!("Failed call")
        }
        Ok(Err(_)) => {
            panic!("Failed call")
        }
        Ok(Ok(())) => {/*Swap successful*/}
    }
}

With the examples above, one can conduct successful swaps on the AndromedaSwap protocol.

Last updated