Skip to main content
이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.영문판 보기 →
이 페이지는 products/clmm/accounts (계정이 무엇인지)와 products/clmm/math (수학이 무엇인지)와 함께 사용됩니다. 인자와 계정 순서에 대해 권위 있는 참조이며, 특정 바이트 레이아웃은 IDL에서 나옵니다.

명령어 목록

대부분의 관리자 전용 명령어 (CreateAmmConfig, UpdateAmmConfig, UpdatePoolStatus, CreateSupportMintAssociated, CreateOperationAccount, UpdateOperationAccount, CloseProtocolPosition)는 프로그램의 하드코딩된 admin 공개 키로 제어됩니다. CreatePermissionPda / ClosePermissionPdaadmin 공개 키 또는 전용 permission_pda_admin 키를 허용합니다. 보상 스트림 관리자 명령어 (TransferRewardOwner, CollectRemainingRewards)는 프로그램 관리자가 아닌 보상 펀더로 제어됩니다. V2 접미사는 “볼트/NFT에서 Token-2022를 지원하며, 비트맵 확장 슬롯이 필요함”을 의미합니다. SDK는 새 풀에 대해 기본적으로 V2를 선택합니다.

CreatePool

인자
계정 (축약) 전제 조건
  • token_mint_0 < token_mint_1 (바이트 순서).
  • amm_config.disable_create_pool == false.
  • 민트는 Token-2022 확장 허용 목록에 의해 거부되지 않습니다.
사후 조건
  • pool_state.sqrt_price_x64 = sqrt_price_x64, tick_current = floor(log_{1.0001}(price)).
  • pool_state.liquidity = 0 (아직 포지션 없음).
  • pool_state.fee_on = FromInput (레거시 기본값).
  • pool_state.dynamic_fee_info는 0으로 설정됨 (동적 수수료 비활성화).

CreateCustomizablePool

새 풀에 권장됩니다. CreatePool과 동일한 효과에 풀별 수수료 수집 모드와 선택적 동적 수수료 옵트인을 추가합니다. 인자
계정 (축약)CreatePool과 동일하며, enable_dynamic_fee = true일 때: 전제 조건CreatePool과 동일합니다. enable_dynamic_fee = false이면 dynamic_fee_config는 무시됩니다. 사후 조건
  • pool_state.fee_on이 선택한 CollectFeeOn 변형으로 설정됨.
  • 동적 수수료가 활성화된 경우: pool_state.dynamic_fee_info는 제공된 DynamicFeeConfig에서 초기화됨 (5개의 보정 매개변수 복사됨, 상태 필드는 0으로 설정됨).
  • 그렇지 않으면: pool_state.dynamic_fee_info는 0으로 설정됨 (= 이 풀에 대해 동적 수수료는 영구적으로 비활성화).
fee_on과 동적 수수료 활성화 비트는 풀 생성 시에만 설정됩니다. 제자리 업그레이드는 없습니다. 레거시 CreatePool을 통해 생성된 풀은 동적 수수료나 단측 수수료를 소급하여 얻을 수 없습니다. 새 배포는 이 명령어를 기본값으로 사용해야 합니다.

CreatePermissionedPool

CreatePoolCreateCustomizablePool 모두 ["pool", amm_config, token_mint_0, token_mint_1]에서 풀 PDA를 파생하므로, (config, mint0, mint1) 트리플당 정확히 하나의 정규 풀 주소가 있습니다. 같은 시드에서 두 번째 init은 실패합니다. CreatePermissionedPool은 클라이언트가 제공한 seed_index: u16을 풀 PDA 시드에 포함하여 이 제한을 해제하므로, 같은 쌍과 수수료 계층에 대해 여러 풀을 만들 수 있습니다. 각각 자신의 주소에서. 임의의 풀 주소는 특권 기능이므로, 지불자는 이를 승인하는 Permission PDA를 보유해야 합니다. 풀에 대한 다른 모든 것은 CreateCustomizablePool과 동일합니다. 동일한 CreateCustomizableParams를 사용하고 단측 수수료와 동적 수수료 옵트인을 지원합니다. 인자
계정 (축약)CreateCustomizablePool과 동일하며, 앞에: pool_state PDA는 ["pool", amm_config, token_mint_0, token_mint_1, seed_index.to_le_bytes()]에서 파생됩니다. 전제 조건
  • seed_index != 0. seed_index 0은 레거시 풀을 위해 예약되어 있으며 여기서 거부됩니다. [0, 0] 시드 구성 요소는 레거시 풀 주소를 클래식 4시드 형식으로 축소하는 것입니다.
  • payer에 대한 permission PDA가 존재합니다 (관리자가 CreatePermissionPda를 통해 생성).
  • CreatePool과 동일한 민트/허용 목록 규칙.
