이 페이지는 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 스켈레톤은 raydium-clmm의 master를 대상으로 하며, Anchor =0.32.1을 고정합니다 — CPMM 페이지에서 사용하는 1.0.2가 아닙니다; 둘은 하나의 크레이트에 함께 있을 수 없습니다. 프로그램 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 (API 풀 객체가 아닌 getPoolInfoFromRpc의 computePoolInfo)와 두 개의 추가 필수 인수 — 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 라우팅.

