Trang này được dịch tự động bằng AI. Phiên bản tiếng Anh là bản chính thức.Xem bản tiếng Anh →
Thiết lập
raydium-sdk-V2-demo/src/clmm; liên kết GitHub nằm ngay cạnh mỗi phần. Phần khởi tạo theo tệp config.ts.template của demo repo (nguồn). Với mọi tích hợp không đơn giản, nên đặt disableFeatureCheck: true:
Tạo pool CLMM
Nguồn:src/clmm/createPool.ts
- Sắp xếp
mint1/mint2theo thứ tự byte trước khi suy ra địa chỉ. - Tính
sqrt_price_x64 = floor(sqrt(initialPrice × 10^(dB−dA)) × 2^64). - Tạo các tài khoản
observationvàtick_array_bitmap_extension. - Thanh toán phí tạo pool được quy định bởi
ammConfig.
Mở position trong khoảng giá đã chọn
Nguồn:src/clmm/createPosition.ts
OpenPosition* tự cấp phát tick array còn thiếu, với chi phí do payer chi trả.
Tăng thanh khoản cho position hiện có
Nguồn:src/clmm/increaseLiquidity.ts
Giảm thanh khoản (đồng thời thu phí)
Nguồn:src/clmm/decreaseLiquidity.ts và src/clmm/closePosition.ts
decreaseLiquidity với liquidity = new BN(0). Tác dụng phụ của lệnh này là quyết toán token_fees_owed_{0,1} và reward_amount_owed, rồi chuyển chúng ra khỏi pool. Đây là cách duy nhất để thu một trong hai khoản này.
Để đóng position hoàn toàn sau khi đưa thanh khoản và phí về 0, truyền ownerInfo: { closePosition: true } ở lệnh decreaseLiquidity cuối cùng. SDK sẽ thêm ClosePosition và đốt NFT.
Với client Anchor gọi trực tiếp, giữ nguyên các tài khoản đã khai báo và thêm pool vào:
poolId ở mọi lần đóng. CLMM chỉ đọc giá trị này khi positionNftAccount bị đóng băng, nhờ đó một đường dẫn client duy nhất vẫn tương thích với cả position cũ và position mới.
Thu phần thưởng
Nguồn:src/clmm/harvestAllRewards.ts
harvestAllRewards duyệt mọi position trên mọi pool được truyền vào, gom các lệnh DecreaseLiquidity có thanh khoản bằng 0 dùng để quyết toán phí và phần thưởng (cùng mọi UpdateRewardInfos nếu có), rồi chia chúng sang nhiều giao dịch khi cần.
Swap
Nguồn:src/clmm/swap.ts
Ví dụ này bám theo src/clmm/swap.ts, nhưng mô phỏng bằng swapInternal thay vì PoolUtils.computeAmountOutFormat.
amountCalculated) cùng danh sách tài khoản chính xác mà lệnh swap sẽ truy cập (accounts).
Luôn truyền remainingAccounts mà bước mô phỏng trả về: nếu thiếu, swap sẽ bị revert giữa chừng với lỗi NotEnoughTickArrayAccount; nếu thừa hoặc đã cũ thì chỉ lãng phí compute.
PoolUtils.computeAmountOutFormat vẫn tồn tại, nhưng nó cần một ComputeClmmPoolInfo (là computePoolInfo lấy từ getPoolInfoFromRpc, không phải đối tượng pool từ API) và thêm hai tham số bắt buộc là tickarrayBitmapExtension và blockTimestamp. Ngoài ra, không tồn tại phương thức raydium.clmm.fetchTickArrays (fetchTickArrays là một hàm độc lập; các hàm hỗ trợ ở cấp module là PoolUtils.fetchMultiplePoolTickArrays, cùng với tickData / tickArrays được trả về bởi getPoolInfoFromRpc).Tạo pool CLMM tùy chỉnh được
createCustomizablePool là hàm đầu vào cho phép bật/tắt phí động và phí một phía ngay tại thời điểm tạo pool. Hàm này nhận cùng tham số với createPool, cộng thêm hai tham số bổ sung:
createPool vẫn hoạt động cho trường hợp dùng phí mặc định, không có phí động. Hãy dùng createCustomizablePool khi bạn cần một trong hai tùy chọn trên. Xem products/clmm/instructions để biết danh sách tài khoản on-chain.
Lệnh giới hạn (Limit orders)
Lệnh giới hạn giữ tiền đầu vào của người dùng tại một tick duy nhất và được khớp theo nguyên tắc FIFO khi một lệnh swap vượt qua tick đó. Kết quả được chuyển về ATA của chủ lệnh tại thời điểm quyết toán; chủ lệnh không cần trực tuyến để lệnh được khớp.Mở lệnh giới hạn
Không có tài khoản cấu hình lệnh giới hạn riêng cho từng pool và cũng không có hàm hỗ trợgetClmmLimitOrderConfigs(). Các lệnh được định danh theo tick.
LimitOrderState từ (owner, nonce PDA, order nonce), tăng LimitOrderNonce của từng ví, và đưa lệnh vào nhóm FIFO tại tick đó.
Tăng / giảm một lệnh đang mở
decreaseLimitOrder chỉ có thể rút phần chưa khớp của lệnh; phần đã khớp bị khóa cho đến khi quyết toán. Cả hai lệnh đều revert với InvalidOrderPhase nếu lệnh đã được khớp hoàn toàn.
Quyết toán lệnh đã khớp
settleLimitOrder đọc unfilled_ratio_x64 của lệnh so với bộ theo dõi nhóm, tính toán lượng token đã khớp và chuyển về ATA của chủ lệnh. Chủ lệnh có thể tự gọi hàm này; limit_order_admin (một keeper vận hành ngoài chuỗi) cũng có thể gọi thay chủ lệnh, nhưng kết quả vẫn được chuyển về cho chủ lệnh.
Để đóng các lệnh đã quyết toán hoàn toàn nhằm thu hồi rent, hãy dùng closeLimitOrder (từng lệnh) hoặc closeAllLimitOrder (theo lô). Để quyết toán nhiều lệnh cùng lúc, settleAllLimitOrder sẽ gom càng nhiều lệnh SettleLimitOrder càng tốt vào một giao dịch v0.
Liệt kê các lệnh đang treo của ví (ngoài chuỗi)
totalAmount / filledAmount / pendingSettle giúp phân biệt từng giai đoạn. Để xem lịch sử lệnh đã đóng, hãy dùng /limit-order/history/order/list-by-user?wallet=… (theo từng ví, phân trang bằng nextPageId); để xem toàn bộ nhật ký sự kiện của một lệnh cụ thể, hãy dùng /limit-order/history/event/list-by-pda?pda=….
Khung CPI bằng Rust
SwapV2:
Những lỗi thường gặp
- Tick đầu mút không khớp bước tick (tick spacing) →
TickAndSpacingNotMatch. Luôn căn chỉnh quaTickUtil.getPriceAndTick(dùngTickUtilsố ít). - Không cung cấp đủ tick array trong
SwapV2→NotEnoughTickArrayAccount. Lấy danh sách từswapInternal(...).accounts. - Vị trí full-range nhưng thiếu bitmap extension → PDA của extension phải có quyền ghi; SDK tự xử lý việc này.
- Nhầm
sqrt_price_x64vớiprice→ nhầm lẫn hệ số 2 ở đây đặc biệt khó chịu. Khi không chắc, hãy để SDK tính từ giá dễ đọc cho con người. - Thu phần thưởng quá thường xuyên → mỗi lần thu là một
DecreaseLiquidityvới liquidity bằng không và tốn một giao dịch. Hãy gom nhiều vị thế bằngharvestAllRewards, và nhớ rằngexecutecủa hàm này cần{ sequentially: true }. - Tự đóng tài khoản NFT →
ClosePositionđốt NFT và đóng ATA của nó. Lệnh này cũng đóng mint NFT Token-2022; còn mint SPL Token cổ điển vẫn tồn tại với supply bằng không vì chương trình đó không thể đóng mint. Đừng tự đóng các tài khoản được hỗ trợ riêng, nếu không lệnh sẽ bị revert. - Mở lệnh limit tại tick không nằm trên bước tick →
TickAndSpacingNotMatch. Luôn lượng tử hóa bằng hàm trợ giúpgetOrderTickđược export. - Gọi
decreaseLimitOrdertrên lệnh đã khớp hoàn toàn →InvalidOrderPhase. Thay vào đó, hãy dùngsettleLimitOrderrồicloseLimitOrder. - Kỳ vọng có cờ
enableDynamicFee→ không tồn tại cờ này. Bỏ quadynamicFeeConfigchỉ đơn giản tạo một pool phí cố định, âm thầm và không báo lỗi. Nếu bạn muốn phí động, hãy truyềnPublicKeycủa tài khoản cấu hình, lấy từ/vi/main/clmm-dynamic-config.
Bước tiếp theo
sdk-api/typescript-sdk— toàn bộ giao diện SDK.sdk-api/rest-api— các endpoint báo giá và metadata pool.user-flows/create-clmm-pool— hướng dẫn không dùng code.integration-guides/aggregator— định tuyến CLMM như một phần của đường đi swap.