사후 조건
  • 새로운 pool_stateseed_index 파생 주소에 존재하며, pool_state.seed_index = seed_index.
  • 다른 모든 사후 상태는 CreateCustomizablePool과 일치합니다 (수수료 모드, 선택적 동적 수수료).
이 명령어는 일반 풀 생성 접근을 확대하지 않습니다. 무허가 생성은 CreatePool / CreateCustomizablePool을 통해 계속되며, 이는 쌍당 하나의 풀로 유지됩니다. CreatePermissionedPool은 화이트리스트된 운영자가 같은 쌍에 대해 여러 풀이 필요한 경우 (예: 다른 초기 가격 또는 출시 코호트)이고 관리자가 부여한 Permission PDA를 보유하는 특정 경우에 존재합니다.

OpenPositionV2 / OpenPositionWithToken22Nft

기존 풀 내에 새로운 포지션을 만듭니다. 인자
계정 (축약) 수학products/clmm/math 참조. base_flag가 주어지면, 프로그램은 liquidity 또는 (amount_0_max, amount_1_max) 중 하나를 실제 L과 소비된 실제 토큰 금액으로 해석합니다. 전제 조건
  • tick_lower < tick_upper, 둘 다 pool.tick_spacing의 배수, [MIN_TICK, MAX_TICK] 범위 내.
  • 필요한 틱 배열이 전달되고 초기화됨 (또는 트랜잭션에서 InitTickArray CPI를 통해 여기서 생성됨).
  • 사용자는 소스 ATA에 최소 amount_0_maxamount_1_max를 보유합니다.
사후 조건
  • personal_position이 존재하고, liquidity가 설정되고, fee_growth_inside_last가 스냅샷됨.
  • tick_lowertick_upper의 틱 배열 항목이 업데이트됨 (liquidity_gross += L, liquidity_net ± L, 수수료 성장 스냅샷 유지).
  • 포지션이 범위 내인 경우 pool_state.liquidity += L (tick_lower ≤ tick_current < tick_upper).
  • 포지션 NFT 민트는 pool_state를 동결 권한으로 기록합니다. 민트 권한은 단일 NFT가 발행된 후 제거됩니다. 동결 권한을 기록해도 NFT 토큰 계정의 상태는 변경되지 않습니다.
  • NFT 토큰 계정은 명령어가 OpenPositionV2 또는 OpenPositionWithToken22Nft 이고 볼트 민트의 동결 권한이 CLMM의 제한된 발급자 목록과 일치하는 경우를 제외하고는 동결되지 않은 상태로 유지됩니다. 일치하는 V2 경로만 계정을 동결합니다. OpenPosition V1은 동결하지 않습니다.
일반적인 오류InvalidTickIndex, NotApproved, ZeroAmountSpecified, TransactionTooLarge (틱 배열이 너무 많은 경우).
포지션 동결은 선언된 명령어 계정이나 인자를 추가하지 않습니다. 클라이언트는 기존 V2 레이아웃으로 이러한 포지션을 열 수 있습니다. 동작은 vault_0_mintvault_1_mint에서 온체인으로 선택됩니다.

IncreaseLiquidityV2

이미 열린 포지션에 유동성을 추가합니다. 인자
계정OpenPosition과 유사하지만 NFT 민트 제외 (포지션이 이미 존재하고, NFT는 1개 토큰을 보유하는 소유자의 ATA로 전달됨). 효과
  • 사용자 → 볼트에서 amount_0_actual / amount_1_actual을 전송합니다.
  • personal_position.liquiditypool_state.liquidity (범위 내인 경우)를 증가시키고, 끝점 틱 liquidity_gross / liquidity_net을 그에 따라 조정합니다.
  • 마지막 터치 이후 지불해야 할 수수료와 보상을 수집하고 tokens_fees_owed_{0,1} / reward_amount_owed에 입금합니다. 이들은 DecreaseLiquidity 또는 CollectReward에서만 지불되며, 증가 시에는 지불되지 않습니다.

DecreaseLiquidityV2

포지션에서 유동성을 제거합니다. 인자
계정IncreaseLiquidity와 동일한 형태. 효과
  • 현재 sqrt_price_x64가 주어진 제거된 L에 대해 (amount_0, amount_1)을 계산합니다.
  • 마지막 터치 이후 발생한 수수료/보상을 정산합니다 (IncreaseLiquidity와 동일).
  • 볼트에서 사용자에게 amount_0 + fees_owed_0amount_1 + fees_owed_1을 전송합니다.
  • 유동성 카운터를 감소시킵니다. 새로운 personal_position.liquidity == 0이면, 포지션은 ClosePosition에 적합합니다.
