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 →
Trang này kết hợp với
products/clmm/accounts (các tài khoản là gì) và products/clmm/math (toán học là gì). Nó là tài liệu chính thức cho các đối số và thứ tự tài khoản; bố cục byte cụ thể đến từ IDL.Nâng cấp chương trình 2026-09 đã xây dựng lại CLMM trên Anchor 1.0.2 / Solana 3.1.10, thêm lệnh admin CollectExcessLamports, và thay đổi những gì CreateAmmConfig ghi vào owner / fund_owner. Không có lệnh nào hướng tới người dùng thay đổi tài khoản, đối số hoặc toán học của nó. Xem mục nhập nhật ký 2026-09-30.Danh sách lệnh
Không có lệnh init-tick-array, và không cần thiết. Một tick array được tạo bên trong
OpenPosition* / IncreaseLiquidity* bởi TickArrayState::get_or_create_tick_array, được trả tiền bởi
payer. Truyền PDA tick-array (có thể vẫn chưa được khởi tạo, do hệ thống sở hữu) làm
tick_array_lower / tick_array_upper và chương trình phân bổ nó nếu nó bị thiếu.
OpenLimitOrder làm tương tự cho tick_array duy nhất của nó.CreateAmmConfig, UpdateAmmConfig, UpdatePoolStatus, CreateOperationAccount, UpdateOperationAccount, CloseProtocolPosition) được kiểm soát bởi khóa admin được mã hóa cứng của chương trình. CreatePermissionPda / ClosePermissionPda chấp nhận khóa admin hoặc khóa permission_pda_admin chuyên dụng; CreateSupportMintAssociated / CloseSupportMintAssociated chấp nhận khóa admin hoặc khóa chủ sở hữu mint hỗ trợ chuyên dụng; CollectExcessLamports chấp nhận khóa admin hoặc ví thu thập lamport chuyên dụng. Các lệnh admin luồng phần thưởng (TransferRewardOwner, CollectRemainingRewards) được kiểm soát bởi người tài trợ phần thưởng, không phải admin chương trình.
Hậu tố V2 có nghĩa là “hỗ trợ Token-2022 trên vault / NFT, yêu cầu khe bitmap-extension”. SDK chọn V2 theo mặc định cho các pool mới.
CreatePool
Đối số
Điều kiện tiên quyết
token_mint_0 < token_mint_1theo thứ tự byte.amm_config.disable_create_pool == false.- Các mint không bị từ chối bởi danh sách cho phép phần mở rộng Token-2022.
pool_state.sqrt_price_x64 = sqrt_price_x64,tick_current = floor(log_{1.0001}(price)).pool_state.liquidity = 0(chưa có vị trí).pool_state.fee_on = FromInput(mặc định kế thừa).pool_state.dynamic_fee_infođược đặt thành 0 (phí động bị vô hiệu hóa).
CreateCustomizablePool
Được khuyến nghị cho các pool mới. Cùng hiệu ứng với CreatePool cộng với chế độ thu thập phí trên mỗi pool và tùy chọn phí động tùy chọn.
Đối số
CreatePool. dynamic_fee_config không phải là một tài khoản được khai báo.
Điều kiện tiên quyết — giống như CreatePool. Nếu enable_dynamic_fee = false, không cần remaining_account và bất kỳ cái nào được truyền chỉ được quét để tìm các bản ghi mint hỗ trợ.
Điều kiện sau
pool_state.fee_onđược đặt thành biến thểCollectFeeOnđược chọn.- Nếu phí động được bật:
pool_state.dynamic_fee_infođược khởi tạo từDynamicFeeConfigđược cung cấp (năm tham số hiệu chỉnh được sao chép; các trường trạng thái được đặt thành 0). - Nếu không:
pool_state.dynamic_fee_infođược đặt thành 0 (= phí động không hoạt động mãi mãi cho pool này).
fee_on và bit bật phí động được đặt chỉ khi tạo pool. Không có nâng cấp tại chỗ — các pool được tạo qua CreatePool kế thừa không thể có được phí động hoặc phí một chiều một cách hồi tưởng. Các triển khai mới nên mặc định cho lệnh này.
CreatePermissionedPool
Cả CreatePool và CreateCustomizablePool đều lấy PDA pool từ ["pool", amm_config, token_mint_0, token_mint_1], vì vậy có chính xác một địa chỉ pool chính tắc cho mỗi bộ ba (config, mint0, mint1) — một init thứ hai ở cùng seed sẽ thất bại. CreatePermissionedPool nâng cao hạn chế đó bằng cách gấp seed_index: u16 do khách hàng cung cấp vào seed PDA pool, cho phép nhiều pool cho cùng một cặp và tầng phí — mỗi cái ở địa chỉ riêng của nó. Vì một địa chỉ pool tùy ý là một khả năng có đặc quyền, người trả phí phải giữ một PDA Permission cho phép nó.
Mọi thứ khác về pool là giống hệt với CreateCustomizablePool: nó lấy cùng CreateCustomizableParams và hỗ trợ phí một chiều và tùy chọn phí động.
Đối số
CreateCustomizablePool cộng với, ở phía trước:
PDA
pool_state được lấy từ ["pool", amm_config, token_mint_0, token_mint_1, seed_index.to_le_bytes()].
Điều kiện tiên quyết
seed_index != 0. Mộtseed_indexcủa0được dành riêng cho các pool kế thừa và bị từ chối ở đây; thành phần seed[0, 0]là những gì làm cho địa chỉ pool kế thừa sụp đổ thành dạng bốn seed cổ điển.- PDA
permissionchopayertồn tại (được tạo bởi admin quaCreatePermissionPda). - Các quy tắc mint / danh sách cho phép giống như
CreatePool.
- Một
pool_statemới tồn tại ở địa chỉ được lấy từseed_index, vớipool_state.seed_index = seed_index. - Tất cả các trạng thái sau khác khớp với
CreateCustomizablePool(chế độ phí, phí động tùy chọn).
Lệnh này không mở rộng quyền truy cập tạo pool chung — tạo không cần phép tiếp tục thông qua
CreatePool / CreateCustomizablePool, vẫn là một pool trên mỗi cặp. CreatePermissionedPool tồn tại cho trường hợp cụ thể khi một nhà khai thác được liệt kê trắng danh cần nhiều pool cho cùng một cặp (ví dụ: giá ban đầu khác nhau hoặc nhóm khởi chạy) và giữ một PDA Permission được cấp bởi admin.OpenPositionV2 / OpenPositionWithToken22Nft
Tạo một vị trí mới bên trong một pool hiện có.
Đối số
OpenPositionV2 khai báo 22; OpenPositionWithToken22Nft khai báo 20.
OpenPositionV2, theo thứ tự:
OpenPositionWithToken22Nft là cùng danh sách với metadata_account (5) và metadata_program (19) bị loại bỏ — nó ghi siêu dữ liệu vị trí của nó thông qua phần mở rộng siêu dữ liệu Token-2022 trên mint NFT thay thế — cho 20 tài khoản. position_nft_mint của nó là một Signer trần và position_nft_account là một UncheckedAccount.
Toán học — xem products/clmm/math. Cho base_flag, chương trình giải quyết liquidity hoặc (amount_0_max, amount_1_max) thành L thực tế và số tiền token thực tế được tiêu thụ.
Điều kiện tiên quyết
tick_lower < tick_upper, cả hai bội số củapool.tick_spacing, trong[MIN_TICK, MAX_TICK].- Hai PDA tick-array được truyền. Chúng không cần phải tồn tại —
get_or_create_tick_arrayphân bổ một cái bị thiếu ở chi phí củapayerbên trong lệnh này. Không có lệnh init-tick-array riêng biệt. - Người dùng có ít nhất
amount_0_maxvàamount_1_maxtrong các ATA nguồn.
personal_positiontồn tại,liquidityđược đặt,fee_growth_inside_lastđược chụp.- Các mục tick-array ở
tick_lowervàtick_upperđược cập nhật (liquidity_gross += L,liquidity_net ± L, ảnh chụp tăng trưởng phí được duy trì). pool_state.liquidity += Lnếu vị trí nằm trong phạm vi (tick_lower ≤ tick_current < tick_upper).- Mint NFT vị trí ghi lại
pool_statelàm cơ quan đóng băng. Cơ quan mint được loại bỏ sau khi NFT duy nhất được mint. Ghi lại cơ quan đóng băng không thay đổi trạng thái của tài khoản token NFT. - Tài khoản token NFT vẫn không bị đóng băng trừ khi lệnh là
OpenPositionV2hoặcOpenPositionWithToken22Nftvà cơ quan phát hành hạn chế của mint vault bất kỳ khớp với danh sách. Chỉ đường dẫn V2 khớp đó mới đóng băng tài khoản.OpenPositionV1 không đóng băng.
TickInvalidOrder (tick_lower >= tick_upper), TickAndSpacingNotMatch (một điểm cuối không phải là bội số của tick_spacing), InvalidTickIndex (ngoài [MIN_TICK, MAX_TICK]), MissingTickArrayBitmapExtensionAccount (phạm vi ngoài bitmap nội tuyến và phần mở rộng không được nối), NotApproved (pool_state.status chặn mở), ZeroAmountSpecified.
Đóng băng vị trí không thêm tài khoản lệnh được khai báo hoặc đối số. Khách hàng có thể mở các vị trí này với bố cục V2 hiện có. Hành vi được chọn trên chuỗi từ
vault_0_mint và vault_1_mint.IncreaseLiquidityV2
Thêm thanh khoản vào một vị trí đã mở.
Đối số
OpenPosition: không có rent, không có system_program, không có associated_token_program và không có tài khoản siêu dữ liệu.
Thêm PDA
TickArrayBitmapExtension ở phía trước làm remaining_accounts[0] khi phạm vi vị trí nằm ngoài bitmap nội tuyến.
Hiệu ứng
- Chuyển
amount_0_actual/amount_1_actualtừ người dùng → vault. - Tăng
personal_position.liquidityvàpool_state.liquidity(nếu nằm trong phạm vi), vàliquidity_gross/liquidity_nettick điểm cuối tương ứng. - Thu thập phí và phần thưởng nợ kể từ lần chạm cuối cùng và ghi có chúng vào
token_fees_owed_{0,1}/reward_amount_owed. Những cái đó chỉ được trả ra trênDecreaseLiquidity/DecreaseLiquidityV2, không phải trên tăng — không có lệnh thu thập độc lập.
DecreaseLiquidityV2
Loại bỏ thanh khoản từ một vị trí.
Đối số
IncreaseLiquidityV2: personal_position và pool_state được hoán đổi, các vault đi trước tick array, các tài khoản phía người dùng được đặt tên recipient_token_account_*, và có một memo_program bổ sung.
Tài khoản còn lại — ba cho mỗi phần thưởng hoạt động được thu thập, theo thứ tự
reward_token_vault(W), recipient_token_account(W), reward_vault_mint. Thêm PDA TickArrayBitmapExtension ở phía trước khi phạm vi vị trí nằm ngoài bitmap nội tuyến.
Đây cũng là cách duy nhất để thu thập phí và phần thưởng. Để thu thập mà không thay đổi
vị trí, gọi nó với
liquidity = 0, amount_0_min = 0, amount_1_min = 0.- Tính toán
(amount_0, amount_1)choLđược loại bỏ chosqrt_price_x64hiện tại. - Giải quyết phí/phần thưởng tích lũy kể từ lần chạm cuối cùng, giống như
IncreaseLiquidity. - Chuyển
amount_0 + fees_owed_0vàamount_1 + fees_owed_1ra khỏi vault cho người dùng. - Giảm bộ đếm thanh khoản; nếu
personal_position.liquiditymới== 0, vị trí đủ điều kiện choClosePosition.
amount_0_min và amount_1_min là mức tối thiểu mà người dùng chấp nhận sau khi trừ phí chuyển Token-2022 ở phía đầu ra.
ClosePosition
Đốt NFT vị trí và đóng PersonalPositionState.
Tài khoản được khai báo
Tài khoản còn lại
- NFT không bị đóng băng: không cần; một tài khoản pool bổ sung là vô hại vì trình xử lý không đọc nó.
- NFT bị đóng băng: nối
personal_position.pool_idlàm tài khoản còn lại đầu tiên. Chương trình tải nó làmPoolStatevà sử dụng seed PDA của nó để ký rã đông.
personal_position.liquidity == 0.tokens_fees_owed_{0,1} == 0.- Tất cả bộ đếm phần thưởng
reward_amount_owed == 0.
- Nếu tài khoản token NFT bị đóng băng, xác minh tài khoản còn lại đầu tiên bằng
personal_position.pool_id, sau đó rã đông nó với pool PDA. - Đốt NFT.
- Đóng tài khoản token NFT và
personal_position, hoàn lại tiền thuê nhà chonft_owner. Nếu NFT vị trí sử dụng Token-2022, nó cũng đóng mint NFT; mint SPL Token cổ điển không thể đóng và vẫn có cung cấp 0.
AccountLack khi đóng một vị trí bị đóng băng. Truyền pool cho mỗi lần đóng là chiến lược tương thích đơn giản nhất.
SwapV2
Đi bộ dọc theo đường cong thanh khoản; đầu vào chính xác hoặc đầu ra chính xác tùy thuộc vào is_base_input.
Đối số
Người gọi truyền một danh sách tick array được xếp hạng bao trùm bước đi swap dự kiến; chương trình sử dụng bao nhiêu nó cần. SDK tính toán danh sách này qua
PoolUtils.computeAmountOutFormat hoặc điểm cuối trích dẫn của API.
Điều kiện tiên quyết
pool_state.statuscho phép swap.now >= open_time.sqrt_price_limit_x64nằm ở phía chính xác củasqrt_price_x64cho hướng.
TooLittleOutputReceived (trượt giá chính xác-in), TooMuchInputPaid (trượt giá chính xác-out), SqrtPriceLimitOverflow, NotEnoughTickArrayAccount, InvalidFirstTickArrayAccount, MissingTickArrayBitmapExtensionAccount, LiquidityInsufficient, NotApproved (bit swap được đặt trên pool_state.status). CLMM không có biến thể ExceededSlippage — tên đó là của CPMM — và không có TickArrayNotFound.
Những gì SwapV2 làm bên trong mà người gọi nên biết (phát hành sau 2025):
- Phụ phí phí động — nếu
pool.dynamic_fee_infokhác 0, chương trình cập nhật bộ tích lũy biến động bằng cách sử dụng khoảng cách tick được duyệt kể từ swap cuối cùng (với các quy tắc bộ lọc/phân rã từproducts/clmm/fees) và thêmdynamic_fee_componenttrênAmmConfig.trade_fee_rate. Tổng phí được giới hạn ở 10% (MAX_FEE_RATE_NUMERATOR / 1_000_000). - Khớp lệnh giới hạn — khi bước đi giá vượt qua một tick giữ các lệnh giới hạn mở, chương trình trước tiên điền thanh khoản lệnh giới hạn có sẵn ở tick đó (FIFO theo
order_phase), sau đó tiếp tục dọc theo đường cong thanh khoản LP. Các số tiền đã điền cập nhậttick.unfilled_ratio_x64vàtick.part_filled_orders_remainingđể giải quyết sau; các lệnh chính nó vẫn chưa được chi tiêu cho đến khi chủ sở hữu của chúng gọiSettleLimitOrder. - Định tuyến phí một chiều — khi
pool.fee_on = Token0OnlyhoặcToken1Only, bước swap vẫn tính toán cùng một giao dịch đầu vào-đầu ra; phí sau đó được định tuyến đến phía được cấu hình. Đối với các hướng mà phía phí được cấu hình là đầu ra, phí được khấu trừ từ đầu ra swap (người dùng nhậnout − fee); đối với các hướng mà nó là đầu vào, hành vi khớp vớiFromInput. Xemis_fee_on_input(zero_for_one)vàis_fee_on_token0(zero_for_one)trênPoolState.
Swap (V1) thực hiện cùng phí động, định tuyến phí một chiều và khớp lệnh giới hạn như SwapV2; tính năng duy nhất nó thiếu là hỗ trợ Token-2022 — cả hai vault phải là SPL Token cổ điển. Các pool có bất kỳ mint Token-2022 nào phải được swap qua SwapV2. Bộ tập hợp và SDK đã ưu tiên V2 cho mỗi chân CLMM vì vậy người gọi không phải phân nhánh trên loại mint.
OpenLimitOrder
Đặt một lệnh bán ở một tick cụ thể. Lệnh nằm trong một nhóm FIFO trên mỗi tick và điền khi giá vượt qua.
Đối số
Tài khoản còn lại —
[0] tick_array_bitmap_extension, chỉ bắt buộc khi khởi tạo một tick array có chỉ mục bắt đầu nằm ngoài bitmap nội tuyến của pool. Không truyền gì nếu không.
Thay đổi danh sách tài khoản (phát hành 2026-07).
OpenLimitOrder hiện cũng lấy các tài khoản phía đầu ra — output_token_account, output_vault và output_vault_mint — ngoài phía đầu vào. Chúng chỉ được sử dụng để xác thực: chương trình từ chối lệnh nếu tài khoản token đầu vào hoặc đầu ra của chủ sở hữu bị đóng băng. Điều này đảm bảo rằng một điền có thể thực sự được giải quyết cho ATA đầu ra của chủ sở hữu, điều này quan trọng đối với các mint Token-2022 được cho phép / đóng băng mặc định (ví dụ: token được phép) nơi một tài khoản có thể chưa được rã đông. Khách hàng được xây dựng dựa trên danh sách tài khoản một chiều cũ phải thêm ba tài khoản đầu ra.- Cả
input_token_accountvàoutput_token_accountđều không bị đóng băng (nếu khôngNotApproved). pool_state.statuscho phép cả hoạt động swap (bit 4) và lệnh giới hạn (bit 5) (nếu khôngNotApproved).tick_index % pool.tick_spacing == 0và trong[MIN_TICK, MAX_TICK].tick_indexnằm ở phía bên phải củapool.tick_currentcho hướng được chọn (bán token0 → tick phải ở trên hiện tại, và ngược lại). Bán ở một tick đã vượt qua sẽ được khớp ngay lập tức và bị từ chối.
limit_ordertồn tại, chụptick.order_phasevàtick.unfilled_ratio_x64tại thời gian mở.tick.orders_amount += amount(trong nhóm hiện tại).limit_order_nonce.order_nonce += 1.OpenLimitOrderEventđược phát hành.
NotApproved (tài khoản token đầu vào hoặc đầu ra bị đóng băng, hoặc pool có swap / lệnh giới hạn bị vô hiệu hóa), ZeroAmountSpecified (amount == 0 sau phí chuyển phía đầu vào), InvalidLimitOrderAmount (số tiền sẽ tạo ra đầu ra dưới 1 đơn vị cơ sở ở tick đó, hoặc tràn u64), InvalidTickIndex (ngoài [MIN_TICK, MAX_TICK], hoặc ở phía sai của tick_current cho hướng được chọn), TickAndSpacingNotMatch (tick_index % pool.tick_spacing != 0), OrderPhaseSaturated.
IncreaseLimitOrder
Thêm vào một lệnh mở hiện có. Chỉ có thể gọi bởi owner của lệnh.
Đối số
system_program.
Điều kiện tiên quyết
limit_order.owner == signer.- Lệnh vẫn nằm trong cùng một nhóm (
tick.order_phase == limit_order.order_phase). Nếu nhóm đã bắt đầu điền, lệnh được giải quyết một phần — người gọi nên gọiDecreaseLimitOrderhoặcSettleLimitOrdertrước để cuộn về phía trước.
- Chuyển
amounttừ ATA chủ sở hữu đếninput_vault. limit_order.total_amount += amount;tick.orders_amount += amount.
DecreaseLimitOrder
Giảm hoặc hủy hoàn toàn một lệnh mở. Trả lại phần còn lại chưa điền cho chủ sở hữu, cộng với bất kỳ đầu ra nào đã được giải quyết bởi các điền một phần trong quá khứ.
Đối số
Hiệu ứng
- Tính toán lại số tiền đã điền của lệnh từ
unfilled_ratio_x64của nhóm kể từ khi mở. - Gửi đầu ra đã điền đến
output_token_account. - Gửi
amountcủa đầu vào chưa điền quay lạiinput_token_account. - Cập nhật
limit_ordertương ứng. Nếu phần còn lại chưa điền mới bằng 0, chương trình đóng tài khoản và hoàn lại tiền thuê nhà choowner.
SettleLimitOrder
Đẩy các token đầu ra đã điền cho chủ sở hữu mà không thay đổi phần còn lại chưa điền của lệnh. Hữu ích khi các người giữ auto_withdraw muốn drip-pay các điền một phần chạy dài.
Người gọi — hoặc owner của lệnh, hoặc limit_order_admin của chương trình (một ví nóng hoạt động ngoài chuỗi chạy một vòng lặp người giữ tự động). Người giữ không có cơ quan khác — nó không thể di chuyển quỹ của người dùng ngoài việc đẩy đầu ra đã điền đến ATA owner.
Tài khoản
Hiệu ứng
- Tính toán đầu ra tích lũy nợ bằng cách sử dụng
(limit_order.unfilled_ratio_x64, tick.unfilled_ratio_x64). - Chuyển delta

