Skip to main content
Version banner. All TypeScript demos target @raydium-io/raydium-sdk-v2@0.2.64-alpha; they were last executed against 0.2.42-alpha (2026-04) and their call signatures re-checked against the 0.2.64-alpha source on 2026-09-09, against Solana mainnet-beta. The Rust CPI skeleton targets raydium-cp-swap on the chore/upgrade-anchor branch, Anchor 1.0.2 — master still pins 0.32.1. Program IDs are pulled via constants from reference/program-addresses.

Prerequisites

Every demo on this page mirrors a file in raydium-sdk-V2-demo/src/cpmm; the GitHub link sits next to each section. Bootstrap follows the demo repo’s config.ts.template (source):
The Raydium instance is the SDK’s facade — every demo below uses it. Raydium.load is async because it loads the token list by default; pass disableLoadToken: true to skip that fetch. The availability feature-check is already skipped unless you pass disableFeatureCheck: false. Fee configs are fetched lazily on first use via raydium.api.getCpmmConfigs().

Create a CPMM pool

Source: src/cpmm/createCpmmPool.ts
A few things the SDK quietly takes care of:
  • Sorting the mints into token0/token1 order before deriving the PDA.
  • Paying the one-time create_pool_fee to poolFeeAccount.
  • Creating the caller’s associated token accounts if missing.
  • Choosing the right token program (SPL Token vs Token-2022) per side.
After confirmation you can fetch the live pool state with:

Swap (base-input)

Source: src/cpmm/swap.ts
Note: the SDK always re-fetches the pool state from an RPC inside getPoolInfoFromRpc. Do not quote off api-v3.raydium.io for a transaction you are about to sign — a quote that is one block stale can slip into ExceededSlippage at land time.

Swap (base-output)

Source: src/cpmm/swapBaseOut.ts

Deposit liquidity

Source: src/cpmm/deposit.ts
The SDK derives the paired amount from the pool’s current reserves, inflates each side by the slippage for the instruction’s maximum_* arguments, and builds the ATA creations if necessary. raydium.cpmm.computePairAmount({ ... }) returns the same numbers if you want them for a UI preview.

Withdraw liquidity

Source: src/cpmm/withdraw.ts

Collect protocol/fund/creator fees

Source: src/cpmm/collectCreatorFee.ts, src/cpmm/collectAllCreatorFee.ts Protocol and fund collection remain authority-gated. Creator fees have two paths: the creator-signed CollectCreatorFee, and the additive CollectCreatorFeePermissionless, which any payer can invoke but which can transfer only to the creator’s canonical ATAs. 0.2.64-alpha ships module-level builders for both creator paths:
Both creator instructions changed their account lists in the 2026-09-19 program upgrade. Each now takes a creator_fee_share PDA at ["creator_fee_share", creator, ammConfig], and the permissionless one takes amm_config as well — both appended after system_program rather than inserted, so the accounts that were already there keep their positions. A builder pinned to an SDK release that predates the upgrade emits the shorter list and the transaction is rejected for missing accounts. Check that the version you install carries the new accounts before using these helpers against the upgraded program, and refresh the IDL if you generate clients from it.Passing the PDA is mandatory even when it has never been created — derive it and pass it; the program falls back to AmmConfig.creator_fee_share_rate when the account is empty.
The two creator instructions have different discriminators and account layouts — the permissionless one replaces the creator signer with a separate payer and a non-signing creator. Use the matching builder rather than hand-swapping accounts on the other one.There is no protocol- or fund-fee builder in the SDK (makeCollectProtocolFeeInstruction and makeCollectFundFeeInstruction do not exist under any name) — those are admin paths, and so are CreateCreatorFeeShare / CloseCreatorFeeShare, which have no builder either. The low-level instruction builders that do exist are collectCpFeeInstruction, makeCollectCreatorFeeInstruction and collectCreatorFeePermissionlessInInstruction.
Off-chain you can read accrued fees directly from PoolState:

Rust CPI skeleton

If you want to invoke CPMM from your own Anchor program — for example, a vault that swaps on behalf of its depositors — the CPI context looks like this. Account ordering follows products/cpmm/instructions.
If your CPI signs as a PDA (e.g., you manage a vault on behalf of depositors), swap CpiContext::new for CpiContext::new_with_signer and pass your seeds.

Common pitfalls

A short checklist before opening a support ticket:
  • Sorted mints. If your derived poolState PDA does not match the on-chain pool, you probably forgot to sort the mints.
  • Stale API quote. Never pass a reserve value from api-v3.raydium.io into CurveCalculator.swap. Fetch from an RPC.
  • Wrong token program. A Token-2022 mint’s vault is owned by the Token-2022 program, not by SPL Token. Always use the pool’s token_0_program / token_1_program fields.
  • Slippage under-denominated for transfer-fee mints. If either side of the pool is a Token-2022 transfer-fee mint, your minimum_amount_out must be denominated in what the user actually receives, not in what the vault sends.
  • NotApproved on a swap. Check PoolState.status — the admin may have paused swaps on that pool. See products/cpmm/instructions for the status bitmask.

Where to go next

Sources: