> For the complete documentation index, see [llms.txt](https://tapp-exchange.gitbook.io/tapp-exchange/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tapp-exchange.gitbook.io/tapp-exchange/developer-docs/sc.md).

# Smart Contract

## Smart Contract

We use a **BCS (Binary Canonical Serialization)** stream to interact with **V2**, **V3**, and **Stable** pool hooks on Aptos. This documentation provides an overview of the serialization and transaction building process using the Aptos SDK in JavaScript/TypeScript.

## 📚 Table of Contents

* [Smart Contract Address](#smart-contract-addresses)
* [Interaction](#interaction)
* [Create Pool](#create-pool)
  * [AMM](#amm)
  * [CLMM](#clmm)
  * [Stable](#stable)
* [Add Liquidity](#add-liquidity)
  * [AMM](#amm-1)
  * [CLMM](#clmm-1)
  * [Stable](#stable-1)
* [Create Pool And Add Liquidity](#create-pool-and-add-liquidity)
  * [AMM](#amm-2)
  * [CLMM](#clmm-2)
  * [Stable](#stable-2)
* [Swap](#swap)
  * [AMM](#amm-3)
  * [CLMM](#clmm-3)
  * [Stable](#stable-3)
* [Remove Liquidity](#remove-liquidity)
  * [AMM](#amm-4)
  * [CLMM](#clmm-4)
  * [Stable](#stable-4)
* [Remove Multi Liquidity](#remove-multi-liquidity)
  * [AMM](#amm-5)
  * [CLMM](#clmm-5)
  * [Stable](#stable-5)
* [Collect Fee](#collect-fee)
  * [CLMM](#clmm-6)
* [Gauge Commit / Uncommit](#gauge-commit--uncommit)
* [Submitting the Transaction](#-submitting-the-transaction)
* [View](#view)
  * [Example Usage](#example-usage)
  * [AMM View API](#amm-view-api)
    * [Reserves & Shares](#-reserves--shares)
    * [Positions](#-positions)
    * [Fees](#-fees)
    * [Liquidity Calculations](#-liquidity-calculations)
    * [Swap Calculations](#-swap-calculations)
  * [CLMM View API](#clmm-view-api)
    * [Pool-Level Views](#pool-level-views)
    * [Position-Level Views](#position-level-views)
    * [Fee Views](#fee-views)
    * [Swap Simulation](#swap-simulation)
    * [Liquidity Calculations](#liquidity-calculations)
  * [Stable View API](#stable-view-api)
* [TAPP View API](#tapp-view-api)
* [veTAPP Smart Contract](#vetapp-smart-contract)
  * [veTAPP Contract Addresses](#vetapp-contract-addresses)
  * [Gauge Operations](#gauge-operations)
    * [`fees_voting_reward::earned`](#fees_voting_rewardearned)
    * [`bribe_voting_reward::earned`](#bribe_voting_rewardearned)
    * [`claim_fees`](#claim_fees)
    * [`claim_bribes`](#claim_bribes)
  * [Lock](#lock)
    * [`create_lock`](#create_lock)
    * [`withdraw`](#withdraw)
    * [`increase_amount`](#increase_amount)
    * [`increase_unlock_time`](#increase_unlock_time)
    * [`merge`](#merge)
    * [`split`](#split)
    * [`create_perm_lock`](#create_perm_lock)
    * [`create_lock_for`](#create_lock_for)
    * [`create_perm_lock_for`](#create_perm_lock_for)
    * [`deposit_for`](#deposit_for)
    * [`lock_permanent`](#lock_permanent)
    * [`unlock_permanent`](#unlock_permanent)
* [Fee Guide](#-fee-guide)

***

## Smart Contract Addresses

Use the following addresses to interact with the smart contract:

| Kind               | Address                                                              |
| ------------------ | -------------------------------------------------------------------- |
| **View Address**   | `0xf5840b576a3a6a42464814bc32ae1160c50456fb885c62be389b817e75b2a385` |
| **Router Address** | `0x487e905f899ccb6d46fdaec56ba1e0c4cf119862a16c409904b8c78fab1f5e8a` |

Use this value when referencing `routerAddress` in your transactions and `viewAddress` in your view.

***

## Interaction

Before interacting with the smart contracts, you must:

* Import required classes such as `Serializer` and `AccountAddress` from the Aptos SDK.
* Initialize a serializer instance before sending any transaction data.
* The transaction examples below are for position v1. Position v2 is an internal flow and is not documented here.

```ts
// Serializer setup
const ser = new Serializer();
```

***

### Create Pool

Function

```ts
router::create_pool
```

#### AMM

#### 📝 Parameters

| Name     | Type              | Description                      | Serialization                                                                                |
| -------- | ----------------- | -------------------------------- | -------------------------------------------------------------------------------------------- |
| poolType | `u8`              | Pool type (2 = V2)               | `ser.serializeU8(2);`                                                                        |
| assets   | `vector<address>` | List of coin types (2 addresses) | `ser.serializeVector([AccountAddress.fromString(coinA), AccountAddress.fromString(coinB)]);` |
| fee      | `u64`             | Fee in basis points (bps)        | <p><code>ser.serializeU64(fee);</code><br>e.g. <code>3000</code> = 0.3%</p>                  |

#### 💡 Example

```ts
ser.serializeU8(2); // V2

ser.serializeVector([
    AccountAddress.fromString(coinA),
    AccountAddress.fromString(coinB),
]);

ser.serializeU64(3000); // Fee = 0.3%
```

***

#### CLMM

#### 📝 Parameters

| Name      | Type              | Description                             | Serialization                                                                                |
| --------- | ----------------- | --------------------------------------- | -------------------------------------------------------------------------------------------- |
| poolType  | `u8`              | Pool type (3 = V3)                      | `ser.serializeU8(3);`                                                                        |
| assets    | `vector<address>` | List of coin types (2 addresses)        | `ser.serializeVector([AccountAddress.fromString(coinA), AccountAddress.fromString(coinB)]);` |
| fee       | `u64`             | Fee in basis points (bps)               | <p><code>ser.serializeU64(fee);</code><br>e.g. <code>3000</code> = 0.3%</p>                  |
| sqrtPrice | `u128`            | Initial square root price for the pool. | `ser.serializeU128(sqrtPrice);`                                                              |

#### 💡 Example

```ts
ser.serializeU8(3); // V3

ser.serializeVector([
    AccountAddress.fromString(coinA),
    AccountAddress.fromString(coinB),
]);

ser.serializeU64(3000); // Fee = 0.3%

// initial square root price.
ser.serializeU128(sqrtPrice);
```

***

#### Stable

#### 📝 Parameters

| Name             | Type              | Description                                               | Serialization                                                                                |
| ---------------- | ----------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| poolType         | `u8`              | Pool type (4 = Stable)                                    | `ser.serializeU8(4);`                                                                        |
| assets           | `vector<address>` | List of coin types (max 4 addresses)                      | `ser.serializeVector([AccountAddress.fromString(coinA), AccountAddress.fromString(coinB)]);` |
| fee              | `u64`             | Fee in basis points (bps)                                 | <p><code>ser.serializeU64(fee);</code><br>e.g. <code>3000</code> = 0.3%</p>                  |
| amp              | `u256`            | Amplification factor. Value must be between 100 and 1000. | `ser.serializeU256(amp);`                                                                    |
| offPegMultiplier | `u256`            | off peg multiplier.                                       | `ser.serializeU256(offpeg_fee_multiplier);`                                                  |

#### 💡 Example

```ts
// pool type
ser.serializeU8(4);

// assets, support up to 4 coins.
ser.serializeVector([AccountAddress.fromString(coinA), AccountAddress.fromString(coinB)]);

// fee 1_000_000 for 0.01%, and 5_000_000 for 0.05%
ser.serializeU64(fee);

// amp. Between 100 to max 1000
ser.serializeU256(amp);

// off peg multiplier
ser.serializeU256(offpeg_fee_multiplier);

```

***

### Add Liquidity

Function

```ts
router::add_liquidity
```

#### AMM

#### 📝 Parameters

| Name         | Type                           | Description                                          | Serialization                                                                             |
| ------------ | ------------------------------ | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| poolId       | `address`                      | Address of the pool                                  | `ser.serialize(AccountAddress.fromString(poolId));`                                       |
| positionAddr | `address` or `Option<address>` | Address of existing position or `None` to create new | `AccountAddress.fromString(positionAddr).serialize(ser);` or `ser.serializeOption(null);` |
| amountA      | `u64`                          | Desired amount of token A                            | `ser.serializeU64(amountA);`                                                              |
| amountB      | `u64`                          | Desired amount of token B                            | `ser.serializeU64(amountB);`                                                              |
| minAmountA   | `u64`                          | Minimum amount of token A (slippage protection)      | `ser.serializeU64(0);`                                                                    |
| minAmountB   | `u64`                          | Minimum amount of token B (slippage protection)      | `ser.serializeU64(0);`                                                                    |

#### 💡 Example

```ts
ser.serialize(AccountAddress.fromString(poolId));

// If creating new position, use:
// ser.serializeOption(null);
AccountAddress.fromString(positionAddr).serialize(ser);

ser.serializeU64(amountA);
ser.serializeU64(amountB);

// Slippage protection set to zero
ser.serializeU64(0);
ser.serializeU64(0);
```

***

#### CLMM

#### 📝 Parameters

| Name         | Type                           | Description                                          | Serialization                                                                             |
| ------------ | ------------------------------ | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| poolId       | `address`                      | Address of the pool                                  | `ser.serialize(AccountAddress.fromString(poolId));`                                       |
| positionAddr | `address` or `Option<address>` | Address of existing position or `None` to create new | `AccountAddress.fromString(positionAddr).serialize(ser);` or `ser.serializeOption(null);` |
| amountA      | `u64`                          | Desired amount of token A                            | `ser.serializeU64(amountA);`                                                              |
| amountB      | `u64`                          | Desired amount of token B                            | `ser.serializeU64(amountB);`                                                              |
| fixedAmountA | `bool`                         | if true then its expect amountA to be fixed.         | `ser.serializeBool(fixed_amount_a);`                                                      |
| lowerTick    | `u64`                          | Lower Tick                                           | `ser.serializeU64(lower_tick);`                                                           |
| upperTick    | `u64`                          | Upper Tick                                           | `ser.serializeU64(upper_tick);`                                                           |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));

// position address. Use ser.serializeOption(null) if the user wants to create a new position.
AccountAddress.fromString(positionAddr).serialize(ser);

// The desired amount of the first token to be added
ser.serializeU64(amountA);

// The desired amount of the second token to be added
ser.serializeU64(amountB);

// fixed_amount_a true if we expect amount_a to be fixed.
ser.serializeBool(fixed_amount_a);

// lower_tick
ser.serializeU64(lower_tick);

// upper_tick
ser.serializeU64(upper_tick);

```

***

#### Stable

#### 📝 Parameters

| Name          | Type                           | Description                                          | Serialization                                                                             |
| ------------- | ------------------------------ | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| poolId        | `address`                      | Address of the pool                                  | `ser.serialize(AccountAddress.fromString(poolId));`                                       |
| positionAddr  | `address` or `Option<address>` | Address of existing position or `None` to create new | `AccountAddress.fromString(positionAddr).serialize(ser);` or `ser.serializeOption(null);` |
| amounts       | `vector<u256>`                 | desired amounts for each coin with maximum 4 coins.  | `ser.serializeVector(amounts.map(amount => new U256(amount)));`                           |
| minMintAmount | `u256`                         | The minimum LP amount                                | `ser.serializeU256(min_mint_amount);`                                                     |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));

// position address. Use ser.serializeOption(null) if the user wants to create a new position.
AccountAddress.fromString(positionAddr).serialize(ser);

// The desired amount for each coin.
ser.serializeVector(amounts.map(amount => new U256(amount)));

// The minimum LP amount
ser.serializeU256(min_mint_amount);


```

***

### Create Pool And Add Liquidity

Function

```ts
router::create_pool_add_liquidity
```

#### AMM

#### 📝 Parameters

| Name         | Type                           | Description                                          | Serialization                                                                                |
| ------------ | ------------------------------ | ---------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| poolType     | `u8`                           | Pool type (2 = V2)                                   | `ser.serializeU8(2);`                                                                        |
| assets       | `vector<address>`              | List of coin address (2 addresses)                   | `ser.serializeVector([AccountAddress.fromString(coinA), AccountAddress.fromString(coinB)]);` |
| fee          | `u64`                          | Fee in basis points (bps)                            | <p><code>ser.serializeU64(fee);</code><br>e.g. <code>3000</code> = 0.3%</p>                  |
| positionAddr | `address` or `Option<address>` | Address of existing position or `None` to create new | `AccountAddress.fromString(positionAddr).serialize(ser);` or `ser.serializeOption(null);`    |
| amountA      | `u64`                          | Desired amount of token A                            | `ser.serializeU64(amountA);`                                                                 |
| amountB      | `u64`                          | Desired amount of token B                            | `ser.serializeU64(amountB);`                                                                 |
| minAmountA   | `u64`                          | Minimum amount of token A (slippage protection)      | `ser.serializeU64(0);`                                                                       |
| minAmountB   | `u64`                          | Minimum amount of token B (slippage protection)      | `ser.serializeU64(0);`                                                                       |

#### 💡 Example

```ts
// pool type
ser.serializeU8(2);

// assets
ser.serializeVector([AccountAddress.fromString(coinA), AccountAddress.fromString(coinB)]);

// fee. 100 for 0.01%, 500 for 0.05%, 3000 for 0.3%, 10000 for 1%.
ser.serializeU64(fee);

// position address. Use ser.serializeOption() if the user wants to create a new position.
AccountAddress.fromString(positionAddr).serialize(ser);

// The desired amount of the first token to be added
ser.serializeU64(amountA);

// The desired amount of the second token to be added
ser.serializeU64(amountB);

// The minimum amount of the first token that must be added
ser.serializeU64(0);

// The minimum amount of the second token that must be added
ser.serializeU64(0);

```

***

#### CLMM

#### 📝 Parameters

| Name         | Type              | Description                                  | Serialization                                                                                |
| ------------ | ----------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------- |
| poolType     | `u8`              | Pool type (3 = V3)                           | `ser.serializeU8(3);`                                                                        |
| assets       | `vector<address>` | List of coin address (2 addresses)           | `ser.serializeVector([AccountAddress.fromString(coinA), AccountAddress.fromString(coinB)]);` |
| fee          | `u64`             | Fee in basis points (bps)                    | <p><code>ser.serializeU64(fee);</code><br>e.g. <code>3000</code> = 0.3%</p>                  |
| sqrtPrice    | `u128`            | Initial square root price for the pool.      | `ser.serializeU128(sqrtPrice);`                                                              |
| amountA      | `u64`             | Desired amount of token A                    | `ser.serializeU64(amountA);`                                                                 |
| amountB      | `u64`             | Desired amount of token B                    | `ser.serializeU64(amountB);`                                                                 |
| fixedAmountA | `bool`            | if true then its expect amountA to be fixed. | `ser.serializeBool(fixed_amount_a);`                                                         |
| lowerTick    | `u64`             | Lower Tick                                   | `ser.serializeU64(lower_tick);`                                                              |
| upperTick    | `u64`             | Upper Tick                                   | `ser.serializeU64(upper_tick);`                                                              |

#### 💡 Example

```ts
// pool type
ser.serializeU8(3);

// assets
ser.serializeVector([AccountAddress.fromString(coinA), AccountAddress.fromString(coinB)]);

// fee. 100 for 0.01%, 500 for 0.05%, 3000 for 0.3%, 10000 for 1%.
ser.serializeU64(fee);

// initial square root price.
ser.serializeU128(sqrtPrice);

// The desired amount of the first token to be added
ser.serializeU64(amountA);

// The desired amount of the second token to be added
ser.serializeU64(amountB);

// fixed_amount_a true if we expect amount_a to be fixed.
ser.serializeBool(fixed_amount_a);

// lower_tick
ser.serializeU64(lower_tick);

// upper_tick
ser.serializeU64(upper_tick);
```

***

#### Stable

#### 📝 Parameters

| Name             | Type              | Description                                               | Serialization                                                                                |
| ---------------- | ----------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| poolType         | `u8`              | Pool type (4 = Stable)                                    | `ser.serializeU8(4);`                                                                        |
| assets           | `vector<address>` | List of coin address (max 4 addresses)                    | `ser.serializeVector([AccountAddress.fromString(coinA), AccountAddress.fromString(coinB)]);` |
| fee              | `u64`             | Fee in basis points (bps)                                 | <p><code>ser.serializeU64(fee);</code><br>e.g. <code>3000</code> = 0.3%</p>                  |
| amp              | `u256`            | Amplification factor. Value must be between 100 and 1000. | `ser.serializeU256(amp);`                                                                    |
| offPegMultiplier | `u256`            | off peg multiplier.                                       | `ser.serializeU256(offpeg_fee_multiplier);`                                                  |
| amounts          | `vector<u256>`    | desired amounts for each coin with maximum 4 coins.       | `ser.serializeVector(amounts.map(amount => new U256(amount)));`                              |
| minMintAmount    | `u256`            | The minimum LP amount                                     | `ser.serializeU256(min_mint_amount);`                                                        |

#### 💡 Example

```ts
// pool type
ser.serializeU8(4);

// assets, support up to 4 coins.
ser.serializeVector([AccountAddress.fromString(coinA), AccountAddress.fromString(coinB)]);

// fee 1_000_000 for 0.01%, and 5_000_000 for 0.05%
ser.serializeU64(fee);

// amp. Between 100 to max 1000
ser.serializeU256(amp);

// off peg multiplier
ser.serializeU256(offpeg_fee_multiplier);

// Initial liquidity for each coins
ser.serializeVector(amounts.map(amount => new U256(amount)));

// minimum LP mint amount
ser.serializeU256(min_mint_amount);
```

***

### Swap

Function

```ts
router::swap
```

#### AMM

#### 📝 Parameters

| Name          | Type      | Description                                                           | Serialization                                       |
| ------------- | --------- | --------------------------------------------------------------------- | --------------------------------------------------- |
| poolId        | `address` | Address of the pool                                                   | `ser.serialize(AccountAddress.fromString(poolId));` |
| aToB          | `bool`    | Set to true when swapping from token0 to token1 in the pool.          | `ser.serializeBool(aToB);`                          |
| fixedAmountIn | `bool`    | Indicates whether the input amount will remain fixed during the swap. | `ser.serializeBool(fixed_amount_in);`               |
| amountIn      | `u64`     | Quantity of input tokens to swap                                      | `ser.serializeU64(amountIn);`                       |
| amountOutMin  | `u64`     | Minimum quantity of output tokens expected from the swap,             | `ser.serializeU64(amountOutMin);`                   |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));

// swap from tokenA to tokenB
ser.serializeBool(aToB);

// fixed_amount_in.
// True = swap_exact_tokens_for_tokens
// False = swap_tokens_for_exact_tokens
ser.serializeBool(fixed_amount_in);


// amount in
ser.serializeU64(amountIn);

// minimum amount out
ser.serializeU64(amountOutMin);
```

***

#### CLMM

#### 📝 Parameters

| Name            | Type      | Description                                                           | Serialization                                       |
| --------------- | --------- | --------------------------------------------------------------------- | --------------------------------------------------- |
| poolId          | `address` | Address of the pool                                                   | `ser.serialize(AccountAddress.fromString(poolId));` |
| aToB            | `bool`    | Set to true when swapping from token0 to token1 in the pool.          | `ser.serializeBool(aToB);`                          |
| fixedAmountIn   | `bool`    | Indicates whether the input amount will remain fixed during the swap. | `ser.serializeBool(fixed_amount_in);`               |
| amountIn        | `u64`     | Quantity of input tokens to swap                                      | `ser.serializeU64(amountIn);`                       |
| amountOutMin    | `u64`     | Minimum quantity of output tokens expected from the swap,             | `ser.serializeU64(amountOutMin);`                   |
| targetSqrtPrice | `u128`    | target square root price after swap.                                  | `ser.serializeU128(target_sqrt_price);`             |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));

// swap from tokenA to tokenB
ser.serializeBool(aToB);

// fixed_amount_in.
ser.serializeBool(fixed_amount_in);

// amount in.
ser.serializeU64(amountIn);

// minimum amount out.
ser.serializeU64(amountOutMin);

// target square root price after swap.
ser.serializeU128(target_sqrt_price);

```

***

#### Stable

#### 📝 Parameters

| Name         | Type      | Description         | Serialization                                       |
| ------------ | --------- | ------------------- | --------------------------------------------------- |
| poolId       | `address` | Address of the pool | `ser.serialize(AccountAddress.fromString(poolId));` |
| tokenIn      | `u64`     | token index in.     | `ser.serializeU64(tokenIn);`                        |
| tokenOut     | `u64`     | token index out.    | `ser.serializeU64(tokenOut);`                       |
| amountIn     | `u256`    | amount in.          | `ser.serializeU256(amountIn);`                      |
| minAmountOut | `u256`    | min amount out,     | `ser.serializeU256(min_amount_out);`                |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));

// i. token index in
ser.serializeU64(tokenIn);

// j. token index out
ser.serializeU64(tokenOut);

// dx. amount in
ser.serializeU256(amountIn);

// min_dy. min amount out
ser.serializeU256(min_amount_out);
```

### Remove Liquidity

Function

```ts
router::remove_liquidity
```

#### AMM

#### 📝 Parameters

| Name         | Type      | Description                                                                     | Serialization                                             |
| ------------ | --------- | ------------------------------------------------------------------------------- | --------------------------------------------------------- |
| poolId       | `address` | Address of the pool                                                             | `ser.serialize(AccountAddress.fromString(poolId));`       |
| positionAddr | `address` | Address of existing position                                                    | `ser.serialize(AccountAddress.fromString(positionAddr));` |
| burnedShares | `u128`    | Amount of liquidity provider (LP) tokens or shares to burn/remove from the pool | `ser.serializeU128(burnedShares);`                        |
| minAmountA   | `u64`     | Minimum token A amounts to receive when removing liquidity.                     | `ser.serializeU64(minAmountA);`                           |
| minAmountB   | `u64`     | Minimum token B amounts to receive when removing liquidity.                     | `ser.serializeU64(minAmountB);`                           |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));

// position address
ser.serialize(AccountAddress.fromString(positionAddr));

// burned share
ser.serializeU128(burnedShares);

// min_amount_a
ser.serializeU64(minAmountA);

// min_amount_b
ser.serializeU64(minAmountB);
```

***

#### CLMM

#### 📝 Parameters

| Name         | Type      | Description                                                                     | Serialization                                             |
| ------------ | --------- | ------------------------------------------------------------------------------- | --------------------------------------------------------- |
| poolId       | `address` | Address of the pool                                                             | `ser.serialize(AccountAddress.fromString(poolId));`       |
| positionAddr | `address` | Address of existing position                                                    | `ser.serialize(AccountAddress.fromString(positionAddr));` |
| burnedShares | `u128`    | Amount of liquidity provider (LP) tokens or shares to burn/remove from the pool | `ser.serializeU128(burnedShares);`                        |
| minAmountA   | `u64`     | Minimum token A amounts to receive when removing liquidity.                     | `ser.serializeU64(minAmountA);`                           |
| minAmountB   | `u64`     | Minimum token B amounts to receive when removing liquidity.                     | `ser.serializeU64(minAmountB);`                           |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));

// position address
ser.serialize(AccountAddress.fromString(positionAddr));

// burned share
ser.serializeU128(burnedShares);

// min_amount_a
ser.serializeU64(minAmountA);

// min_amount_b
ser.serializeU64(minAmountB);
```

***

#### Stable

#### 📝 Parameters

| Name         | Type           | Description                                                                               | Serialization                                                   |
| ------------ | -------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| poolId       | `address`      | Address of the pool                                                                       | `ser.serialize(AccountAddress.fromString(poolId));`             |
| positionAddr | `address`      | Address of existing position                                                              | `ser.serialize(AccountAddress.fromString(positionAddr));`       |
| Type         | `u8`           | 1 : remove liquidity one coin, 2 : remove liquidity imbalance, 3 : remove liquidity ratio | `ser.serializeU8(3)`                                            |
| burnedShare  | `u256`         | Amount of liquidity provider (LP) tokens or shares to burn/remove from the pool           | `ser.serializeU256(shares);`                                    |
| minAmounts   | `vector<u256>` | Minimum token amounts to receive when removing liquidity.                                 | `ser.serializeVector(amounts.map(amount => new U256(amount)));` |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));

// position address
ser.serialize(AccountAddress.fromString(positionAddr));

// type 1 = remove_liquidity_one_coin
// type 2 =remove_liquidity_imbalance
// type 3 = remove_liquidity_ratio
ser.serializeU8(3)

// burn amount
ser.serializeU256(shares);

// minimum received for each token
ser.serializeVector(amounts.map(amount => new U256(amount)));
```

***

### Remove Multi Liquidity

Function

```ts
router::remove_multi_liquidity
```

#### AMM

#### 📝 Parameters

| Name                      | Type      | Description                                                                     | Serialization                                                      |
| ------------------------- | --------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| poolId                    | `address` | Address of the pool                                                             | `ser.serialize(AccountAddress.fromString(poolId));`                |
| positions.length          | `u64`     | Total number of positions                                                       | `ser.serializeU64(positions.length);`                              |
| positions.positionAddress | `address` | Address of existing position                                                    | `ser.serialize(AccountAddress.fromString(position.positionAddr));` |
| positions.burnedShares    | `u128`    | Amount of liquidity provider (LP) tokens or shares to burn/remove from the pool | `ser.serializeU128(position.burnedShares);`                        |
| positions.minAmountA      | `u64`     | Minimum token A amounts to receive when removing liquidity.                     | `ser.serializeU64(position.minAmountA);`                           |
| positions.minAmountB      | `u64`     | Minimum token B amounts to receive when removing liquidity.                     | `ser.serializeU64(position.minAmountB);`                           |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));
// number of positions
ser.serializeU64(positions.length);

positions.forEach((position) => {
    // position address
    ser.serialize(AccountAddress.fromString(position.positionAddr));

    // burned_shares
    ser.serializeU128(position.burnedShares);

    // min_amount_a
    ser.serializeU64(position.minAmountA);

    // min_amount_b
    ser.serializeU64(position.minAmountB);
})
```

***

#### CLMM

#### 📝 Parameters

| Name                      | Type      | Description                                                                     | Serialization                                                      |
| ------------------------- | --------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| poolId                    | `address` | Address of the pool                                                             | `ser.serialize(AccountAddress.fromString(poolId));`                |
| positions.length          | `u64`     | Total number of positions                                                       | `ser.serializeU64(positions.length);`                              |
| positions.positionAddress | `address` | Address of existing position                                                    | `ser.serialize(AccountAddress.fromString(position.positionAddr));` |
| positions.burnedShares    | `u128`    | Amount of liquidity provider (LP) tokens or shares to burn/remove from the pool | `ser.serializeU128(position.burnedShares);`                        |
| positions.minAmountA      | `u64`     | Minimum token A amounts to receive when removing liquidity.                     | `ser.serializeU64(position.minAmountA);`                           |
| positions.minAmountB      | `u64`     | Minimum token B amounts to receive when removing liquidity.                     | `ser.serializeU64(position.minAmountB);`                           |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));
// number of positions
ser.serializeU64(positions.length);

positions.forEach((position) => {
    // position address
    ser.serialize(AccountAddress.fromString(position.positionAddr));

    // burned_shares
    ser.serializeU128(position.burnedShares);

    // min_amount_a
    ser.serializeU64(position.minAmountA);

    // min_amount_b
    ser.serializeU64(position.minAmountB);
})
```

***

#### Stable

#### 📝 Parameters

| Name                   | Type           | Description                                                                               | Serialization                                                               |
| ---------------------- | -------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| poolId                 | `address`      | Address of the pool                                                                       | `ser.serialize(AccountAddress.fromString(poolId));`                         |
| positions.length       | `u64`          | Total number of positions                                                                 | `ser.serializeU64(positions.length);`                                       |
| positions.positionAddr | `address`      | Address of existing position                                                              | `ser.serialize(AccountAddress.fromString(position.positionAddr))`           |
| positions.type         | `u8`           | 1 : remove liquidity one coin, 2 : remove liquidity imbalance, 3 : remove liquidity ratio | `ser.serializeU8(position.type);`                                           |
| positions.burnedShare  | `u256`         | Amount of liquidity provider (LP) tokens or shares to burn/remove from the pool           | `ser.serializeU128(position.burnedShare);`                                  |
| positions.minAmounts   | `vector<u256>` | Minimum token amounts to receive when removing liquidity.                                 | `ser.serializeVector(position.minAmounts.map(amount => new U256(amount)));` |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));
// number of positions
ser.serializeU64(positions.length);

positions.forEach(position => {
    // position address
    ser.serialize(AccountAddress.fromString(position.positionAddr));

    // type 1 = remove_liquidity_one_coin
    // type 2 =remove_liquidity_imbalance
    // type 3 = remove_liquidity_ratio
    ser.serializeU8(position.type);

    // burned_shares
    ser.serializeU256(position.burnedShare);

    // minimum received for each token
    ser.serializeVector(position.minAmounts.map(amount => new U256(amount)));
})

```

***

### Collect Fee

Function

```ts
router::collect_fee
```

#### CLMM

#### 📝 Parameters

| Name            | Type      | Description                  | Serialization                                                |
| --------------- | --------- | ---------------------------- | ------------------------------------------------------------ |
| poolId          | `address` | Address of the pool          | `ser.serialize(AccountAddress.fromString(poolId));`          |
| positionAddress | `address` | Address of existing position | `AccountAddress.fromString(positionAddress).serialize(ser);` |

#### 💡 Example

```ts
// pool id
ser.serialize(AccountAddress.fromString(poolId));

// position address
AccountAddress.fromString(positionAddress).serialize(ser);
```

### Gauge Commit / Uncommit

These are direct entry functions in `tapp::ve`, not BCS-packed router payloads. `gauge_commit` claims any owed fees before committing the position, and `gauge_uncommit` claims any owed gauge rewards before releasing it.

#### Gauge Commit

Function

```ts
tapp::ve::gauge_commit
```

#### 📝 Parameters

| Name         | Type          | Description                                                         |
| ------------ | ------------- | ------------------------------------------------------------------- |
| poolAddr     | `address`     | Address of the pool                                                 |
| positionAddr | `address`     | Address of the position to commit                                   |
| positionIdx  | `Option<u64>` | Position index for position v2. Use `none()` for position v1 flows. |

#### 💡 Example

```ts
// position v1
await aptos.transaction.build.simple({
    sender: account.accountAddress,
    data: {
        function: `${tappAddress}::ve::gauge_commit`,
        functionArguments: [poolAddr, positionAddr, null],
    },
});
```

#### Gauge Uncommit

Function

```ts
tapp::ve::gauge_uncommit
```

#### 📝 Parameters

| Name         | Type          | Description                                                         |
| ------------ | ------------- | ------------------------------------------------------------------- |
| poolAddr     | `address`     | Address of the pool                                                 |
| positionAddr | `address`     | Address of the position to uncommit                                 |
| positionIdx  | `Option<u64>` | Position index for position v2. Use `none()` for position v1 flows. |

#### 💡 Example

```ts
// position v1
await aptos.transaction.build.simple({
    sender: account.accountAddress,
    data: {
        function: `${tappAddress}::ve::gauge_uncommit`,
        functionArguments: [poolAddr, positionAddr, null],
    },
});
```

### 🚀 Submitting the Transaction

Once all arguments are serialized, submit the transaction using the Aptos SDK:

```ts
const transaction = await aptos.transaction.build.simple({
    sender: account.accountAddress,
    data: {
        function: `${routerAddress}::${functionName}`,
        functionArguments: [ser.toUint8Array()],
    },
});
```

***

## View

This documentation provides read-only access to key on-chain data across multiple pool types, including pool state, user positions, and swap simulations. It is intended for developers and integrators to support analytics, UI rendering, and off-chain logic without modifying blockchain state.

### Example Usage

To interact with the View API, you can use the `views` module provided by the `aptos` framework. This module contains read-only functions that allow you to query various aspects of the AMM, CLMM, and Stable pools without modifying the on-chain state.

**Example usage in JavaScript:**

```javascript

async function getPoolReserves(poolAddress) {
    const reservesA = await aptos.view({
        function: `${viewAddress}::amm_views::reserve_a`,
        type_arguments: [],
        arguments: [poolAddress],
    });

    const reservesB = await aptos.view({
        function: `${viewAddress}::amm_views::reserve_b`,
        type_arguments: [],
        arguments: [poolAddress],
    });

    return {reservesA, reservesB};
}
```

***

### AMM View API

The `views::amm_views` module provides a collection of read-only view functions designed to interact with and retrieve information from AMM (Automated Market Maker) pools. These functions are useful for frontend queries and off-chain data display.

***

#### 📊 Reserves & Shares

**Function `reserve_a(pool_addr: address): u64`**

Returns the reserve amount of token A in the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const reservesA = await aptos.view({
    function: `${viewAddress}::amm_views::reserve_a`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `reserve_b(pool_addr: address): u64`**

Returns the reserve amount of token B in the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const reservesB = await aptos.view({
    function: `${viewAddress}::amm_views::reserve_b`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `total_shares(pool_addr: address): u128`**

Returns the total number of LP shares for the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const totalShares = await aptos.view({
    function: `${viewAddress}::amm_views::total_shares`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

#### 🧾 Positions

**Function `get_positions(pool_addr: address): vector<amm::amm::Position>`**

Returns all positions in a given pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const positions = await aptos.view({
    function: `${viewAddress}::amm_views::get_positions`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `get_position(pool_addr: address, position_idx: u64): amm::amm::Position`**

Returns the position information for a specific index.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `position_idx`: `u64` – Index of the position within the pool.

**💡 Example**

```javascript
const position = await aptos.view({
    function: `${viewAddress}::amm_views::get_position`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex],
});
```

***

**Function `position_shares(pool_addr: address, position_idx: u64): u128`**

Returns the number of shares owned by the position.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `position_idx`: `u64` – Index of the position within the pool.

**💡 Example**

```javascript
const shares = await aptos.view({
    function: `${viewAddress}::amm_views::position_shares`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex],
});
```

***

#### 💸 Fees

**Function `fee_rate(pool_addr: address): u64`**

Returns the fee rate for the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const feeRate = await aptos.view({
    function: `${viewAddress}::amm_views::fee_rate`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `fee_rate_denominator(): u64`**

Returns the denominator used to calculate the fee percentage.

**💡 Example**

```javascript
const denominator = await aptos.view({
    function: `${viewAddress}::amm_views::fee_rate_denominator`,
    type_arguments: [],
    arguments: [],
});
```

***

#### ➕ Liquidity Calculations

**Function**

`calc_optimal_lp_amount(desired_amount_a: u64, desired_amount_b: u64, min_amount_a: u64, min_amount_b: u64)`

Calculates optimal token amounts to add liquidity while maintaining ratio.

**Params**

* `desired_amount_a`: u64
* `desired_amount_b`: u64
* `min_amount_a`: u64
* `min_amount_b`: u64

**💡 Example**

```javascript
const optimalAmounts = await aptos.view({
    function: `${viewAddress}::amm_views::calc_optimal_lp_amount`,
    type_arguments: [],
    arguments: [desiredAmountA, desiredAmountB, minAmountA, minAmountB],
});
```

***

**Function `compute_lp_from_shares(pool_addr: address, shares: u128): (u64, u64)`**

Calculates the equivalent amounts of token A and B from given LP shares.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `shares`: `u128` – Number of LP shares to convert.

**💡 Example**

```javascript
const amounts = await aptos.view({
    function: `${viewAddress}::amm_views::compute_lp_from_shares`,
    type_arguments: [],
    arguments: [poolAddress, shares],
});
```

***

#### 🔁 Swap Calculations

**Function `compute_amount_out(pool_addr: address, amount_in: u64, a2b: bool): u64`**

Returns the estimated output token amount for a given input and direction.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `amount_in`: `u64` – Amount of input token.
* `a2b`: `bool` – Direction of swap (`true`: A to B, `false`: B to A).

**💡 Example**

```javascript
const amountOut = await aptos.view({
    function: `${viewAddress}::amm_views::compute_amount_out`,
    type_arguments: [],
    arguments: [poolAddress, amountIn, true],
});
```

***

**Function `compute_amount_in(pool_addr: address, amount_out: u64, a2b: bool): u64`**

Returns the required input token amount to receive a specific output.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `amount_out`: `u64` – Desired output token amount.
* `a2b`: `bool` – Direction of swap (`true`: A to B, `false`: B to A).

**💡 Example**

```javascript
const amountIn = await aptos.view({
    function: `${viewAddress}::amm_views::compute_amount_in`,
    type_arguments: [],
    arguments: [poolAddress, amountOut, true],
});
```

***

### CLMM View API

This module contains **read-only view functions** for accessing the on-chain state of CLMM (Concentrated Liquidity Market Maker) pools and positions. All methods are non-mutating and safe to call for off-chain querying.

***

#### Pool-Level Views

**Function `current_sqrt_price(pool_addr: address): u128`**

Returns the current square root price of the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const sqrtPrice = await aptos.view({
    function: `${viewAddress}::clmm_views::current_sqrt_price`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `reserve_a(pool_addr: address): u64`**

Returns the current reserve amount of token A in the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const reserveA = await aptos.view({
    function: `${viewAddress}::clmm_views::reserve_a`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `reserve_b(pool_addr: address): u64`**

Returns the current reserve amount of token B in the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const reserveB = await aptos.view({
    function: `${viewAddress}::clmm_views::reserve_b`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `liquidity(pool_addr: address): u128`**

Returns the total liquidity currently in the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const liquidity = await aptos.view({
    function: `${viewAddress}::clmm_views::liquidity`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `current_tick_idx(pool_addr: address): u64`**

Returns the current tick index for the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const tickIndex = await aptos.view({
    function: `${viewAddress}::clmm_views::current_tick_idx`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

#### Position-Level Views

**Function `get_positions(pool_addr: address): vector<clmm::clmm::Position>`**

Fetches all position objects within the specified pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const positions = await aptos.view({
    function: `${viewAddress}::clmm_views::get_positions`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `get_position(pool_addr: address, position_idx: u64): clmm::clmm::Position`**

Fetches a specific position by index from the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `position_idx`: `u64` – Index of the position within the pool.

**💡 Example**

```javascript
const position = await aptos.view({
    function: `${viewAddress}::clmm_views::get_position`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex],
});
```

***

**Function `position_liquidity(pool_addr: address, position_idx: u64): u128`**

Returns the amount of liquidity in a specific position.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `position_idx`: `u64` – Position index.

**💡 Example**

```javascript
const liquidity = await aptos.view({
    function: `${viewAddress}::clmm_views::position_liquidity`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex],
});
```

***

**Function `position_tick_idxs(pool_addr: address, position_idx: u64): (u64, u64)`**

Returns the tick lower and upper indices for a position.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `position_idx`: `u64` – Position index.

**💡 Example**

```javascript
const tickIdxs = await aptos.view({
    function: `${viewAddress}::clmm_views::position_tick_idxs`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex],
});
```

***

**Function `position_fee_growth_inside(pool_addr: address, position_idx: u64): (u128, u128)`**

Returns the fee growth inside the tick range of a position.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `position_idx`: `u64` – Position index.

**💡 Example**

```javascript
const feeGrowth = await aptos.view({
    function: `${viewAddress}::clmm_views::position_fee_growth_inside`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex],
});
```

***

**Function `position_fee_owed(pool_addr: address, position_idx: u64): (u64, u64)`**

Returns the amount of fees owed to a position.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `position_idx`: `u64` – Position index.

**💡 Example**

```javascript
const feesOwed = await aptos.view({
    function: `${viewAddress}::clmm_views::position_fee_owed`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex],
});
```

***

#### Fee Views

**Function `fee_rate(pool_addr: address): u64`**

Returns the fee rate of the pool.

**Params**

* `pool_addr`: `address` – Pool unique identifier.

**💡 Example**

```javascript
const feeRate = await aptos.view({
    function: `${viewAddress}::clmm_views::fee_rate`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `fee_denominator(): u64`**

Returns the fixed denominator used in fee calculation.

**💡 Example**

```javascript
const denominator = await aptos.view({
    function: `${viewAddress}::clmm_views::fee_denominator`,
    type_arguments: [],
    arguments: [],
});
```

***

#### Swap Simulation

**Function**

`calculate_swap_result(pool_addr: address, a2b: bool, fixed_amount_in: bool, amount: u64): clmm::clmm::CalculatedSwapResult`

Simulates a swap and returns the expected result.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `a2b`: `bool` – Direction of the swap (`true`: A to B, `false`: B to A).
* `fixed_amount_in`: `bool` – Whether the input amount is fixed.
* `amount`: `u64` – The amount to swap.

**💡 Example**

```javascript
const swapResult = await aptos.view({
    function: `${viewAddress}::clmm_views::calculate_swap_result`,
    type_arguments: [],
    arguments: [poolAddress, true, true, amount],
});
```

***

#### Liquidity Calculations

**Function `get_amount_by_liquidity(...): (u64, u64)`**

Returns the token amounts (A, B) corresponding to a given liquidity amount.

**Params**

* `tick_lower_index`: `u64` – Lower bound of tick range.
* `tick_upper_index`: `u64` – Upper bound of tick range.
* `current_tick_index`: `u64` – Current tick index.
* `current_sqrt_price`: `u128` – Current square root price.
* `liquidity`: `u128` – Amount of liquidity.
* `round_up`: `bool` – Whether to round up in calculation.

**💡 Example**

```javascript
const amounts = await aptos.view({
    function: `${viewAddress}::clmm_views::get_amount_by_liquidity`,
    type_arguments: [],
    arguments: [tickLowerIndex, tickUpperIndex, currentTickIndex, currentSqrtPrice, liquidity, true],
});
```

***

**Function**

`get_amount_by_liquidity_of(pool_addr: address, position_idx: u64, liquidity: u128, round_up: bool): (u64, u64)`

Returns the token amounts (A, B) corresponding to a given liquidity amount in a specific position.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `position_idx`: `u64` – Index of the position.
* `liquidity`: `u128` – Amount of liquidity.
* `round_up`: `bool` – Whether to round up in calculation.

**💡 Example**

```javascript
const amounts = await aptos.view({
    function: `${viewAddress}::clmm_views::get_amount_by_liquidity_of`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex, liquidity, true],
});
```

***

**Function `get_liquidity_by_amount(...): (u128, u64, u64)`**

Returns the liquidity and actual token amounts (A, B) that can be provided with a given token amount.

**Params**

* `tick_lower_index`: `u64` – Lower tick index.
* `tick_upper_index`: `u64` – Upper tick index.
* `current_tick_index`: `u64` – Current tick index.
* `current_sqrt_price`: `u128` – Current square root price.
* `amount`: `u64` – The fixed token amount.
* `is_fixed_a`: `bool` – Whether the fixed amount is token A.

**💡 Example**

```javascript
const liquidity = await aptos.view({
    function: `${viewAddress}::clmm_views::get_liquidity_by_amount`,
    type_arguments: [],
    arguments: [tickLowerIndex, tickUpperIndex, currentTickIndex, currentSqrtPrice, amount, true],
});
```

***

**Function**

`get_liquidity_by_amount_of(pool_addr: address, tick_lower_index: u64, tick_upper_index: u64, amount: u64, is_fixed_a: bool): (u128, u64, u64)`

Returns the liquidity and actual token amounts (A, B) that can be provided with a given token amount in a specific position.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `tick_lower_index`: `u64` – Lower tick index.
* `tick_upper_index`: `u64` – Upper tick index.
* `amount`: `u64` – The fixed token amount.
* `is_fixed_a`: `bool` – Whether the fixed amount is token A.

**💡 Example**

```javascript
const liquidity = await aptos.view({
    function: `${viewAddress}::clmm_views::get_liquidity_by_amount_of`,
    type_arguments: [],
    arguments: [poolAddress, tickLowerIndex, tickUpperIndex, amount, true],
});
```

***

**Function `get_position_fee_owned(pool_addr: address, position_idx: u64): (u128, u64, u64)`**

Returns the total fees owed to a position, including fee growth and amounts.

**Params**

* `pool_addr`: `address` – Pool unique identifier.
* `position_idx`: `u64` – Index of the position.

**💡 Example**

```javascript
const feesOwed = await aptos.view({
    function: `${viewAddress}::clmm_views::get_position_fee_owned`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex],
});
```

***

### Stable View API

This module provides read-only view functions for accessing on-chain data related to Stable Pools. It allows querying pool state, user positions, and swap simulations without modifying blockchain state.

***

**Function `n_coins(pool_addr: address): u64`**

returns the number of coins in the pool.

**Params**

* `pool_addr`: `address` – The address of the pool.

**💡 Example**

```javascript
const coinCount = await aptos.view({
    function: `${viewAddress}::stable_views::n_coins`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `rate_multipliers(pool_addr: address): vector<u256>`**

returns the rate multipliers for each coin in the pool.

**Params**

* `pool_addr`: `address` – The address of the pool.

**💡 Example**

```javascript
const rateMultipliers = await aptos.view({
    function: `${viewAddress}::stable_views::rate_multipliers`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `stored_balances(pool_addr: address): vector<u256>`**

returns the stored balances of each coin in the pool.

**Params**

* `pool_addr`: `address` – The address of the pool.

**💡 Example**

```javascript
const balances = await aptos.view({
    function: `${viewAddress}::stable_views::stored_balances`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `initial_a(pool_addr: address): u256`**

returns the initial amplification coefficient (A) of the pool.

**Params**

* `pool_addr`: `address` – The address of the pool.

**💡 Example**

```javascript
const initialA = await aptos.view({
    function: `${viewAddress}::stable_views::initial_a`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `future_a(pool_addr: address): u256`**

returns the future amplification coefficient (A) of the pool.

**Params**

* `pool_addr`: `address` – The address of the pool.

**💡 Example**

```javascript
const futureA = await aptos.view({
    function: `${viewAddress}::stable_views::future_a`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `initial_a_time(pool_addr: address): u64`**

returns the timestamp when the initial amplification coefficient (A) was set.

**Params**

* `pool_addr`: `address` – The address of the pool.

**💡 Example**

```javascript
const initialATime = await aptos.view({
    function: `${viewAddress}::stable_views::initial_a_time`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `future_a_time(pool_addr: address): u64`**

returns the timestamp when the future amplification coefficient (A) will be set.

**Params**

* `pool_addr`: `address` – The address of the pool.

**💡 Example**

```javascript
const futureATime = await aptos.view({
    function: `${viewAddress}::stable_views::future_a_time`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `total_shares(pool_addr: address): u256`**

returns the total number of LP shares for the pool.

**Params**

* `pool_addr`: `address` – The address of the pool.

**💡 Example**

```javascript
const totalShares = await aptos.view({
    function: `${viewAddress}::stable_views::total_shares`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `fee_rate(pool_addr: address): u256`**

returns the fee rate for the pool.

**Params**

* `pool_addr`: `address` – The address of the pool.

**💡 Example**

```javascript
const feeRate = await aptos.view({
    function: `${viewAddress}::stable_views::fee_rate`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `fee_denominator(): u256`**

returns the denominator used to calculate the fee percentage.

**💡 Example**

```javascript
const denominator = await aptos.view({
    function: `${viewAddress}::stable_views::fee_denominator`,
    type_arguments: [],
    arguments: [],
});
```

***

**Function `dynamic_fee(pool_addr: address, i: u64, j: u64): u256`**

returns the dynamic fee rate for a specific coin pair in the pool.

**Params**

* `pool_addr`: `address` – The address of the pool.
* `i`: `u64` – The index of the first coin.
* `j`: `u64` – The index of the second coin.

**💡 Example**

```javascript
const dynamicFee = await aptos.view({
    function: `${viewAddress}::stable_views::dynamic_fee`,
    type_arguments: [],
    arguments: [poolAddress, i, j],
});
```

***

**Function `get_positions(pool_addr: address): vector<stable::stable::Position>`**

returns all positions in a given pool.

**Params**

* `pool_addr`: `address` – The address of the pool.

**💡 Example**

```javascript
const positions = await aptos.view({
    function: `${viewAddress}::stable_views::get_positions`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `get_position(pool_addr: address, position_idx: u64): stable::stable::Position`**

returns the position information for a specific index.

**Params**

* `pool_addr`: `address` – The address of the pool.
* `position_idx`: `u64` – The index of the position within the pool.

**💡 Example**

```javascript
const position = await aptos.view({
    function: `${viewAddress}::stable_views::get_position`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex],
});
```

***

**Function `position_shares(pool_addr: address, position_idx: u64): u256`**

returns the number of shares owned by the position.

**Params**

* `pool_addr`: `address` – The address of the pool.
* `position_idx`: `u64` – The index of the position within the pool.

**💡 Example**

```javascript
const shares = await aptos.view({
    function: `${viewAddress}::stable_views::position_shares`,
    type_arguments: [],
    arguments: [poolAddress, positionIndex],
});
```

***

**Function `get_dx(pool_addr: address, i: u64, j: u64, dy: u256): u256`**

this function calculates the required input amount (dx) for a given output amount (dy) in a specific coin pair.

**Params**

* `pool_addr`: `address` – The address of the pool.
* `i`: `u64` – The index of the first coin.
* `j`: `u64` – The index of the second coin.
* `dy`: `u256` – The output amount for the second coin.

**💡 Example**

```javascript
const dx = await aptos.view({
    function: `${viewAddress}::stable_views::get_dx`,
    type_arguments: [],
    arguments: [poolAddress, i, j, dy],
});
```

***

**Function `get_dy(pool_addr: address, i: u64, j: u64, dx: u256): u256`**

this function calculates the output amount (dy) for a given input amount (dx) in a specific coin pair.

**Params**

* `pool_addr`: `address` – The address of the pool.
* `i`: `u64` – The index of the first coin.
* `j`: `u64` – The index of the second coin.
* `dx`: `u256` – The input amount for the first coin.

**💡 Example**

```javascript
const dy = await aptos.view({
    function: `${viewAddress}::stable_views::get_dy`,
    type_arguments: [],
    arguments: [poolAddress, i, j, dx],
});
```

***

**Function `calc_token_amount(pool_addr: address, amounts: vector<u256>, is_deposit: bool): u256`**

this function calculates the amount of LP shares to mint or burn based on the provided token amounts.

**Params**

* `pool_addr`: `address` – The address of the pool.
* `amounts`: `vector<u256>` – The amounts of each coin to deposit or withdraw.
* `is_deposit`: `bool` – Whether the operation is a deposit (`true`) or withdrawal (`false`).

**💡 Example**

```javascript
const lpAmount = await aptos.view({
    function: `${viewAddress}::stable_views::calc_token_amount`,
    type_arguments: [],
    arguments: [poolAddress, amounts, true],
});
```

***

**Function `calc_withdraw_one_coin(pool_addr: address, burn_amount: u256, i: u64): u256`**

this function calculates the amount of a specific coin to withdraw when burning LP shares.

**Params**

* `pool_addr`: `address` – The address of the pool.
* `burn_amount`: `u256` – The amount of LP shares to burn.
* `i`: `u64` – The index of the coin to withdraw.

**💡 Example**

```javascript
const amount = await aptos.view({
    function: `${viewAddress}::stable_views::calc_withdraw_one_coin`,
    type_arguments: [],
    arguments: [poolAddress, burnAmount, i],
});
```

***

**Function `calc_ratio_amounts(pool_addr: address, liquidity: u256): vector<u256>`**

this function calculates the amounts of each coin based on a given liquidity ratio.

**Params**

* `pool_addr`: `address` – The address of the pool.
* `liquidity`: `u256` – The liquidity ratio to use for the calculation.

**💡 Example**

```javascript
const amounts = await aptos.view({
    function: `${viewAddress}::stable_views::calc_ratio_amounts`,
    type_arguments: [],
    arguments: [poolAddress, liquidity],
});
```

### TAPP View API

This documentation provides read-only access to on-chain data for TAPP protocol integrations, including pool metadata, position details, and calculated incentives. These functions help developers query reward information and render pool/position data in applications without requiring transactions.

***

**Function `get_pool_metas(): vector<tapp::hook_factory::PoolMeta>`**

Returns metadata for all TAPP pools.

**Params**

* *(no parameters)*

**💡 Example**

```javascript
const poolMetas = await aptos.view({
    function: `${viewAddress}::tapp_views::get_pool_metas`,
    type_arguments: [],
    arguments: [],
});
```

***

**Function `get_pool_meta(pool_addr: address): tapp::hook_factory::PoolMeta`**

Returns metadata for a specific TAPP pool.

**Params**

* `pool_addr`: `address` – The address of the TAPP pool.

**💡 Example**

```javascript
const poolMeta = await aptos.view({
    function: `${viewAddress}::tapp_views::get_pool_meta`,
    type_arguments: [],
    arguments: [poolAddress],
});
```

***

**Function `get_position_meta(position_addr: address): tapp::position::PositionMeta`**

Returns metadata for a specific TAPP position.

**Params**

* `position_addr`: `address` – The address of the TAPP position.

**💡 Example**

```javascript
const positionMeta = await aptos.view({
    function: `${viewAddress}::tapp_views::get_position_meta`,
    type_arguments: [],
    arguments: [positionAddress],
});
```

***

**Function**

`calc_incentives(user_address: address, pool_addr: address, position_idx: u64): vector<tapp::hook_factory::IncentiveReward>`

Calculates incentives for a specific user position in a TAPP pool.

**Params**

* `user_address`: `address` – The address of the user.
* `pool_addr`: `address` – The address of the TAPP pool.
* `position_idx`: `u64` – The index of the position within the pool.

**💡 Example**

```javascript
const incentives = await aptos.view({
    function: `${viewAddress}::tapp_views::calc_incentives`,
    type_arguments: [],
    arguments: [userAddress, poolAddress, positionIndex],
});
```

***

**Function**

`calc_incentives_batch(user_address: address, pool_addrs: vector<address>, position_indices: vector<u64>): vector<vector<tapp::hook_factory::IncentiveReward>>`

Calculates incentives for multiple user positions across multiple TAPP pools in a single call. This is more efficient than calling `calc_incentives` individually for each position.

**Params**

* `user_address`: `address` – The address of the user.
* `pool_addrs`: `vector<address>` – A vector of TAPP pool addresses.
* `position_indices`: `vector<u64>` – A vector of position indices corresponding to each pool address.

**💡 Example**

```javascript
const incentives = await aptos.view({
    function: `${viewAddress}::tapp_views::calc_incentives_batch`,
    type_arguments: [],
    arguments: [userAddress, poolAddresses, positionIndices],
});
```

***

### veTAPP Smart Contract

The `veTAPP` (Voting Escrow TAP) contract manages the locking of `TAPP` tokens into veNFTs. These NFTs represent voting power and entitle owners to rewards and governance participation.

#### veTAPP Contract Addresses

| Kind               | Address                                                              |
| ------------------ | -------------------------------------------------------------------- |
| **veTAPP Address** | `0xb0745cc707507e46f7c7510b3cbf0c782dd61530b2135e8ceba7efe39bac861f` |

***

#### Gauge Operations

These helpers belong to the veTAPP flow and interact with gauge rewards and voter emissions. The user-facing claim entrypoints live in `ve_tapp::voter` from `packages/ve_tapp/sources/protocol/voter.move`. They call into `tapp::ve`, which then forwards to the gauge package for reward accounting.

**`fees_voting_reward::earned`**

Returns the fee reward amount earned by a veTAPP NFT for a specific pool fee token.

**Parameters:**

* `pool`: `address` - Pool address.
* `ve_token_addr`: `address` - veTAPP NFT address.
* `fee_token_addr`: `address` - Fee token address.

**View Function:**

```ts
gauge::fees_voting_reward::earned(pool, ve_token_addr, fee_token_addr)
```

***

**`bribe_voting_reward::earned`**

Returns the bribe reward amount earned by a veTAPP NFT for a specific pool bribe token.

**Parameters:**

* `pool`: `address` - Pool address.
* `ve_token_addr`: `address` - veTAPP NFT address.
* `bribe_token_addr`: `address` - Bribe token address.

**View Function:**

```ts
gauge::bribe_voting_reward::earned(pool, ve_token_addr, bribe_token_addr)
```

***

**`claim_fees`**

Claims fee rewards for one or more pools on behalf of the veTAPP NFT owner.

**Parameters:**

* `caller`: `&signer` - Caller and recipient of the claimed fees.
* `pools`: `vector<address>` - Pools to claim from, in batch order.
* `tokens`: `vector<vector<address>>` - Fee token sets for each pool.
* `ve_token_addr`: `address` - ve token address used for entitlement.

**Entry Function:**

```ts
ve_tapp::voter::claim_fees(caller, pools, tokens, ve_token_addr)
```

***

**`claim_bribes`**

Claims bribe rewards for one or more pools on behalf of the veTAPP NFT owner.

**Parameters:**

* `caller`: `&signer` - Caller and recipient of the claimed bribes.
* `pools`: `vector<address>` - Pools to claim from, in batch order.
* `tokens`: `vector<vector<address>>` - Bribe token sets for each pool.
* `ve_token_addr`: `address` - ve token address used for entitlement.

**Entry Function:**

```ts
ve_tapp::voter::claim_bribes(caller, pools, tokens, ve_token_addr)
```

***

#### Lock

**`create_lock`**

Creates a new voting escrow lock by locking `TAPP` tokens for a specified duration. This mints a new veNFT to the sender.

**Parameters:**

* `value`: `u64` - Amount of `TAPP` tokens to lock.
* `lock_duration`: `u64` - Duration of the lock in seconds.

**Entry Function:**

```ts
ve_tapp::vetapp::create_lock(sender, value, lock_duration)
```

***

**`withdraw`**

Withdraws the locked `TAPP` tokens after the lock duration has expired. The veNFT is burned upon withdrawal.

**Entry Function:**

```ts
ve_tapp::vetapp::withdraw(owner, token_addr)
```

*Note: `token_addr` is the address of the veNFT object.*

***

**`increase_amount`**

Increases the amount of `TAPP` tokens in an existing lock.

**Parameters:**

* `token_addr`: `address` - The address of the veNFT.
* `value`: `u64` - Additional amount of `TAPP` tokens to lock.

**Entry Function:**

```ts
ve_tapp::vetapp::increase_amount(caller, token_addr, value)
```

***

**`increase_unlock_time`**

Extends the unlock time of an existing lock.

**Parameters:**

* `token_addr`: `address` - The address of the veNFT.
* `lock_duration`: `u64` - Additional duration in seconds to add to the current lock.

**Entry Function:**

```ts
ve_tapp::vetapp::increase_unlock_time(owner, token_addr, lock_duration)
```

***

**`merge`**

Merges two veNFTs into one. The source veNFT is burned, and its balance and unlock time are merged into the target veNFT.

**Parameters:**

* `from_nft_addr`: `address` - The address of the veNFT to merge from (will be burned).
* `to_nft_addr`: `address` - The address of the veNFT to merge into.

**Entry Function:**

```ts
ve_tapp::vetapp::merge(sender, from_nft_addr, to_nft_addr)
```

***

**`split`**

Splits a veNFT into two. A new veNFT is minted with the specified amount, and the original veNFT's balance is reduced.

**Parameters:**

* `nft_addr`: `address` - The address of the veNFT to split.
* `value`: `u64` - Amount of `TAPP` tokens to move to the new veNFT.

**Entry Function:**

```ts
ve_tapp::vetapp::split(owner, nft_addr, value)
```

***

**`create_perm_lock`**

Creates a permanent lock. Permanent locks do not have an expiration time and cannot be withdrawn unless unlocked first.

**Parameters:**

* `value`: `u64` - Amount of `TAPP` tokens to lock.
* `lock_duration`: `u64` - Duration of the initial lock in seconds.

**Entry Function:**

```ts
ve_tapp::vetapp::create_perm_lock(sender, value, lock_duration)
```

***

**`create_lock_for`**

Creates a voting escrow lock for a recipient address instead of the sender.

**Parameters:**

* `value`: `u64` - Amount of `TAPP` tokens to lock.
* `lock_duration`: `u64` - Duration of the lock in seconds.
* `recipient`: `address` - Address that receives the veNFT.

**Entry Function:**

```ts
ve_tapp::vetapp::create_lock_for(sender, value, lock_duration, recipient)
```

***

**`create_perm_lock_for`**

Creates a permanent voting escrow lock for a recipient address.

**Parameters:**

* `value`: `u64` - Amount of `TAPP` tokens to lock.
* `lock_duration`: `u64` - Duration of the lock in seconds.
* `recipient`: `address` - Address that receives the veNFT.

**Entry Function:**

```ts
ve_tapp::vetapp::create_perm_lock_for(sender, value, lock_duration, recipient)
```

***

**`deposit_for`**

Adds more `TAPP` to an existing veNFT.

**Parameters:**

* `token_addr`: `address` - The address of the veNFT.
* `value`: `u64` - Additional amount of `TAPP` tokens to lock.

**Entry Function:**

```ts
ve_tapp::vetapp::deposit_for(sender, token_addr, value)
```

***

**`lock_permanent`**

Marks an existing veNFT as permanent.

**Parameters:**

* `token_addr`: `address` - The address of the veNFT.

**Entry Function:**

```ts
ve_tapp::vetapp::lock_permanent(owner, token_addr)
```

***

**`unlock_permanent`**

Converts a permanent lock back to a normal lock with a default expiration.

**Parameters:**

* `token_addr`: `address` - The address of the veNFT.

**Entry Function:**

```ts
ve_tapp::vetapp::unlock_permanent(owner, token_addr)
```

***

## 📌 Fee Guide

| Fee (bps) | % Fee | Description              |
| --------- | ----- | ------------------------ |
| 100       | 0.01% | Low volume, tight spread |
| 500       | 0.05% | Standard for stables     |
| 3000      | 0.3%  | Normal volatile pairs    |
| 10000     | 1%    | Exotic or risky tokens   |
