# Add liquidity

Once you have set a suitable tick range, you can proceed to add liquidity to this position. The quantity composition of tokens you need to add is affected by the current price of the pool and the tick interval you have chosen.

There are two situations:

* add liquidity with a specified liquidity value
* add liquidity with fixed coin amount.

## 1. Add liquidity with a specified liquidity value

use `sdk.Position.createAddLiquidityPayload()` method.

#### Function input params

*Please refer to the original function for specific parameter types.*

* **`poolID`**: The object id about which pool you want to operation.
* **`posID`**: The object id about position.
* **`maxAmountA`**: The max limit about used coin a amount.
* **`maxAmountB`**: The max limit about used coin b amount.
* **`deltaLiquidity`**: The actual change in liquidity that has been added.

> how to calculate **`deltaLiquidity`** **`maxAmountA`** and **`maxAmountB`** ?
>
> 1. you can set fixed two coin amount you want to use.
> 2. use `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()` to calculated the `delataLiquidity`.
> 3. Apply price slippage adjustment to the two coin amounts(`max_amount_a` and `max_amount_b`) calculated above by method `adjustForCoinSlippage`.

*Notice*: how to calculate **`deltaLiquidity`** **`maxAmountA`** and **`maxAmountB`** ?

* **`tickLower`**: Represents the index of the lower tick boundary.
* **`tickUpper`**: Represents the index of the upper tick boundary.
* **`collectFee`**: If you already has one position, you can select collect fees while adding liquidity.
* **`rewarderCoinTypes`**: If these not empty, it will collect rewarder in this position, if you already open the position.

#### Example

```ts
const pool = await buildTestPool(sdk, TokensMapping.USDT_USDC_LP.poolObjectIds[0])
const curSqrtPrice = new BN(pool.current_sqrt_price)
// ===>tick_uppe
const tick_lower_index = -304
const tick_upper_index = 552
const slippageTolerance = new Percentage(new BN(5), new BN(100))

const totalAmount = '18.73'
const tokenPriceA = '1.000625867190606471'
const tokenPriceB = '1'

const coinAmounts = ClmmPoolUtil.estCoinAmountsFromTotalAmount(
  tick_lower_index,
  tick_upper_index,
  curSqrtPrice,
  totalAmount,
  tokenPriceA,
  tokenPriceB
)
console.log('coinAmounts: ', coinAmounts)

const amountA = toDecimalsAmount(coinAmounts.amountA.toFixed(6, Decimal.ROUND_UP).toString(), 6)
const amountB = toDecimalsAmount(coinAmounts.amountB.toFixed(6, Decimal.ROUND_UP).toString(), 6)

const tokenAmounts = {
  coinA: new BN(amountA),
  coinB: new BN(amountB),
}

const liquidity = ClmmPoolUtil.estimateLiquidityFromcoinAmounts(curSqrtPrice, tick_lower_index, tick_upper_index, tokenAmounts)

console.log('liquidity: ', liquidity.toString())

const { tokenMaxA, tokenMaxB } = adjustForCoinSlippage(tokenAmounts, slippageTolerance, true)

const addLiquidityPayloadParams: AddLiquidityParams = {
  coinTypeA: pool.coinTypeA,
  coinTypeB: pool.coinTypeB,
  pool_id: pool.poolAddress,
  tick_lower: tick_lower_index.toString(),
  tick_upper: tick_upper_index.toString(),
  delta_liquidity: liquidity.toString(),
  max_amount_a: tokenMaxA.toString(),
  max_amount_b: tokenMaxB.toString(),
  pos_id: '',
  rewarder_coin_types: [],
  collect_fee: false,
}

const payload = await sdk.Position.createAddLiquidityPayload(addLiquidityPayloadParams)

printTransaction(payload)

const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair, payload)
console.log('createAddLiquidityPayload: ', transferTxn)
```

## 2. Add liquidity with a fixed coin amount

This function is the same as open position and add liquidity with fixed coin amount.

#### Function input params

*Please refer to the original function for specific parameter types.*

