> For the complete documentation index, see [llms.txt](https://cetus-1.gitbook.io/cetus-developer-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cetus-1.gitbook.io/cetus-developer-docs/developer/via-sdk-v2/sdk-modules/cetusprotocol-sui-clmm-sdk/open-position.md).

# 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)
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

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

```
GET https://cetus-1.gitbook.io/cetus-developer-docs/developer/via-sdk-v2/sdk-modules/cetusprotocol-sui-clmm-sdk/open-position.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

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