What this does. Creates a new CLMM pool at the fee tier of your choice, then opens an initial concentrated position. Two transactions, one script. Code is lifted from the official demos in
raydium-sdk-V2-demo/src/clmm and adapted to a single Node-runnable file.Setup
Make sure you’ve read the Quick start prerequisites and haveRPC_URL, KEYPAIR, and the deps installed.
CLMM pool creation has a one-time fee plus per-tick-array rent for the initial position. You’ll also need both seed mints in your wallet — opening a position when the price sits inside the chosen range requires liquidity on both sides.
Step 1 — config.ts
Save as config.ts. This is the same shape as the demo repo’s src/config.ts.template — disableFeatureCheck is forced to true (recommended for any non-trivial integration so the SDK does not block on its startup feature-detect call):
Step 2 — createPool.ts
Save alongside config.ts. Source: src/clmm/createPool.ts.
Step 3 — createPosition.ts
Source: src/clmm/createPosition.ts.
Step 4 — utils.ts
Source: src/clmm/utils.ts.
Run it
What just happened
Transaction 1 —raydium.clmm.createPool initialized:
- the pool state at the canonical PDA for
(mint1, mint2, ammConfig), token_0_vaultandtoken_1_vault(sorted by mint byte order),- the
observationring buffer, - the inline tick-array bitmap,
sqrt_price_x64 from your initialPrice.
Transaction 2 — raydium.clmm.openPositionFromBase opened a concentrated position:
- minted a position NFT to your wallet (the NFT is the position; transferring it transfers the position),
- allocated tick arrays at the lower and upper bounds (one-time rent if first position in those ranges; tick arrays are never closed by the program, so subsequent positions in the same arrays pay no extra rent),
- deposited
inputAmountofmint1and the matching pair amount ofmint2(computed byPoolUtils.getLiquidityAmountOutFromAmountIn), - credited the position with liquidity proportional to the range width.
[0.000001, 100000]) is effectively full-range; tighten it to concentrate fees near current spot.
Picking a fee tier
clmmConfigs[0] is the lowest-fee tier. The full set is published at GET https://api-v3.raydium.io/main/clmm-config:
| Index | tradeFeeRate | Tick spacing | Use when |
|---|---|---|---|
| 0 | 100 (1bp) | 1 | Stable / stable, very low impermanent loss expected |
| 1 | 500 (5bp) | 10 | Highly correlated assets (e.g. liquid-staked vs underlying) |
| 2 | 2_500 (25bp) | 60 | Standard token pair, blue-chip + stable |
| 3 | 10_000 (1.00%) | 120 | Volatile or thin pair where IL risk is high |
user-flows/choosing-a-pool-type for a full decision matrix.
Common errors
Pool already exists for this config— A CLMM pool already exists for this(mint1, mint2, ammConfig)triple. Look up the existing pool ID and skip Step 2.Insufficient funds for amount B— Your wallet has the requested amount ofmintAbut not the matchingmintB. Opening a position when the price sits inside the range requires liquidity on both sides.Tick out of range— YourlowerPriceorupperPricefalls outside the representable price range. Use a more reasonable range relative to current price.- Stale price — A quote from the API can be 5–60 seconds stale. If
executePositionfails on slippage, uncomment thegetRpcClmmPoolInfoblock increatePosition.tsto re-fetch the live price right before signing.
Caveats
- Position NFT is your only handle. Lose the NFT or transfer it, lose access to the position. Treat it like a key.
- Out-of-range positions earn no fees. If price moves outside
[lowerPrice, upperPrice], your position is parked entirely in one asset and earns nothing until you rebalance. - Tick array rent is one-way. The first position to touch a never-initialised tick array pays its rent; the program does not expose a path to close tick arrays, so that rent is permanent. Subsequent positions in the same array are free.
Next
products/clmm/overview— full CLMM mechanics.products/clmm/ticks-and-positions— the math behind ticks.algorithms/impermanent-loss— quantifying CLMM IL amplification.user-flows/create-clmm-pool— the same flow via the Raydium UI.

