Skip to main content
本页内容由 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
SDK 会:
  • 按字节顺序对 mint1/mint2 进行排序后再推导。
  • 计算 sqrt_price_x64 = floor(sqrt(initialPrice × 10^(dB−dA)) × 2^64)
  • 创建 observationtick_array_bitmap_extension 账户。
  • 支付由 ammConfig 定义的池创建费用。

在选定范围内开仓

源代码:src/clmm/createPosition.ts
SDK 会自动计算该范围涉及的 tick 数组,并在任何未初始化的数组上捆绑 InitTickArray 指令。

增加现有仓位的流动性

源代码:src/clmm/increaseLiquidity.ts

减少流动性(同时收取费用)

源代码:src/clmm/decreaseLiquidity.tssrc/clmm/closePosition.ts
仅收取费用,调用 decreaseLiquidity 时设置 liquidity = new BN(0)。该指令的副作用是结算 tokens_fees_owed_{0,1} 并转出它们。 要在流动性和费用都清零后完全关闭仓位,在最后一次 decreaseLiquidity 调用时传递 closePosition: true。SDK 会追加 ClosePosition 并销毁 NFT。
受限发行人仓位需要兼容的关闭构建器。 这些仓位有冻结的 NFT 代币账户。ClosePosition 必须将仓位的池 ID 作为第一个剩余账户追加,以便 CLMM 在销毁前解冻该账户。程序源分支不包含 SDK 更改。在启用受限发行人仓位创建之前,请确认你的 SDK 版本明确支持冻结关闭路径。
对于直接的 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;所有者无需在线即可成交。

开启限价单

SDK 从 (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_x64price → 这里的因子-2 混淆特别痛苦。有疑问时,让 SDK 从人类可读的价格计算。
  • 过于频繁地收取奖励 → 每次收取需要一个交易。通过 harvestAllRewards 跨多个仓位批量处理。
  • 自己关闭 NFT 账户ClosePosition 销毁 NFT 并关闭其 ATA。它也关闭 Token-2022 NFT 铸币;经典 SPL Token 铸币保持供应量为零,因为该程序无法关闭铸币。不要单独关闭支持的账户,否则指令会回滚。
  • 在非对齐 tick 处开启限价单InvalidTickIndex。始终通过 TickUtils.getPriceAndTick 量化。
  • 在完全成交的订单上调用 decreaseLimitOrderInvalidOrderPhase。改用 settleLimitOrder 然后 closeLimitOrder
  • 在传递 enableDynamicFee: true 时忘记 dynamicFeeConfigIdCreateCustomizablePool 回滚是 InvalidDynamicFeeConfigParams。要么关闭动态费用,要么从 /main/clmm-dynamic-config 选择一个配置。

后续步骤

来源: