Skip to main content
本頁內容由 AI 自動翻譯,所有內容以英文版本為準。查看英文版 →
版本說明。 所有 TypeScript 示例針對 @raydium-io/raydium-sdk-v2@0.2.64-alpha;最後執行於 0.2.42-alpha(2026-04),並於 2026-09-09 針對 Solana mainnet-beta 重新檢查了 0.2.64-alpha 原始碼中的呼叫簽名。末尾的 Rust CPI 骨架針對 master 分支上的 raydium-clmm,其中 Anchor 版本為 =0.32.1不是 CPMM 頁面使用的 1.0.2;兩者無法共存於一個 crate 中。程式 ID 來自 reference/program-addresses 透過 SDK。

設定

本頁的每個示例都對應 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 陣列,並將其作為帳戶傳遞。它不需要捆綁任何初始化指令 — 沒有初始化 tick 陣列指令;OpenPosition* 會自行分配缺失的 tick 陣列,費用由支付者承擔。

增加現有部位的流動性

原始碼:src/clmm/increaseLiquidity.ts

減少流動性(同時收取費用)

原始碼:src/clmm/decreaseLiquidity.tssrc/clmm/closePosition.ts
若要僅收取費用和獎勵,使用 liquidity = new BN(0) 呼叫 decreaseLiquidity。指令的副作用是結算 token_fees_owed_{0,1}reward_amount_owed 並將其轉出 — 這是收取任一者的唯一方式。 若要在清零流動性和費用後完全關閉部位,在最後的 decreaseLiquidity 呼叫上傳遞 ownerInfo: { closePosition: true }。SDK 會附加 ClosePosition 並燒毀 NFT。
受限發行人部位需要相容的關閉建構器。 這些部位有凍結的 NFT 代幣帳戶。ClosePosition 必須將部位的流動性池 ID 附加為第一個剩餘帳戶,以便 CLMM 可以在燒毀前解凍帳戶。程式原始碼分支不包括 SDK 變更。在啟用受限發行人部位建立之前,請確認你的 SDK 版本明確支援凍結關閉路徑。
對於直接 Anchor 用戶端,保持宣告的帳戶不變並附加流動性池:
你可以在每次關閉時傳遞 poolId。CLMM 只在 positionNftAccount 凍結時讀取它,這使一個用戶端路徑與舊部位和新部位相容。

收取獎勵

原始碼:src/clmm/harvestAllRewards.ts
harvestAllRewards 遍歷傳入的每個流動性池上的每個部位,批次處理結算費用和獎勵的零流動性 DecreaseLiquidity 呼叫(加上任何 UpdateRewardInfos),並在需要時將其分散到多個交易中。

交換

原始碼:src/clmm/swap.ts
模擬使用與鏈上程式相同的邏輯離線遍歷 tick 地圖,並傳回輸出量(amountCalculated)加上交換將涉及的確切帳戶列表(accounts)。 始終傳遞模擬傳回的 remainingAccounts:太少會導致交換在遍歷中途以 NotEnoughTickArrayAccount 回復;過時的只會浪費計算。
PoolUtils.computeAmountOutFormat 仍然存在,但它需要 ComputeClmmPoolInfo(來自 getPoolInfoFromRpccomputePoolInfo,不是 API 流動性池物件)加上另外兩個必需的引數 — tickarrayBitmapExtensionblockTimestamp — 並且沒有 raydium.clmm.fetchTickArrays 方法(fetchTickArrays 是自由函式;模組級別的輔助程式是 PoolUtils.fetchMultiplePoolTickArraysgetPoolInfoFromRpc 傳回的 tickData / tickArrays)。

建立可自訂的 CLMM 流動性池

createCustomizablePool 是入口點,在流動性池建立時公開動態費用和單邊費用切換。它採用 createPool 的形狀加上兩個新增項:
沒有 enableDynamicFee 和沒有 dynamicFeeConfigId 參數,也沒有 startTime提供 dynamicFeeConfig 就是啟用動態費用的方式 — 省略它,你會得到靜態費用流動性池,沒有錯誤。另請注意,SDK 列舉成員是 TokenOnlyA / TokenOnlyB,而鏈上 Rust 列舉拼寫為 Token0Only / Token1Only;數值相符(FromInput = 0)。
createPool 繼續用於預設費用、無動態費用路徑。每當你需要任一旋鈕時,使用 createCustomizablePool。見 products/clmm/instructions 以了解鏈上帳戶列表。

限價單

限價單在單個 tick 處停泊使用者輸入,當交換穿過該 tick 時按 FIFO 方式成交。輸出在結算時推送到所有者的 ATA;所有者不需要在線即可成交。

開設限價單

SDK 從 (owner, nonce PDA, order nonce) 推導 LimitOrderState PDA,碰撞每個錢包的 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 端點TickAndSpacingNotMatch。始終透過 TickUtil.getPriceAndTick(單數 TickUtil)對齊。
  • SwapV2 中提供的 tick 陣列不足NotEnoughTickArrayAccount。取得 swapInternal(...).accounts 傳回的列表。
  • 沒有位圖擴展的全範圍部位 → 擴展 PDA 必須可寫;SDK 會自動處理此問題。
  • sqrt_price_x64 誤認為 price → 這裡的因子 2 混淆特別痛苦。如有疑問,讓 SDK 從人類可讀的價格計算它。
  • 過於急切地收取獎勵 → 每次收取都是零流動性 DecreaseLiquidity,成本為一個交易。透過 harvestAllRewards 跨許多部位進行批次處理,並記住其 execute 需要 { sequentially: true }
  • 自己關閉 NFT 帳戶ClosePosition 燒毀 NFT 並關閉其 ATA。它也關閉 Token-2022 NFT 鑄幣;經典 SPL Token 鑄幣保持供應量為零,因為該程式無法關閉鑄幣。不要單獨關閉支援的帳戶,否則指令將回復。
  • 在非間距 tick 開設限價單TickAndSpacingNotMatch。始終透過匯出的 getOrderTick 輔助程式進行量化。
  • 在完全成交的訂單上呼叫 decreaseLimitOrderInvalidOrderPhase。改用 settleLimitOrder 然後 closeLimitOrder
  • 期望 enableDynamicFee 旗標 → 沒有。省略 dynamicFeeConfig 只是建立靜態費用流動性池,無聲且無錯誤。如果你想要動態費用,傳遞從 /main/clmm-dynamic-config 選擇的配置帳戶的 PublicKey

後續步驟

來源: