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

1. Open a position only
2. Open position and add liquidity (recommended)

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

### 1.1. Open a Position Only with tick range

Use `sdk.Position.openPositionPayload()` method.

#### Function Parameters

* `pool_id`: The object id about which pool you want to operation
* `coin_type_a`: The coin type address about coinA
* `coin_type_b`: The coin type address about coinB
* `tick_lower`: Represents the index of the lower tick boundary
* `tick_upper`: Represents the index of the upper tick boundary

#### Important Notes

* 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 < tick_lower_index < tick_upper_index < 443636`,  **443636** is a constant, derived from the maximum range representable by the Q32.62 fixed-point number format.
* If you know price range, 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.getPrevInitializeTickIndex()` and `TickMath.getNextInitializeTickIndex()` to find the next initialized tick.
* If you want to add global liquidity, you can set:
  * `tick_lower_index = -443636 + (443636 % tick_spacing)`
  * `tick_upper_index = 443636 - (443636 % tick_spacing)`

#### &#x20;Example

```typescript
const send_key_pair = 'THE_KEY_PAIR_GENERATED_BY_YOUR_PRIVATE_KEY'
// fetch pool data
const pool = await sdk.Pool.getPool(pool_id)
// build tick range
const lower_tick = TickMath.getPrevInitializeTickIndex(new BN(pool.current_tick_index).toNumber(), new BN(pool.tick_spacing).toNumber())
const upper_tick = TickMath.getNextInitializeTickIndex(new BN(pool.current_tick_index).toNumber(), new BN(pool.tick_spacing).toNumber())
// build open position payload
const open_position_payload = sdk.Position.openPositionPayload({
  coin_type_a: pool.coin_type_a,
  coin_type_b: pool.coin_type_b,
  tick_lower: lower_tick.toString(),
  tick_upper: upper_tick.toString(),
  pool_id: pool.id,
})
const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, open_position_payload, true)
```

#### 1.2 Open a Position Only with price range

Use `sdk.Position.openPositionWithPricePayload()` method.

**Required Parameters**

* `pool_id`: The object id about which pool you want to operation
* `add_mode_params`: Configuration for price range:
  * For custom range: `{ is_full_range: false, min_price: string, max_price: string , price_base_coin: string }`
  * For full range: `{ is_full_range: true }`
* `coin_decimals_a`: Number of decimal places for coin A
* `coin_decimals_b`: Number of decimal places for coin B
* `price_base_coin`: Base coin for price calculation (**'coin\_a'** or **'coin\_b'**)

```typescript
const pool_id = '0x0...'

// use full range price mode
const full_range_params: OpenPositionWithPriceParams = {
  pool_id,
  is_full_range: true,
}
const open_payload = await sdk.Position.openPositionWithPricePayload(full_range_params)

// or
// use custom price range
const custom_price_range_params: OpenPositionWithPriceParams = {
  pool_id,
  coin_decimals_a: 6,
  coin_decimals_b: 9,
  is_full_range: false,
  min_price: '0.2',
  max_price: '0.9',
  price_base_coin: 'coin_a',
}
const open_payload = await sdk.Position.openPositionWithPricePayload(custom_price_range_params)

const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, open_payload, true)
```

### 2.1 Open Position with Add Liquidity by tick range

Use `sdk.Position.createAddLiquidityFixTokenPayload()` method.

#### Function Parameters

* `pool_id`: The object id about which pool you want to operation
* `coin_type_a`: The coin type address about coinA
* `coin_type_b`: The coin type address about coinB
* `tick_lower`: Represents the index of the lower tick boundary
* `tick_upper`: Represents the index of the upper tick boundary
* `is_open`: true means if first add liquidity, so needs open one position
* `pos_id`: The object id about position
* `fix_amount_a`: true means fixed coinA amount, false means fixed coinB amount
* `amount_a`: If fixed amount A, you must set amount\_a, amount\_b will be auto calculated by `ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts()`
* `amount_b`: If fixed amount B, you must set amount\_b, amount\_a will be auto calculated by `ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts()`
* `collect_fee`: If you already has one position, you can select collect fees while adding liquidity
* `rewarder_coin_types`: If these not empty, it will collect rewarder in this position, if you already open the position

