# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://andromeda-swap.gitbook.io/andromedaswap-documentation/ink-developers-guide/price-estimation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