슬리피지amount_0_minamount_1_min은 출력 측의 Token-2022 전송 수수료를 차감한 사용자가 수락하는 최소값입니다.

ClosePosition

포지션 NFT를 소각하고 PersonalPositionState를 닫습니다. 선언된 계정 남은 계정
  • 동결되지 않은 NFT: 필요 없음. 추가 풀 계정은 핸들러가 읽지 않으므로 무해합니다.
  • 동결된 NFT: personal_position.pool_id를 첫 번째 남은 계정으로 추가합니다. 프로그램은 이를 PoolState로 로드하고 해제에 서명하기 위해 PDA 시드를 사용합니다.
전제 조건
  • personal_position.liquidity == 0.
  • tokens_fees_owed_{0,1} == 0.
  • 모든 보상 카운터 reward_amount_owed == 0.
(즉, 먼저 모든 것을 수집하고 0으로 감소시킵니다.) 효과
  • NFT 토큰 계정이 동결되어 있으면, 첫 번째 남은 계정이 personal_position.pool_id와 같은지 확인한 후 풀 PDA로 해제합니다.
  • NFT를 소각합니다.
  • NFT 토큰 계정과 personal_position을 닫고, 임차료를 nft_owner에게 환불합니다. 포지션 NFT가 Token-2022를 사용하면 NFT 민트도 닫습니다. 클래식 SPL 토큰 민트는 닫을 수 없으며 공급량 0으로 유지됩니다.
해제, 소각, 닫기는 원자적입니다. NFT는 이 단계 사이에 양도 가능해질 수 없습니다. 조건부 클라이언트 중단 — 선언된 IDL 레이아웃은 변경되지 않으므로 레거시 클라이언트는 기존 및 동결되지 않은 포지션을 계속 닫습니다. 풀 남은 계정을 생략하는 레거시 빌더는 동결된 포지션을 닫을 때 AccountLack으로 실패합니다. 모든 닫기에 대해 풀을 전달하는 것이 가장 간단한 호환 전략입니다.

SwapV2

유동성 곡선을 따라갑니다. is_base_input에 따라 정확한 입력 또는 정확한 출력. 인자
계정 (축약) 호출자는 예상 스왑 워크를 포함하는 순위가 지정된 틱 배열 목록을 전달합니다. 프로그램은 필요한 만큼 사용합니다. SDK는 PoolUtils.computeAmountOutFormat 또는 API의 견적 끝점을 통해 이 목록을 계산합니다. 전제 조건
  • pool_state.status가 스왑을 허용합니다.
  • now >= open_time.
  • sqrt_price_limit_x64는 방향에 대해 sqrt_price_x64의 올바른 쪽에 있습니다.
일반적인 오류ExceededSlippage, SqrtPriceLimitOverflow, TickArrayNotFound, LiquidityInsufficient. SwapV2가 내부적으로 수행하는 작업 (호출자가 알아야 할 사항) (2025년 이후 릴리스):
  1. 동적 수수료 할증pool.dynamic_fee_info가 0이 아니면, 프로그램은 마지막 스왑 이후 순회한 틱 거리를 사용하여 변동성 누적기를 업데이트하고 (필터/감소 규칙 포함 products/clmm/fees) AmmConfig.trade_fee_rate 위에 dynamic_fee_component를 추가합니다. 총 수수료는 10% (MAX_FEE_RATE_NUMERATOR / 1_000_000)로 제한됩니다.
  2. 지정가 주문 매칭 — 가격 워크가 공개 지정가 주문을 보유한 틱을 지날 때, 프로그램은 먼저 해당 틱에서 사용 가능한 지정가 주문 유동성을 채우고 (FIFO by order_phase), 그 다음 LP 유동성 곡선을 따라갑니다. 채워진 금액은 나중의 정산을 위해 tick.unfilled_ratio_x64tick.part_filled_orders_remaining을 업데이트합니다. 주문 자체는 소유자가 SettleLimitOrder를 호출할 때까지 미지출 상태로 유지됩니다.
  3. 단측 수수료 라우팅pool.fee_on = Token0Only 또는 Token1Only일 때, 스왑 단계는 여전히 동일한 입력-출력 거래를 계산합니다. 그 다음 수수료는 구성된 쪽으로 라우팅됩니다. 구성된 수수료 쪽이 출력인 방향의 경우, 수수료는 스왑 출력에서 차감됩니다 (사용자는 out − fee를 받음). 구성된 쪽이 입력인 방향의 경우, 동작은 FromInput과 일치합니다. PoolStateis_fee_on_input(zero_for_one)is_fee_on_token0(zero_for_one)을 참조하세요.
Swap (V1)은 SwapV2와 동일한 동적 수수료, 단측 수수료 라우팅, 지정가 주문 매칭을 구현합니다. 유일하게 부족한 기능은 Token-2022 지원입니다. 두 볼트 모두 클래식 SPL 토큰이어야 합니다. Token-2022 민트가 있는 풀은 SwapV2를 통해 스왑해야 합니다. 애그리게이터와 SDK는 이미 모든 CLMM 레그에 대해 V2를 선호하므로 호출자는 민트 유형에 따라 분기할 필요가 없습니다.

OpenLimitOrder

특정 틱에서 판매 주문을 배치합니다. 주문은 틱별 FIFO 코호트에 앉아 있고 가격이 지나갈 때 채워집니다. 인자
계정 (축약)
계정 목록 변경 (2026-07 릴리스). OpenLimitOrder는 이제 입력 쪽 외에도 출력 쪽 계정 — output_token_account, output_vault, output_vault_mint — 도 사용합니다. 이들은 검증에만 사용됩니다. 프로그램은 소유자의 입력 또는 출력 토큰 계정이 동결되어 있으면 주문을 거부합니다. 이는 채우기가 실제로 소유자의 출력 ATA로 정산될 수 있음을 보장합니다. 이는 허용 목록/기본 동결 Token-2022 민트 (예: 허가된 토큰)에 중요합니다. 여기서 계정이 아직 해제되지 않았을 수 있습니다. 이전 단측 계정 목록에 대해 빌드된 클라이언트는 3개의 출력 계정을 추가해야 합니다.
전제 조건
  • input_token_accountoutput_token_account 모두 동결되지 않음 (그렇지 않으면 NotApproved).
  • pool_state.status가 스왑 (비트 4)과 지정가 주문 (비트 5) 작업을 모두 허용함 (그렇지 않으면 NotApproved).
  • tick_index % pool.tick_spacing == 0이고 [MIN_TICK, MAX_TICK] 범위 내.
  • tick_index는 선택한 방향에 대해 pool.tick_current의 올바른 쪽에 있음 (토큰0 판매 → 틱은 현재 위에 있어야 함, 그 반대도 마찬가지). 이미 지나간 틱에서 판매하면 즉시 매칭되고 거부됩니다.
사후 조건
  • limit_order가 존재하고, 열기 시간에 tick.order_phasetick.unfilled_ratio_x64를 스냅샷함.
  • tick.orders_amount += amount (현재 코호트에서).
  • limit_order_nonce.order_nonce += 1.
  • OpenLimitOrderEvent 발행됨.
일반적인 오류NotApproved (입력 또는 출력 토큰 계정 동결, 또는 풀이 스왑/지정가 주문 비활성화), InvalidLimitOrderAmount (0 또는 풀의 최소값 이하), InvalidTickIndex ([MIN_TICK, MAX_TICK] 범위 밖, 또는 선택한 방향에 대해 tick_current의 잘못된 쪽), TickAndSpacingNotMatch (tick_index % pool.tick_spacing != 0), OrderPhaseSaturated.

IncreaseLimitOrder

기존 공개 주문에 추가합니다. 주문의 owner만 호출할 수 있습니다. 인자
계정OpenLimitOrder와 유사하지만 논스 계정 제외. limit_order PDA는 직접 전달됩니다. 전제 조건
  • limit_order.owner == signer.
  • 주문이 여전히 동일한 코호트에 있음 (tick.order_phase == limit_order.order_phase). 코호트가 이미 채우기를 시작했으면, 주문은 부분적으로 정산됨. 호출자는 먼저 DecreaseLimitOrder 또는 SettleLimitOrder를 호출하여 앞으로 이동해야 합니다.
효과
  • 소유자 ATA에서 input_vaultamount를 전송합니다.
  • limit_order.total_amount += amount. tick.orders_amount += amount.

DecreaseLimitOrder

공개 주문을 줄이거나 완전히 취소합니다. 미체결 나머지를 소유자에게 지불하고, 과거 부분 채우기로 이미 정산된 출력도 지불합니다. 인자
계정 — 입력 및 출력 토큰 쪽: 효과
  • 열기 이후 코호트의 unfilled_ratio_x64에서 주문의 채워진 금액을 재계산합니다.
  • 채워진 출력을 output_token_account로 보냅니다.
  • 미체결 입력의 amountinput_token_account로 다시 보냅니다.
  • limit_order를 그에 따라 업데이트합니다. 새로운 미체결 나머지가 0이면, 프로그램은 계정을 닫고 임차료를 owner에게 환불합니다.

SettleLimitOrder

주문의 미체결 나머지를 변경하지 않고 채워진 출력 토큰을 소유자에게 푸시합니다. auto_withdraw 담당자가 장기 실행 부분 채우기를 점진적으로 지불하려고 할 때 유용합니다. 호출자 — 주문의 owner 또는 프로그램의 limit_order_admin (자동화된 담당자 루프를 실행하는 오프체인 운영 핫 지갑). 담당자는 다른 권한이 없습니다. 채워진 출력을 주문의 owner ATA로 푸시하는 것 외에는 사용자 자금을 이동할 수 없습니다. 계정 효과
  • (limit_order.unfilled_ratio_x64, tick.unfilled_ratio_x64)를 사용하여 누적 출력 지불액을 계산합니다.
  • 델타를 output_token_account로 전송합니다.
  • limit_order.settled_output을 업데이트합니다.
  • 주문을 닫지 않습니다. 남은 입력에 대해 여전히 열려 있습니다.

CloseLimitOrder

완전히 소비된 주문 계정을 닫습니다. 임차료는 누가 서명하든 항상 limit_order.owner에게 반환됩니다. 호출자owner 또는 limit_order_admin. 전제 조건
  • 주문의 미체결 나머지가 0임 (amount == total_amount가 채워지고 정산되었거나, 소유자가 이전에 주문을 0으로 감소시키고 닫기를 잊음).
효과
  • limit_order를 닫습니다. 임차료는 limit_order.owner로 전송됩니다.

CreateDynamicFeeConfig (관리자)

u16 인덱스 아래에서 재사용 가능한 매개변수 집합을 만듭니다. 인자
계정 일반적인 오류InvalidDynamicFeeConfigParams (decay_period <= filter_period 또는 0 값 필드가 범위를 벗어남).

UpdateDynamicFeeConfig (관리자)

기존 DynamicFeeConfig를 수정합니다. 생성 시 이미 구성을 스냅샷한 풀은 소급하여 업데이트되지 않습니다. 이 구성을 참조하는 새로 생성된 풀만 새 값을 선택합니다. 인자CreateDynamicFeeConfig와 동일한 5개의 보정 필드 (filter_period, decay_period, reduction_factor, dynamic_fee_control, max_volatility_accumulator). index는 생성 시 고정되며 여기서 다시 전달되지 않습니다.

CollectProtocolFee / CollectFundFee

CPMM의 CollectProtocolFee / CollectFundFee와 동일한 형태. 서명자는 AmmConfig.owner / AmmConfig.fund_owner와 일치해야 합니다. 풀의 볼트에서 누적된 프로토콜/펀드 수수료를 수신자에게 정리하고, 해당 PoolState.protocol_fees_* / fund_fees_* 필드를 0으로 설정합니다.

InitializeReward

풀에 새로운 보상 스트림을 추가합니다. 최대 3개의 스트림이 한 번에 활성화될 수 있습니다. 인자
계정 전제 조건
  • 풀에서 현재 3개 미만의 스트림이 활성화됨.
  • 펀더는 이 명령어의 일부로 total_emission = emissions_per_second × (end_time − open_time) 상당의 보상 토큰을 볼트에 입금합니다.
  • operation_state당 화이트리스트된 보상 민트.

SetRewardParams

기존 보상 스트림을 연장, 충전 또는 배출 속도를 변경합니다. 일반적으로 풀 생성자 또는 Raydium 멀티시그에서 호출합니다. 제약은 온체인에 있습니다. 일반적으로 end_time을 연장하거나 배출을 증가시킬 수 있지만, 소급하여 축소할 수는 없습니다. operation_state의 소유자 목록을 확인하세요.

UpdateRewardInfos

순수 부기 — reward_growth_global_x64를 현재 시간으로 정산합니다. emissions_per_second × Δt / liquidity를 곱합니다. 모든 유동성 터치 명령어에 의해 내부적으로 호출됩니다. 외부 행위자 (UI, 크랭크)가 때때로 이를 트리거하려고 하므로 독립 실행형 명령어로 노출됩니다.

CollectReward

포지션 소유자가 지불해야 할 보상 토큰을 청구합니다. 계정 효과
  • 보상 성장을 정산합니다 (수수료와 동일한 패턴).
  • 지불해야 할 금액을 수신자 ATA로 전송하고, reward_amount_owed[i]를 0으로 설정합니다.

상태 변경 매트릭스