本页内容由 AI 自动翻译,所有内容以英文版本为准。查看英文版 →
版本说明。 所有示例针对
@raydium-io/raydium-sdk-v2@0.2.42-alpha 在 Solana mainnet-beta 上运行,已于 2026-04 验证。程序 ID 来自 SDK 中的 reference/program-addresses。设置
raydium-sdk-V2-demo/src/clmm 中的一个文件;每个部分旁边都有 GitHub 链接。初始化遵循示例仓库的 config.ts.template(源代码)— 对于任何非平凡的集成,推荐设置 disableFeatureCheck: true:
创建 CLMM 池
源代码:src/clmm/createPool.ts
- 按字节顺序对
mint1/mint2进行排序后再推导。 - 计算
sqrt_price_x64 = floor(sqrt(initialPrice × 10^(dB−dA)) × 2^64)。 - 创建
observation和tick_array_bitmap_extension账户。 - 支付由
ammConfig定义的池创建费用。
在选定范围内开仓
源代码:src/clmm/createPosition.ts
InitTickArray 指令。
增加现有仓位的流动性
源代码:src/clmm/increaseLiquidity.ts
减少流动性(同时收取费用)
源代码:src/clmm/decreaseLiquidity.ts 和 src/clmm/closePosition.ts
decreaseLiquidity 时设置 liquidity = new BN(0)。该指令的副作用是结算 tokens_fees_owed_{0,1} 并转出它们。
要在流动性和费用都清零后完全关闭仓位,在最后一次 decreaseLiquidity 调用时传递 closePosition: true。SDK 会追加 ClosePosition 并销毁 NFT。
对于直接的 Anchor 客户端,保持声明的账户不变并追加池:
poolId。CLMM 仅在 positionNftAccount 冻结时读取它,这使一个客户端路径与旧仓位和新仓位都兼容。
收取奖励
源代码:src/clmm/harvestAllRewards.ts
harvestAllRewards 遍历传入的每个池上的每个仓位,批量处理 CollectReward(和任何 UpdateRewardInfos)指令,如果需要会跨多个交易分割。
交换
源代码:src/clmm/swap.ts
computeAmountOutFormat 使用与链上程序相同的逻辑离线遍历 tick 映射,并返回:
- 预期输出数量,
- 滑点后的最小输出数量,
- 实际交换将触及的 tick 数组账户列表(
remainingAccounts)。
remainingAccounts:如果传递的太少,交换会在遍历中途以 TickArrayNotFound 回滚;如果传递过时的,会浪费计算。
创建可自定义的 CLMM 池
createCustomizablePool 是新的入口点,在池创建时暴露动态费用和单边费用切换。它采用与 createPool 相同的形式加上三个新增项:
createPool 继续用于默认费用、无限价单、无动态费用的路径。当你需要三个新开关中的任何一个时,使用 createCustomizablePool。详见 products/clmm/instructions 的链上账户列表。
限价单
限价单在单个 tick 处停泊用户输入,当交换穿过该 tick 时按 FIFO 成交。输出在结算时推送到所有者的 ATA;所有者无需在线即可成交。开启限价单
(pool, owner, tick, nonce) 推导 LimitOrderState PDA,为每个 (pool, owner) 对增加 LimitOrderNonce,并将订单插入该 tick 处的 FIFO 队列。
增加/减少开放订单
decreaseLimitOrder 只能从订单的未成交部分移除;成交部分被锁定直到结算。如果订单已完全成交,两个指令都会以 InvalidOrderPhase 回滚。
结算已成交的订单
settleLimitOrder 根据队列跟踪器读取订单的 unfilled_ratio_x64,计算成交输出,并将其转移到所有者的 ATA。所有者可以自己调用此方法;limit_order_admin(离线操作守护进程)也可以代表所有者调用 — 输出仍然进入所有者账户。
要关闭完全结算的订单以恢复租金,使用 closeLimitOrder(单个)或 closeAllLimitOrder(批量)。要一次结算许多订单,settleAllLimitOrder 会尽可能多地将 SettleLimitOrder 调用打包到一个 v0 交易中。
列出钱包的停泊订单(离线)
totalAmount / filledAmount / pendingSettle 区分阶段)。对于已关闭订单历史,使用 /limit-order/history/order/list-by-user?wallet=…(按钱包,按 nextPageId 分页);对于特定订单的完整事件日志,使用 /limit-order/history/event/list-by-pda?pda=…。
Rust CPI 骨架
SwapV2 的剩余账户顺序:
常见陷阱
- 非对齐 tick 端点 →
InvalidTickIndex。始终通过TickUtils.getPriceAndTick对齐。 SwapV2中提供的 tick 数组不足 →TickArrayNotFound。使用computeAmountOutFormat获取完整列表。- 没有 bitmap 扩展的全范围仓位 → 扩展 PDA 必须可写;SDK 会自动处理。
- 混淆
sqrt_price_x64和price→ 这里的因子-2 混淆特别痛苦。有疑问时,让 SDK 从人类可读的价格计算。 - 过于频繁地收取奖励 → 每次收取需要一个交易。通过
harvestAllRewards跨多个仓位批量处理。 - 自己关闭 NFT 账户 →
ClosePosition销毁 NFT 并关闭其 ATA。它也关闭 Token-2022 NFT 铸币;经典 SPL Token 铸币保持供应量为零,因为该程序无法关闭铸币。不要单独关闭支持的账户,否则指令会回滚。 - 在非对齐 tick 处开启限价单 →
InvalidTickIndex。始终通过TickUtils.getPriceAndTick量化。 - 在完全成交的订单上调用
decreaseLimitOrder→InvalidOrderPhase。改用settleLimitOrder然后closeLimitOrder。 - 在传递
enableDynamicFee: true时忘记dynamicFeeConfigId→CreateCustomizablePool回滚是InvalidDynamicFeeConfigParams。要么关闭动态费用,要么从/main/clmm-dynamic-config选择一个配置。
后续步骤
sdk-api/typescript-sdk— 完整 SDK 表面。sdk-api/rest-api— 报价和池元数据端点。user-flows/create-clmm-pool— 非代码演练。integration-guides/aggregator— 将 CLMM 作为路径的一部分进行路由。

