이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.영문판 보기 →
버전 배너. 모든 TypeScript 데모는
@raydium-io/raydium-sdk-v2@0.2.64-alpha를 대상으로 하며, 0.2.42-alpha(2026-04)에 대해 마지막으로 실행되었고 2026-09-09에 Solana mainnet-beta에 대해 0.2.64-alpha 소스에 대해 호출 서명을 다시 확인했습니다. 끝의 Rust CPI 스켈레톤은 chore/upgrade-anchor 브랜치의 raydium-clmm을 대상으로 하며, Anchor 1.0.2를 사용합니다. 이는 CPMM 페이지와 동일한 핀이므로 두 개가 하나의 크레이트에 함께 있을 수 있습니다. master는 여전히 0.32.1을 핀합니다. 프로그램 ID는 SDK를 통해 reference/program-addresses에서 가져옵니다.설정
raydium-sdk-V2-demo/src/clmm의 파일을 미러링합니다. GitHub 링크는 각 섹션 옆에 있습니다. 부트스트랩은 데모 리포지토리의 config.ts.template(소스)을 따릅니다. disableFeatureCheck: true는 모든 비자명한 통합에 권장되는 설정입니다:
CLMM 풀 생성
소스:src/clmm/createPool.ts
- 파생 전에 바이트 순서로
mint1/mint2를 정렬합니다. sqrt_price_x64 = floor(sqrt(initialPrice × 10^(dB−dA)) × 2^64)를 계산합니다.observation및tick_array_bitmap_extension계정을 생성합니다.ammConfig에서 정의한 풀 생성 수수료를 지불합니다.
선택한 범위에서 포지션 열기
소스:src/clmm/createPosition.ts
OpenPosition*은 누락된 틱 배열을 자체적으로 할당하며, 지불자의 비용으로 합니다.
기존 포지션의 유동성 증가
소스: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를 정산하고 이를 전송하는 것입니다. 이것이 둘 다 수집하는 유일한 방법입니다.
유동성과 수수료를 0으로 만든 후 포지션을 완전히 닫으려면 최종 decreaseLiquidity 호출에서 ownerInfo: { closePosition: true }를 전달합니다. SDK는 ClosePosition을 추가하고 NFT를 소각합니다.
직접 Anchor 클라이언트의 경우 선언된 계정을 변경하지 않고 풀을 추가합니다:
poolId를 전달할 수 있습니다. CLMM은 positionNftAccount가 동결되었을 때만 읽으며, 이는 하나의 클라이언트 경로를 이전 및 새 포지션과 호환되게 유지합니다.
보상 수집
소스:src/clmm/harvestAllRewards.ts
harvestAllRewards는 전달된 모든 풀의 모든 포지션을 순회하고, 수수료 및 보상을 정산하는 0-유동성 DecreaseLiquidity 호출(및 모든 UpdateRewardInfos)을 배치하고, 필요한 경우 트랜잭션 전체에 분할합니다.
스왑
소스:src/clmm/swap.ts
amountCalculated)과 스왑이 터치할 정확한 계정 목록(accounts)을 반환합니다.
항상 시뮬레이션이 반환하는 remainingAccounts를 전달합니다: 너무 적으면 스왑이 NotEnoughTickArrayAccount로 중간에 되돌아갑니다. 오래된 것들은 계산을 낭비합니다.
PoolUtils.computeAmountOutFormat은 여전히 존재하지만, ComputeClmmPoolInfo(getPoolInfoFromRpc의 computePoolInfo, API 풀 객체가 아님)와 두 개의 추가 필수 인수 — tickarrayBitmapExtension 및 blockTimestamp — 가 필요하며, raydium.clmm.fetchTickArrays 메서드가 없습니다(fetchTickArrays는 자유 함수이며, 모듈 수준 헬퍼는 PoolUtils.fetchMultiplePoolTickArrays이고 getPoolInfoFromRpc에서 반환된 tickData / tickArrays입니다).사용자 정의 가능한 CLMM 풀 생성
createCustomizablePool은 풀 생성 시 동적 수수료 및 단측 수수료 토글을 노출하는 진입점입니다. createPool의 형태에 두 가지 추가 사항을 취합니다:
createPool은 기본 수수료, 동적 수수료 없음 경로에 계속 작동합니다. 두 노브 중 하나가 필요할 때마다 createCustomizablePool을 사용합니다. 온체인 계정 목록은 products/clmm/instructions를 참조하세요.
리미트 오더
리미트 오더는 사용자 입력을 단일 틱에 주차하고 스왑이 해당 틱을 교차할 때 FIFO로 채워집니다. 출력은 정산 시 소유자의 ATA로 푸시됩니다. 소유자는 채워지기 위해 온라인일 필요가 없습니다.리미트 오더 열기
(owner, nonce PDA, order 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의 남은 계정 순서:
일반적인 함정
- 간격을 벗어난 틱 끝점 →
TickAndSpacingNotMatch. 항상TickUtil.getPriceAndTick(단수TickUtil)을 통해 스냅합니다. SwapV2에서 제공된 틱 배열이 충분하지 않음 →NotEnoughTickArrayAccount.swapInternal(...).accounts에서 목록을 가져옵니다.- 비트맵 확장 없는 전체 범위 포지션 → 확장 PDA는 쓰기 가능해야 합니다. SDK가 자동으로 처리합니다.
sqrt_price_x64를price로 착각 → 여기서 2배 혼동은 특히 고통스럽습니다. 의심할 때는 SDK가 인간이 읽을 수 있는 가격에서 계산하도록 하세요.- 너무 열심히 보상 수집 → 각 수집은 0-유동성
DecreaseLiquidity이며 하나의 트랜잭션이 소요됩니다.harvestAllRewards를 통해 많은 포지션에 걸쳐 배치하고, 그execute는{ sequentially: true }가 필요함을 기억하세요. - NFT 계정을 직접 닫기 →
ClosePosition은 NFT를 소각하고 그 ATA를 닫습니다. 또한 Token-2022 NFT 민트를 닫습니다. 클래식 SPL Token 민트는 해당 프로그램이 민트를 닫을 수 없기 때문에 공급 0으로 유지됩니다. 지원되는 계정을 별도로 닫지 마세요. 그렇지 않으면 명령이 되돌아갑니다. - 간격이 아닌 틱에서 리미트 오더 열기 →
TickAndSpacingNotMatch. 항상 내보낸getOrderTick헬퍼를 통해 양자화합니다. - 완전히 채워진 오더에서
decreaseLimitOrder호출 →InvalidOrderPhase. 대신settleLimitOrder를 사용한 후closeLimitOrder를 사용합니다. enableDynamicFee플래그 예상 → 없습니다.dynamicFeeConfig를 생략하면 정적 수수료 풀을 조용히 생성하며 오류가 없습니다. 동적 수수료를 원했다면/main/clmm-dynamic-config에서 선택한 구성 계정의PublicKey를 전달합니다.
다음 단계
sdk-api/typescript-sdk— 완전한 SDK 표면.sdk-api/rest-api— 견적 및 풀 메타데이터 엔드포인트.user-flows/create-clmm-pool— 비코드 안내.integration-guides/aggregator— 경로의 일부로 CLMM 라우팅.

