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 SpacingFee Rate2
0.0001
10
0.0005
20
0.001
60
0.0025
200
0.01
220
0.02
initialize_sqrt_price
: For computational convenience, we use fixed-point numbers to represent square root prices. UseTickMath.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
Complete the Coin Type: Ensure the coin type is complete before comparing.
Character-by-Character Comparison: Compare the characters of both coin type addresses.
ASCII Value Comparison: When encountering differing characters, compare their ASCII values. The coin with the larger ASCII value becomes "coin A".
Examples:
Example 1:
coin_type_a:
0x6864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS
coin_type_b:
0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI
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
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 poolcoin_amount
: The amount of coins to add as liquidityfix_amount_a
: Boolean value - true means fixed coin A amount, false means fixed coin B amountadd_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 Acoin_decimals_b
: Number of decimal places for coin Bprice_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
Create Pool with Position Return Use
sdk.Pool.createPoolWithPriceReturnPositionPayload()
to create a pool and get the position ID and remaining coins.
// 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())
Create Pool Directly Use
sdk.Pool.createPoolWithPricePayload()
for a simpler pool creation without position management.
// 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
Last updated