â–Ģī¸Price estimation

To estimate the price (output) of a token in any given pair (AZERO or PSP22) against the other token in that pair, you can follow the steps outlined in this section. It's usually the very first step.

The outputs in this example don't involve fees.

Before we commence the actual implementations, it's important to note that the following methods could come in handy:

  • CASE #1: Getting the address associated with a given AZERO/PSP22 pair

  • CASE #2: Getting the address associated with a given PSP22/PSP22 pair.

To achieve this, we can make cross-contract calls to the router for both cases thus:

Note that, to use the is_zero() trait (to find out if an address is equal to a zero address), you must import the AccountIdExt extension from Openbrush thus:

use openbrush::traits::AccountIdExt;

CASE #1

To achieve this, we can define a method, get_azero_pair_address() that will take the contract address of the PSP22 token and return the contract address of the pool (if found), or zero address. It could be implemented thus:

fn get_azero_pair_address(&self, psp22_token:AccountId) -> AccountId {
    let get_address: Result<Result<AccountId, LangError>, Error> = build_call::<DefaultEnvironment>()
        .call_type(Call::new().callee(ROUTER_ADDRESS))
        .exec_input(
            ExecutionInput::new(Selector::new(
                [0x61, 0x1a, 0x30, 0x52]
            ))
            .push_arg(psp22_token)
        )
        .call_flags(CallFlags::default().set_allow_reentry(true)) //Ignore this line or set to false if it's not a reentrant call
        .returns::<Result<AccountId, LangError>>()
        .fire();
    
    match get_address {
        Err(_) => {
            panic!("Failed call")
        }
        Ok(Err(_)) => {
            panic!("Failed call")
        }
        Ok(Ok(_address)) => return _address
    }
}

CASE #2

To achieve this, we can define a method, get_psp22_pair_address() that will take two arguments: the contract address of both PSP22 tokens; and return the contract address of the pool (if found), or zero address. It could be implemented thus:

fn get_psp22_pair_address(&self, psp22_token_a:AccountId, psp22_token_b:AccountId) -> AccountId {
    let get_address: Result<Result<AccountId, LangError>, Error> = build_call::<DefaultEnvironment>()
        .call_type(Call::new().callee(ROUTER_ADDRESS))
        .exec_input(
            ExecutionInput::new(Selector::new(
                [0xa3, 0xc6, 0x28, 0x62]
            ))
            .push_arg(psp22_token_a)
            .push_arg(psp22_token_b)
        )
        .call_flags(CallFlags::default().set_allow_reentry(true)) //Ignore this line or set to false if it's not a reentrant call
        .returns::<Result<AccountId, LangError>>()
        .fire();
    
    match get_address {
        Err(_) => {
            panic!("Failed call")
        }
        Ok(Err(_)) => {
            panic!("Failed call")
        }
        Ok(Ok(_address)) => return _address
    }
}

The above method results can then be handled as thus (let's focus on CASE #2):

let azero_pair_address = self.get_azero_pair_address(PSP22_TOKEN_ADDRESS);
if azero_pair_address.is_zero() {
    //pool doesn't exist
}
else {
    //pool exists. do your magic...
}

With these in mind, we can go ahead to implement the rest of the examples in this section.

Price estimation for AZERO/PSP22 Pairs

To get the price (estimated amount received in return for the AZERO or PSP22 tokens in the pool as the case may be) in any AZERO/PSP22 pool, there are two approaches:

Getting the estimated amount of AZERO to be received

To get the estimated amount of AZERO that will be received in any AZERO/PSP22 pair, you can write a method like the one below:

fn get_azero_output(&self, psp22_amount:u128) -> u128 {
    let get_amount_out: Result<Result<u128, LangError>, Error> = build_call::<DefaultEnvironment>()
        .call_type(Call::new().callee(AZERO_PAIR_ADDRESS))
        .exec_input(
            ExecutionInput::new(Selector::new(
                [0xbd, 0x77, 0x15, 0xef]
            ))
            .push_arg(psp22_amount)
        )
        .call_flags(CallFlags::default().set_allow_reentry(true)) //Ignore this line or set to false if it's not a reentrant call
        .returns::<Result<u128, LangError>>()
        .fire();
    
    match get_amount_out {
        Err(_) => {
            panic!("Failed call")
        }
        Ok(Err(_)) => {
            panic!("Failed call")
        }
        Ok(Ok(_amount_out)) => return _amount_out
    }
}

Getting the estimated amount of PSP22 tokens to be received

To get the estimated amount of PSP22 tokens that will be received in any AZERO/PSP22 pair, you can write a method like the one below:

fn get_psp22_output(&self, azero_amount:u128) -> u128 {
    let get_amount_out: Result<Result<u128, LangError>, Error> = build_call::<DefaultEnvironment>()
        .call_type(Call::new().callee(AZERO_PAIR_ADDRESS))
        .exec_input(
            ExecutionInput::new(Selector::new(
                [0x42, 0xf5, 0xd9, 0x57]
            ))
            .push_arg(azero_amount)
        )
        .call_flags(CallFlags::default().set_allow_reentry(true)) //Ignore this line or set to false if it's not a reentrant call
        .returns::<Result<u128, LangError>>()
        .fire();
    
    match get_amount_out {
        Err(_) => {
            panic!("Failed call")
        }
        Ok(Err(_)) => {
            panic!("Failed call")
        }
        Ok(Ok(_amount_out)) => return _amount_out
    }
}

Price estimation for PSP22/PSP22 Pairs

To get the price (estimated amount received in return for the PSP22 A or PSP22 B tokens in the pool as the case may be) in any PSP22/PSP22 pool, there are two approaches:

Getting the estimated amount of PSP22 A to be received

To get the estimated amount of PSP22 A tokens that will be received in any PSP22/PSP22 pair, you can write a method like the one below:

fn get_psp22_a_output(&self, psp22_b_amount:u128) -> u128 {
    let get_amount_out: Result<Result<u128, LangError>, Error> = build_call::<DefaultEnvironment>()
        .call_type(Call::new().callee(PSP22_PAIR_ADDRESS))
        .exec_input(
            ExecutionInput::new(Selector::new(
                [0x7d, 0x22, 0x96, 0x8c]
            ))
            .push_arg(psp22_b_amount)
        )
        .call_flags(CallFlags::default().set_allow_reentry(true)) //Ignore this line or set to false if it's not a reentrant call
        .returns::<Result<u128, LangError>>()
        .fire();
    
    match get_amount_out {
        Err(_) => {
            panic!("Failed call")
        }
        Ok(Err(_)) => {
            panic!("Failed call")
        }
        Ok(Ok(_amount_out)) => return _amount_out
    }
}

Getting the estimated amount of PSP22 B to be received

To get the estimated amount of PSP22 B tokens that will be received in any PSP22/PSP22 pair, you can write a method like the one below:

fn get_psp22_a_output(&self, psp22_a_amount:u128) -> u128 {
    let get_amount_out: Result<Result<u128, LangError>, Error> = build_call::<DefaultEnvironment>()
        .call_type(Call::new().callee(PSP22_PAIR_ADDRESS))
        .exec_input(
            ExecutionInput::new(Selector::new(
                [0x71, 0xe9, 0xaf, 0x3a]
            ))
            .push_arg(psp22_a_amount)
        )
        .call_flags(CallFlags::default().set_allow_reentry(true)) //Ignore this line or set to false if it's not a reentrant call
        .returns::<Result<u128, LangError>>()
        .fire();
    
    match get_amount_out {
        Err(_) => {
            panic!("Failed call")
        }
        Ok(Err(_)) => {
            panic!("Failed call")
        }
        Ok(Ok(_amount_out)) => return _amount_out
    }
}

Make sure to closely study and implement this guide as most of the other aspects of this guide will depend on the proper implementation of the aforelisted methods.

Last updated