Open position

Before you want to deposit liquidity, you need to choose an appropriate price range (corresponding to the tick range) to open a position.

There are two situations:

  • open a position only

  • open positon and add liquidity (recommended)

In most cases, opening a position and adding liquidity are supposed to be done simultaneously.

1. Open a position only

Use sdk.Position.openPositionTransactionPayload() 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.

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

  • 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)

Example:

const sendKeypair = buildTestAccount()
// fetch pool data
const pool = await sdk.Pool.getPool(poolAddress)
// build tick range
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()
    )
// build open position payload
const openPositionTransactionPayload = sdk.Position.openPositionTransactionPayload({
      coinTypeA: pool.coinTypeA,
      coinTypeB: pool.coinTypeB,
      tick_lower: lowerTick.toString(),
      tick_upper: upperTick.toString(),
      pool_id: pool.poolAddress,
    })
console.log('openPositionTransactionPayload: ', openPositionTransactionPayload)

const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair,openPositionTransactionPayload)

2. Open position with add liquidity

Use sdk.Position.createAddLiquidityFixTokenPayload() 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.

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

  • 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)

  • 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 amountA, amountB will be auto calculated by ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts().

  • amountB: If fixed amount B, you must set amountB, amountA will be auto calculated by ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts().

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

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)

Last updated