# Price estimation

> 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:

```rust
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:

```rust
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:

```rust
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):

```rust
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:

```rust
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:

```rust
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:

```rust
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:

```rust
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.
