本頁內容由 AI 自動翻譯,所有內容以英文版本為準。查看英文版 →
設定
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
OpenPosition* 會自行配置缺少的 tick array,費用由付款者負擔。
增加現有部位的流動性
來源:src/clmm/increaseLiquidity.ts
減少流動性(並同時領取手續費)
來源:src/clmm/decreaseLiquidity.ts 與 src/clmm/closePosition.ts
liquidity = new BN(0) 呼叫 decreaseLiquidity。此指令的副作用是結算 token_fees_owed_{0,1} 與 reward_amount_owed,並將其轉出。這是領取這兩者的唯一方式。
若要在將流動性歸零並領取手續費後完整關閉部位,請在最後一次 decreaseLiquidity 呼叫中傳入 ownerInfo: { closePosition: true }。SDK 會附加 ClosePosition 並銷毀 NFT。
若直接使用 Anchor 客戶端,請保持宣告的帳戶不變,並附加池帳戶:
poolId。CLMM 只會在 positionNftAccount 處於凍結狀態時讀取它,因此同一套客戶端流程可同時相容舊版與新版部位。
領取獎勵
來源:src/clmm/harvestAllRewards.ts
harvestAllRewards 會走訪所傳入的每個池中的每個部位,將用於結算手續費與獎勵的零流動性 DecreaseLiquidity 呼叫(以及任何 UpdateRewardInfos)加以批次處理,並在需要時拆分到多筆交易中。
兌換
來源:src/clmm/swap.ts
這段範例對應 src/clmm/swap.ts,它使用 swapInternal 進行模擬,而不是 PoolUtils.computeAmountOutFormat。
amountCalculated),以及此次兌換會實際存取的完整帳戶清單(accounts)。
請務必傳入模擬結果回傳的 remainingAccounts:數量不足時,兌換會在走訪途中以 NotEnoughTickArrayAccount 回滾;若帳戶過期,則只會浪費運算資源。
PoolUtils.computeAmountOutFormat 仍然存在,但它需要一個 ComputeClmmPoolInfo(即 getPoolInfoFromRpc 回傳的 computePoolInfo,而非 API 的池物件),另外還需要兩個必填參數,即 tickarrayBitmapExtension 和 blockTimestamp。此外,也沒有 raydium.clmm.fetchTickArrays 方法(fetchTickArrays 是獨立函式;模組層級的輔助函式為 PoolUtils.fetchMultiplePoolTickArrays,以及 getPoolInfoFromRpc 回傳的 tickData / tickArrays)。建立可自訂的 CLMM 池
createCustomizablePool 是在建立池子時,提供動態手續費與單邊手續費切換功能的進入點。它的參數結構與 createPool 相同,但額外多了兩個參數:
createPool 仍可正常運作。只要需要上述任一功能,就改用 createCustomizablePool。鏈上帳戶清單請參閱 products/clmm/instructions。
限價單
限價單會將使用者的輸入資產掛在單一 tick 上,當兌換跨越該 tick 時,依先進先出(FIFO)順序成交。成交後的輸出資產會在結算時直接轉入擁有者的 ATA,擁有者不需要保持在線上即可成交。開啟限價單
目前沒有每個池子專屬的限價單設定帳戶,也沒有getClmmLimitOrderConfigs() 輔助函式。訂單是以 tick 作為索引鍵。
(owner, nonce PDA, order nonce) 推導出 LimitOrderState PDA,遞增每個錢包的 LimitOrderNonce,並將該訂單插入此 tick 的 FIFO 佇列中。
增加/減少未成交的訂單
decreaseLimitOrder 只能從訂單中尚未成交的部分移除資產;已成交的部分會被鎖定,直到結算為止。若訂單已全部成交,這兩個指令都會以 InvalidOrderPhase 回滾。
結算已成交的訂單
settleLimitOrder 會比對訂單的 unfilled_ratio_x64 與 cohort 追蹤器,計算已成交的輸出金額,並將其轉入擁有者的 ATA。擁有者可以自行呼叫此指令;limit_order_admin(鏈下的營運 keeper)也可以代表擁有者呼叫,但輸出資產仍會轉給擁有者。
若要關閉已完全結算的訂單以回收租金,可使用 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 的 remaining-account 順序如下:
常見陷阱
- 刻度端點未對齊間距 →
TickAndSpacingNotMatch。請務必透過TickUtil.getPriceAndTick進行對齊(注意是單數TickUtil)。 SwapV2中提供的 tick array 數量不足 →NotEnoughTickArrayAccount。請從swapInternal(...).accounts取得清單。- 全範圍部位未附帶 bitmap extension → extension PDA 必須為可寫入狀態;SDK 會自動處理此項。
- 把
sqrt_price_x64誤當成price→ 這裡的 2 倍因子混淆特別容易造成困擾。若有疑慮,請讓 SDK 從可讀的價格換算出該值。 - 過於頻繁地領取獎勵 → 每次領取都是一筆零流動性的
DecreaseLiquidity,且會佔用一筆交易。請透過harvestAllRewards批次處理多個部位,並注意其execute需要傳入{ sequentially: true }。 - 自行關閉 NFT 帳戶 →
ClosePosition會銷毀 NFT 並關閉其 ATA。若為 Token-2022 NFT mint,它也會一併關閉;若為傳統 SPL Token mint,則因該程式無法關閉 mint,該 mint 會保留且供應量為零。請勿另外關閉受支援的帳戶,否則指令將會回滾。 - 在非間距對齊的 tick 上開立限價單 →
TickAndSpacingNotMatch。請務必使用匯出的getOrderTick輔助函式進行對齊。 - 對已完全成交的訂單呼叫
decreaseLimitOrder→InvalidOrderPhase。請改用settleLimitOrder,接著closeLimitOrder。 - 以為存在
enableDynamicFee旗標 → 實際上並沒有此旗標。若省略dynamicFeeConfig,系統會靜默地建立一個固定費率的池,且不會報錯。若要使用動態費率,請傳入設定帳戶的PublicKey,該帳戶可從/zh-Hant/main/clmm-dynamic-config取得。
下一步
sdk-api/typescript-sdk— 完整的 SDK 介面。sdk-api/rest-api— 報價與池元資料端點。user-flows/create-clmm-pool— 非程式碼的操作導覽。integration-guides/aggregator— 將 CLMM 納入路徑撮合的整合方式。

