# Create CLMM Pool

Everyone can create Cetus CLMM pools directly.

### 1. Create a CLMM Pool with Initial Liquidity

Use `sdk.Pool.createPoolTransactionPayload()` to create a pool.

#### Function Parameters

**Required Parameters**

* `tick_spacing`: Affects price precision.  Different tick spacing values correspond to different fee rates:

  | Tick Spacing | Fee Rate |
  | ------------ | -------- |
  | 2            | 0.0001   |
  | 4            | 0.0002   |
  | 6            | 0.0003   |
  | 8            | 0.0004   |
  | 10           | 0.0005   |
  | 20           | 0.001    |
  | 30           | 0.0015   |
  | 40           | 0.002    |
  | 60           | 0.0025   |
  | 80           | 0.003    |
  | 100          | 0.004    |
  | 120          | 0.006    |
  | 160          | 0.008    |
  | 200          | 0.01     |
  | 220          | 0.02     |
  | 260          | 0.04     |
* `initialize_sqrt_price`: For computational convenience,  we use fixed-point numbers to represent square root prices. Use `TickMath.priceToSqrtPriceX64()` to transform price to sqrtPrice.
* `coin_type_a`: The coin type address for coin A.
* `coin_type_b`: The coin type address for coin B.
* `amount_a`: The amount of coin A to add as liquidity.
* `amount_b`: The amount of coin B to add as liquidity.
* `fix_amount_a`: Boolean value - true means fixed coin A amount, false means fixed coin B amount.
* `tick_lower`: The index of the lower tick boundary.
* `tick_upper`: The index of the upper tick boundary.
* `metadata_a`: The coin metadata ID of coin A.
* `metadata_b`: The coin metadata ID of coin B.

**Optional Parameters**

* `uri`: The icon of the pool (can be null).

#### Determining Coin Type A and B

1. Complete the Coin Type: Ensure the coin type is complete before comparing.
2. Character-by-Character Comparison: Compare the characters of both coin type addresses.
3. ASCII Value Comparison: When encountering differing characters, compare their ASCII values. The coin with the larger ASCII value becomes "coin A".

**Examples:**

1. Example 1:
   * coin\_type\_a: `0x6864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS`
   * coin\_type\_b: `0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI`
2. Example 2:
   * coin\_type\_a: `0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC`
   * coin\_type\_b: `0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN`

#### Important Notes

* The tick index must be an integer multiple of tickSpacing.
* Range: `-443636 < tick_lower_index < current_tick_index < tick_upper_index < 443636`
* Currently,  creating a pool requires adding bidirectional liquidity.

### Example Code

```typescript
const sdk = CetusClmmSDK.createSDK({ env: 'mainnet' })
const signer = ... // set keypair
sdk.senderAddress = signer.getPublicKey().toSuiAddress() // set sdk.senderAddress

// Initialize sqrt_price
const initialize_sqrt_price = TickMath.priceToSqrtPriceX64(d(1.2),6,6).toString()
const tick_spacing = 2
const current_tick_index = TickMath.sqrtPriceX64ToTickIndex(new BN(initialize_sqrt_price))

// Build tick range
const tick_lower = TickMath.getPrevInitializeTickIndex(
    new BN(current_tick_index).toNumber(),
    new BN(tick_spacing).toNumber()
)
const tick_upper = TickMath.getNextInitializeTickIndex(
    new BN(current_tick_index).toNumber(),
    new BN(tick_spacing).toNumber()
)

// Input token amount
const fix_coin_amount = new BN(200)
const fix_amount_a = true // input token amount is token a
const slippage = 0.05 // 5% slippage
const cur_sqrt_price = new BN(initialize_sqrt_price)

// Estimate liquidity and token amount from one amounts
const res = ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts(
    lower_tick,
    upper_tick,
    fix_coin_amount,
    fix_amount_a,
    true,
    slippage,
    cur_sqrt_price
)

// Estimate token a and token b amount
const amount_a = fix_amount_a ? fix_coin_amount.toNumber() : res.coin_amount_limit_a.toNumber()
const amount_b = fix_amount_a ? res.coin_amount_b.toNumber() : fix_coin_amount.toNumber()

const coin_type_a = '0x3cfe7b9f6106808a8178ebd2d5ae6656cd0ccec15d33e63fd857c180bde8da75::coin:CetusUSDT'
const coin_type_b = '0x3cfe7b9f6106808a8178ebd2d5ae6656cd0ccec15d33e63fd857c180bde8da75::coin::CetusUSDC'

const coin_metadata_a_id = await suiClient.fetchCoinMetadata({coinType: coin_type_a}).id
const coin_metadata_b_id = await suiClient.fetchCoinMetadata({coinType: coin_type_b}).id

// Build createPoolPayload
const create_pool_payload = sdk.Pool.createPoolPayload({
    coin_type_a,
    coin_type_b,
    tick_spacing: tick_spacing,
    initialize_sqrt_price: initialize_sqrt_price,
    uri: '',
    amount_a,
    amount_b,
    fix_amount_a,
    tick_lower,
    tick_upper,
    metadata_a: coin_metadata_a_id,
    metadata_b: coin_metadata_b_id,
})
const send_key_pair = 'THE_KEY_PAIR_GENERATED_BY_YOUR_PRIVATE_KEY'
const transfer_txn = await sdk.FullClient.executeTx(send_key_pair, tx, true)
```