* **`poolID`**: The object id about which pool you want to operation.
* **`coinTypeA`**: the coin type address about coinA.
* **`coinTypeB`**: the coin type address about coinB.
* **`tickLower`**: Represents the index of the lower tick boundary.
* **`tickUpper`**: Represents the index of the upper tick boundary.

{% hint style="info" %}

* The tick index must be an integer multiple of `tickSpacing`. If the provided parameter is not a multiple of `tickSpacing`, the contract will throw an error.
* -443636 < `tickLowerIndex` < `tickUpperIndex` < 443636, 443636 is a constant, derived from the maximum range representable by the Q32.62 fixed-point number format.
* If you know price range, then you can use `TickMath.priceToTickIndex()` to transform real price to tick index.
* You can just open one position near the current price of the pool, use `TickMath.getPrevInitializableTickIndex()` and `TickMath.getNextInitializableTickIndex()` to find the next initialized tick.
* If you want to add global liquidity, you can set `tickLowerIndex` = - 443636 + (443636 % tick\_spacing), `tickUpperIndex` = 443636 - (443636 % tick\_spacing)
  {% endhint %}

- **`isOpen`**: `true` means if first add liquidity, so needs open one position.
- **`posID`**: The object id about position.
- **`fixAmountA`**: `true` means fixed coinA amount, `false` means fixed coinB amount
- **`amountA`**: If fixed amount A, you must set `amount_a`, `amount_b` will be auto calculated by `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()`.
- **`amountB`**: If fixed amount B, you must set `amount_b`, `amount_a` will be auto calculated by `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()`.

  *Notice*: `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()` calculate result means when fixed one coin amount, another coin amount will change because of pool price change. so it will calculated based on the current pool price and processed with slippage.
- **`slippage`**: Price slippage point.
- **`collectFee`**: If you already has one position, you can select collect fees while adding liquidity.
- **`rewarderCoinTypes`**: If these not empty, it will collect rewarder in this position, if you already open the position.

#### Example

```ts
const poolObjectId = '0xcf994611fd4c48e277ce3ffd4d4364c914af2c3cbb05f7bf6facd371de688630' //  TokensMapping.USDT_USDC_LP.poolObjectIds[0]
const pool = await buildTestPool(sdk, poolObjectId)
const lowerTick = TickMath.getPrevInitializableTickIndex(
  new BN(pool.current_tick_index).toNumber(),
  new BN(pool.tickSpacing).toNumber()
)
const upperTick = TickMath.getNextInitializableTickIndex(
  new BN(pool.current_tick_index).toNumber(),
  new BN(pool.tickSpacing).toNumber()
)
const coinAmount = new BN(100)
const fix_amount_a = true
const slippage = 0.01
const curSqrtPrice = new BN(pool.current_sqrt_price)

const liquidityInput = ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts(
  lowerTick,
  upperTick,
  coinAmount,
  fix_amount_a,
  true,
  slippage,
  curSqrtPrice
)

const amount_a = fix_amount_a ? coinAmount.toNumber() : liquidityInput.tokenMaxA.toNumber()
const amount_b = fix_amount_a ? liquidityInput.tokenMaxB.toNumber() : coinAmount.toNumber()

console.log('amount: ', { amount_a, amount_b })

const addLiquidityPayloadParams: AddLiquidityFixTokenParams = {
  coinTypeA: pool.coinTypeA,
  coinTypeB: pool.coinTypeB,
  pool_id: pool.poolAddress,
  tick_lower: lowerTick.toString(),
  tick_upper: upperTick.toString(),
  fix_amount_a,
  amount_a,
  amount_b,
  slippage,
  is_open: true,
  rewarder_coin_types: [],
  collect_fee: false,
  pos_id: '',
}
const createAddLiquidityTransactionPayload = await sdk.Position.createAddLiquidityFixTokenPayload(addLiquidityPayloadParams, {
  slippage: slippage,
  curSqrtPrice: curSqrtPrice,
})

printTransaction(createAddLiquidityTransactionPayload)
const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair, createAddLiquidityTransactionPayload)
console.log('open_and_add_liquidity_fix_token: ', transferTxn)
```