#### Important Notes

* 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 < tick_lower_index < tick_upper_index < 443636`, **443636** is a constant, derived from the maximum range representable by the Q32.62 fixed-point number format.
* If you know price range, 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.getPrevInitializeTickIndex()` and `TickMath.getNextInitializeTickIndex()` to find the next initialized tick.
* If you want to add global liquidity, you can set:
  * `tick_lower_index = -443636 + (443636 % tick_spacing)`
  * `tick_upper_index = 443636 - (443636 % tick_spacing)`

#### Example

```typescript
const pool = await sdk.Pool.getPool(pool_id)
const coin_amount = new BN(500)
const fix_amount_a = true
const slippage = 0.1
const cur_sqrt_price = new BN(pool.current_sqrt_price)

const tick_lower_index = TickMath.getPrevInitializeTickIndex(
  new BN(pool.current_tick_index).toNumber(),
  new BN(pool.tick_spacing).toNumber()
)
const tick_upper_index = TickMath.getNextInitializeTickIndex(
  new BN(pool.current_tick_index).toNumber(),
  new BN(pool.tick_spacing).toNumber()
)

const liquidity_input = ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts(
  tick_lower_index,
  tick_upper_index,
  coin_amount,
  fix_amount_a,
  true,
  slippage,
  cur_sqrt_price
)

const amount_a = fix_amount_a ? coin_amount.toNumber() : Number(liquidity_input.coin_amount_limit_a)
const amount_b = fix_amount_a ? Number(liquidity_input.coin_amount_limit_b) : coin_amount.toNumber()

const add_liquidity_payload_params: AddLiquidityFixTokenParams = {
  coin_type_a: pool.coin_type_a,
  coin_type_b: pool.coin_type_b,
  pool_id: pool.id,
  tick_lower: tick_lower_index.toString(),
  tick_upper: tick_upper_index.toString(),
  fix_amount_a,
  amount_a,
  amount_b,
  slippage,
  is_open: true,
  pos_id: position.pos_object_id,
  rewarder_coin_types: [],
  collect_fee: false,
}
const add_liquidity_payload = await sdk.Position.createAddLiquidityFixTokenPayload(add_liquidity_payload_params)

const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, add_liquidity_payload, true)
```

### 2.2 Open Position with Add Liquidity by price range

Use `sdk.Position.createAddLiquidityFixCoinWithPricePayload()` method.

#### Function Parameters

* `pool_id`: The object id about which pool you want to operation
* `add_mode_params`: Configuration for price range:
  * For custom range: `{ is_full_range: false, min_price: string, max_price: string , price_base_coin: string, coin_decimals_a: number, coin_decimals_b: number }`
  * For full range: `{ is_full_range: true }`
* `coin_decimals_a`: Number of decimal places for coin A
* `coin_decimals_b`: Number of decimal places for coin B
* `price_base_coin`: Base coin for price calculation (**'coin\_a'** or **'coin\_b'**)

#### Example

Use `sdk.Position.createAddLiquidityFixTokenPayload()` method.

```typescript
// custom price range
const params: CustomRangeParams = {
  s_full_range: false,
  min_price: '0.2',
  max_price: '0.7',
  coin_decimals_a: 6,
  coin_decimals_b: 9,
  price_base_coin: 'coin_a',
}

// or
//  full range price
const params: FullRangeParams = {
  is_full_range: true,
}

const result = await sdk.Position.calculateAddLiquidityResultWithPrice({
  add_mode_params: params,
  pool_id,
  slippage: 0.01,
  coin_amount: toDecimalsAmount(1, 6).toString(),
  fix_amount_a: true,
})

const payload = await sdk.Position.createAddLiquidityFixCoinWithPricePayload({
  pool_id,
  calculate_result: result,
  add_mode_params: params,
})

const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, payload, true)
```