### 2. Create a CLMM Pool with Initial Liquidity by directly inputting the price range

Use `sdk.Pool.createPoolWithPricePayload()` to create a pool.

#### Function Parameters

**Required Parameters**

* `tick_spacing`: Affects price precision and fee rate (see table above)
* `current_price`: The initial price of the pool
* `coin_amount`: The amount of coins to add as liquidity
* `fix_amount_a`: Boolean value - true means fixed coin A amount, false means fixed coin B amount
* `add_mode_params`: Configuration for price range:
  * For custom range: `{ is_full_range: false, min_price: string, max_price: 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'**)
* `slippage`: Maximum acceptable slippage (e.g., 0.05 for 5%)

#### Two Ways to Create Pool

1. **Create Pool with Position Return**\
   Use `sdk.Pool.createPoolWithPriceReturnPositionPayload()` to create a pool and get the position ID and remaining coins.

```typescript
// Custom price range example
const tick_spacing = 220

const mode_params: CreatePoolCustomRangeParams = {
  is_full_range: false,
  min_price: '0.2',
  max_price: '0.7',
}

const result = await sdk.Pool.calculateCreatePoolWithPrice({
  tick_spacing,
  current_price: '0.5',
  coin_amount: '1000000',
  fix_amount_a: true,
  add_mode_params: mode_params,
  coin_decimals_a: 6,
  coin_decimals_b: 9,
  price_base_coin: 'coin_a',
  slippage: 0.05,
})

const { tx, pos_id, remain_coin_a, remain_coin_b, remain_coin_type_a, remain_coin_type_b } =
  await sdk.Pool.createPoolWithPriceReturnPositionPayload({
    tick_spacing,
    calculate_result: result,
    add_mode_params: mode_params,
    coin_type_a,
    coin_type_b,
  })

// Handle remaining coins
buildTransferCoin(sdk, tx, remain_coin_a, remain_coin_type_a)
buildTransferCoin(sdk, tx, remain_coin_b, remain_coin_type_b)
tx.transferObjects([pos_id], sdk.getSenderAddress())
```

2. **Create Pool Directly**\
   Use `sdk.Pool.createPoolWithPricePayload()` for a simpler pool creation without position management.

```typescript
// Full range example
const full_range_params: FullRangeParams = {
  is_full_range: true,
}

const full_range_result = await sdk.Pool.calculateCreatePoolWithPrice({
  tick_spacing,
  current_price: '0.5',
  coin_amount: '1000000',
  fix_amount_a: true,
  add_mode_params: full_range_params,
  coin_decimals_a: 6,
  coin_decimals_b: 9,
  price_base_coin: 'coin_a',
  slippage: 0.05,
})

const tx = await sdk.Pool.createPoolWithPricePayload({
  tick_spacing,
  calculate_result: full_range_result,
  add_mode_params: full_range_params,
  coin_type_a,
  coin_type_b,
})
```

#### Important Notes

* The price range must be valid and within acceptable bounds
* For custom ranges, ensure **min\_price** < **current\_price** < **max\_price**
* The tick spacing determines the fee rate and price precision
* Slippage protection is important to prevent significant price impact
* Consider the decimal places of both coins when calculating amounts


---

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

```
GET https://cetus-1.gitbook.io/cetus-developer-docs/developer/via-sdk-v2/sdk-modules/cetusprotocol-sui-clmm-sdk/create-clmm-pool.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
