Skip to main content
本頁內容由 AI 自動翻譯,所有內容以英文版本為準。查看英文版 →

設定

本頁每個範例都對應 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)。
  • 建立 observation 與 tick_array_bitmap_extension 帳戶。
  • 支付由 ammConfig 定義的建池費用。

在指定區間開立部位

來源:src/clmm/createPosition.ts
SDK 會計算此區間涉及哪些 tick array,並將它們作為帳戶傳入。它不需要附帶任何初始化指令。系統中並不存在 init-tick-array 指令;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。
受限發行者的部位需要相容的關閉建構器。 這些部位的 NFT 代幣帳戶處於凍結狀態。ClosePosition 必須將部位所屬的池 ID 附加為第一個 remaining account,CLMM 才能在銷毀前解凍該帳戶。程式原始碼分支不包含 SDK 變更。在啟用受限發行者部位的建立功能之前,請先確認你的 SDK 版本明確支援凍結狀態下的關閉流程。
若直接使用 Anchor 客戶端,請保持宣告的帳戶不變,並附加池帳戶:
你可以在每次關閉時都傳入 poolId。CLMM 只會在 positionNftAccount 處於凍結狀態時讀取它,因此同一套客戶端流程可同時相容舊版與新版部位。

領取獎勵

來源:src/clmm/harvestAllRewards.ts
harvestAllRewards 會走訪所傳入的每個池中的每個部位,將用於結算手續費與獎勵的零流動性 DecreaseLiquidity 呼叫(以及任何 UpdateRewardInfos)加以批次處理,並在需要時拆分到多筆交易中。

兌換

來源:src/clmm/swap.ts 這段範例對應 src/clmm/swap.ts,它使用 swapInternal 進行模擬,而不是 PoolUtils.computeAmountOutFormat。
模擬流程會在鏈下依照與鏈上程式相同的邏輯走訪 tick map,並回傳輸出金額(amountCalculated),以及此次兌換會實際存取的完整帳戶清單(accounts)。 請務必傳入模擬結果回傳的 remainingAccounts:數量不足時,兌換會在走訪途中以 NotEnoughTickArrayAccount 回滾;若帳戶過期,則只會浪費運算資源。
PoolUtils.computeAmountOutFormat 仍然存在,但它需要一個 ComputeClmmPoolInfo(即 getPoolInfoFromRpc 回傳的 computePoolInfo,而非 API 的池物件),另外還需要兩個必填參數,即 tickarrayBitmapExtension 和 blockTimestamp。此外,也沒有 raydium.clmm.fetchTickArrays 方法(fetchTickArrays 是獨立函式;模組層級的輔助函式為 PoolUtils.fetchMultiplePoolTickArrays,以及 getPoolInfoFromRpc 回傳的 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,擁有者不需要保持在線上即可成交。

開啟限價單

目前沒有每個池子專屬的限價單設定帳戶,也沒有 getClmmLimitOrderConfigs() 輔助函式。訂單是以 tick 作為索引鍵。
SDK 會根據 (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 順序如下:
若兌換過程永遠不需要 extension,可以省略它;否則它會是第一個 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 取得。

下一步

資料來源: