Skip to main content
이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.영문판 보기 →
버전 배너. 모든 데모는 Solana mainnet-beta에서 @raydium-io/raydium-sdk-v2@0.2.42-alpha를 대상으로 하며, 2026-04에 검증되었습니다. 프로그램 ID는 SDK를 통해 reference/program-addresses에서 가져옵니다.

설정

이 페이지의 모든 데모는 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)를 계산합니다.
  • observationtick_array_bitmap_extension 계정을 생성합니다.
  • ammConfig에서 정의한 풀 생성 수수료를 지불합니다.

선택한 범위에서 포지션 열기

소스: src/clmm/createPosition.ts
SDK는 범위가 터치하는 틱 배열을 자동으로 계산하고, 초기화되지 않은 경우 InitTickArray 명령을 번들로 묶습니다.

기존 포지션의 유동성 증가

소스: src/clmm/increaseLiquidity.ts

유동성 감소 (동시에 수수료 수집)

소스: src/clmm/decreaseLiquidity.tssrc/clmm/closePosition.ts
수수료만 수집하려면 liquidity = new BN(0)으로 decreaseLiquidity를 호출합니다. 명령의 부작용은 tokens_fees_owed_{0,1}을 정산하고 이를 전송하는 것입니다. 유동성과 수수료를 0으로 만든 후 포지션을 완전히 닫으려면 최종 decreaseLiquidity 호출에서 closePosition: true를 전달합니다. SDK는 ClosePosition을 추가하고 NFT를 소각합니다.
제한된 발행자 포지션은 호환되는 클로즈 빌더가 필요합니다. 이러한 포지션은 동결된 NFT 토큰 계정을 가집니다. ClosePosition은 CLMM이 소각 전에 계정을 해제할 수 있도록 포지션의 풀 ID를 첫 번째 남은 계정으로 추가해야 합니다. 프로그램 소스 분기에는 SDK 변경이 포함되지 않습니다. 제한된 발행자 포지션 생성을 활성화하기 전에 SDK 릴리스가 동결된 클로즈 경로를 명시적으로 지원하는지 확인하세요.
직접 Anchor 클라이언트의 경우 선언된 계정을 변경하지 않고 풀을 추가합니다:
모든 클로즈에서 poolId를 전달할 수 있습니다. CLMM은 positionNftAccount가 동결되었을 때만 읽으므로, 한 클라이언트 경로를 이전 및 새 포지션과 호환되게 유지합니다.

보상 수집

소스: src/clmm/harvestAllRewards.ts
harvestAllRewards는 전달된 모든 풀의 모든 포지션을 순회하고, CollectReward (및 모든 UpdateRewardInfos) 명령을 배치하며, 필요한 경우 트랜잭션 간에 분할합니다.

스왑

소스: src/clmm/swap.ts
computeAmountOutFormat는 온체인 프로그램과 동일한 로직을 사용하여 틱 맵을 오프체인에서 순회하고 다음을 반환합니다:
  • 예상 출력 금액,
  • 슬리피지 후 최소 출력 금액,
  • 실제 스왑이 터치할 틱 배열 계정 목록 (remainingAccounts).
시뮬레이션에서 반환한 remainingAccounts를 항상 전달합니다: 너무 적게 전달하면 스왑이 TickArrayNotFound로 중간에 되돌아가고, 오래된 것을 전달하면 낭비되는 계산이 발생합니다.

사용자 정의 가능한 CLMM 풀 생성

createCustomizablePool은 풀 생성 시 동적 수수료 및 단측 수수료 토글을 노출하는 새로운 진입점입니다. createPool과 동일한 형태에 세 가지 추가 사항이 있습니다:
createPool은 기본 수수료, 제한 주문 없음, 동적 수수료 없음 경로에 계속 작동합니다. 세 가지 새로운 노브 중 하나가 필요할 때마다 createCustomizablePool을 사용합니다. 온체인 계정 목록은 products/clmm/instructions를 참조하세요.

제한 주문

제한 주문은 사용자 입력을 단일 틱에 주차하고, 스왑이 해당 틱을 교차할 때 FIFO로 채워집니다. 출력은 정산 시 소유자의 ATA로 푸시되며, 소유자가 온라인 상태일 필요가 없습니다.

제한 주문 열기

SDK는 (pool, owner, tick, nonce)에서 LimitOrderState PDA를 파생하고, 풀당 소유자별 LimitOrderNonce를 범프하며, 해당 틱의 FIFO 코호트에 주문을 삽입합니다.

열린 주문 증가 / 감소

decreaseLimitOrder는 주문의 채워지지 않은 부분에서만 제거할 수 있습니다. 채워진 부분은 정산까지 잠깁니다. 주문이 이미 완전히 채워진 경우 두 명령 모두 InvalidOrderPhase로 되돌아갑니다.

채워진 주문 정산

settleLimitOrder는 주문의 unfilled_ratio_x64를 코호트 추적기에 대해 읽고, 채워진 출력을 계산하며, 이를 소유자의 ATA로 전송합니다. 소유자가 직접 호출할 수 있습니다. limit_order_admin (오프체인 운영 키퍼)도 소유자를 대신하여 호출할 수 있습니다. 출력은 여전히 소유자에게 갑니다. 완전히 정산된 주문을 닫아 임차료를 복구하려면 closeLimitOrder (단일) 또는 closeAllLimitOrder (배치)를 사용합니다. 한 번에 많은 것을 정산하려면 settleAllLimitOrder가 v0 tx에 맞는 만큼 많은 SettleLimitOrder 호출을 패킹합니다.

지갑의 주차된 주문 나열 (오프체인)

활성 주문 엔드포인트는 채워지지 않은 주문과 부분적으로 채워진 주문을 하나의 페이로드로 반환합니다 (totalAmount / filledAmount / pendingSettle이 단계를 구분합니다). 닫힌 주문 기록의 경우 /limit-order/history/order/list-by-user?wallet=… (지갑별, nextPageId로 페이지 매김)을 사용합니다. 특정 주문의 전체 이벤트 로그의 경우 /limit-order/history/event/list-by-pda?pda=…를 사용합니다.

Rust CPI 스켈레톤

SwapV2의 남은 계정 순서:
스왑이 확장을 필요로 하지 않으면 생략합니다. 그렇지 않으면 첫 번째 남은 계정입니다.

일반적인 함정

  • 간격을 벗어난 틱 끝점InvalidTickIndex. 항상 TickUtils.getPriceAndTick을 통해 스냅합니다.
  • SwapV2에서 제공된 틱 배열이 부족TickArrayNotFound. computeAmountOutFormat을 사용하여 전체 목록을 가져옵니다.
  • 비트맵 확장 없는 전체 범위 포지션 → 확장 PDA는 쓰기 가능해야 합니다. SDK가 자동으로 처리합니다.
  • sqrt_price_x64price로 착각 → 여기서 2배 혼동은 특히 고통스럽습니다. 의심할 때는 SDK가 인간이 읽을 수 있는 가격에서 계산하도록 하세요.
  • 너무 열심히 보상 수집 → 각 수집은 하나의 트랜잭션이 소요됩니다. 많은 포지션에서 harvestAllRewards를 통해 배치합니다.
  • NFT 계정을 직접 닫기ClosePosition은 NFT를 소각하고 ATA를 닫습니다. Token-2022 NFT 민트도 닫습니다. 고전적인 SPL Token 민트는 해당 프로그램이 민트를 닫을 수 없기 때문에 공급량 0으로 유지됩니다. 지원되는 계정을 별도로 닫지 마세요. 그렇지 않으면 명령이 되돌아갑니다.
  • 간격이 없는 틱에서 제한 주문 열기InvalidTickIndex. 항상 TickUtils.getPriceAndTick을 통해 양자화합니다.
  • 완전히 채워진 주문에서 decreaseLimitOrder 호출InvalidOrderPhase. 대신 settleLimitOrder 다음 closeLimitOrder를 사용합니다.
  • enableDynamicFee: true를 전달하면서 dynamicFeeConfigId 잊기CreateCustomizablePool 되돌아가기는 InvalidDynamicFeeConfigParams입니다. 동적 수수료를 끄거나 /main/clmm-dynamic-config에서 구성을 선택합니다.

다음 단계

소스: