메인 콘텐츠로 건너뛰기

Documentation Index

Fetch the complete documentation index at: https://docs.raydium.io/llms.txt

Use this file to discover all available pages before exploring further.

이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.영문판 보기 →
버전 정보.
  • SDK: @raydium-io/raydium-sdk-v2@0.2.42-alpha
  • 클러스터: Solana mainnet-beta
  • Stable AMM 프로그램 ID: 5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h (reference/program-addresses 참고)
  • 마지막 검증: 2026-04
SDK의 liquidity 모듈은 Stable AMM 풀을 기본으로 지원합니다. Stable 풀은 ApiV3PoolInfoStandardItem에서 version: 5 (또는 pooltype: "StablePool")로 표시되며, addLiquidity / removeLiquidity / 스왑 헬퍼는 AMM v4 (version: 4) 상수곱 풀과 동일하게 작동합니다. SDK가 자동으로 변형을 감지하고 올바른 명령어를 생성합니다. 오프체인 Stable 곡선 수학은 src/raydium/liquidity/stable.ts에 있습니다.

설정

npm install @raydium-io/raydium-sdk-v2 @solana/web3.js @solana/spl-token
import { Raydium, TxVersion } from "@raydium-io/raydium-sdk-v2";
import { Connection, Keypair, clusterApiUrl } from "@solana/web3.js";
import BN from "bn.js";
import bs58 from "bs58";

const connection = new Connection(clusterApiUrl("mainnet-beta"));
const owner = Keypair.fromSecretKey(bs58.decode(process.env.PRIVATE_KEY!));

const raydium = await Raydium.load({
  connection,
  owner,
  cluster: "mainnet",
  // 선택사항: `liquidity/stable.ts`에서 견적 헬퍼를 직접 호출하려는 경우
  // Stable 곡선 모델 레이아웃을 로드합니다. 풀 수준의 스왑 / 추가 / 제거는
  // 필요에 따라 자동으로 처리하므로 대부분의 경우 이 단계를 건너뛸 수 있습니다.
});

// 일회성: 오프체인 Stable 곡선 헬퍼에서 사용하는 온체인 모델 데이터 레이아웃을 미리 가져옵니다.
// getStablePrice / getDxByDyBaseIn / getDyByDxBaseIn을 직접 호출할 때만 필요합니다.
// addLiquidity / removeLiquidity / swap은 이 과정이 필요하지 않습니다.
await raydium.liquidity.initLayout();

Stable 풀 식별

ApiV3PoolInfoStandardItem의 두 가지 동등한 신호:
const isStable =
  pool.version === 5 ||
  pool.pooltype.includes("StablePool"); // SDK는 내부적으로 이 문자열 검사를 사용합니다

// 또는 프로그램 ID로:
const STABLE_AMM_PROGRAM_ID = "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h";
const isStableByProgram = pool.programId === STABLE_AMM_PROGRAM_ID;
AMM v4 (version: 4, 상수곱)과 Stable AMM (version: 5) 모두 SDK의 동일한 LiquidityModule API를 통해 처리됩니다. 내부적으로 모듈은 다음으로 전달됩니다:
  • v4 풀의 InstructionType.AmmV4AddLiquidity / AmmV4RemoveLiquidity
  • v5 (Stable) 풀의 InstructionType.AmmV5AddLiquidity / AmmV5RemoveLiquidity
풀의 programId (풀 키와 함께 반환됨)는 SDK에 어느 프로그램으로 CPI할지 알려줍니다. 하드코딩할 필요가 없습니다.

민트 쌍으로 풀 찾기

import { PublicKey } from "@solana/web3.js";

// 예시로 사용할 두 가지 일반적인 민트
const mintA = new PublicKey("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB"); // USDT
const mintB = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); // USDC

const pools = await raydium.api.fetchPoolByMintPair({
  mint1: mintA.toBase58(),
  mint2: mintB.toBase58(),
});

const stablePool = pools.find(
  (p) => p.version === 5 || p.pooltype.includes("StablePool"),
);

if (!stablePool) {
  throw new Error("No Stable pool exists for this mint pair");
}

console.log("Stable pool id:", stablePool.id);
console.log("Stable pool programId:", stablePool.programId);
console.log("TVL:", stablePool.tvl);
민트 쌍에 v4 (상수곱) 풀과 v5 (Stable) 풀이 모두 있는 경우, 응답에는 둘 다 포함됩니다. 필요한 풀을 선택하거나 AMM Routing 프로그램에 전달하여 최적 경로를 선택하게 합니다.

Stable 풀을 통한 스왑

LiquidityModule.swap 흐름은 v4 풀과 동일한 모양입니다. v5 풀 객체를 전달하기만 하면 됩니다:
import { Percent, TokenAmount, toToken } from "@raydium-io/raydium-sdk-v2";

const inputAmount = new TokenAmount(toToken(stablePool.mintA), 1_000_000); // 1 USDT
const slippage = new Percent(50, 10_000); // 0.5%

// SDK의 Stable 곡선 헬퍼를 내부적으로 사용하여 예상 출력값을 계산합니다.
const { amountOut, minAmountOut } = raydium.liquidity.computeAmountOut({
  poolInfo: stablePool,
  amountIn: inputAmount,
  mintIn:  stablePool.mintA.address,
  mintOut: stablePool.mintB.address,
  slippage,
});

console.log("Expected out:", amountOut.toSignificant());
console.log("Minimum out:", minAmountOut.toSignificant());

// 스왑 트랜잭션을 구성하고 서명합니다.
const { transaction, execute } = await raydium.liquidity.swap({
  poolInfo: stablePool,
  amountIn:    inputAmount.raw,
  amountOut:   minAmountOut.raw,
  fixedSide:   "in",
  txVersion:   TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
console.log("Stable swap tx:", txId);
SDK는 풀 키에서 풀의 programId를 읽고 Stable AMM 프로그램으로 전달합니다. 특수한 programId 인자는 필요하지 않습니다.

유동성 추가 및 제거

addLiquidityremoveLiquidity는 v4 및 v5 풀에서 동일하게 작동합니다:
import { Percent, TokenAmount, toToken } from "@raydium-io/raydium-sdk-v2";

const amountInA = new TokenAmount(toToken(stablePool.mintA), 100_000_000); // 100 USDT
const slippage  = new Percent(50, 10_000); // 0.5%

// 곡선에서 이 크기의 A에 필요한 매칭 B 양을 계산합니다.
const { anotherAmount, minAnotherAmount } = raydium.liquidity.computePairAmount({
  poolInfo: stablePool,
  amount:   amountInA.toSignificant(),
  baseIn:   true,
  slippage,
});

const { execute } = await raydium.liquidity.addLiquidity({
  poolInfo: stablePool,
  amountInA,
  amountInB:      anotherAmount,
  otherAmountMin: minAnotherAmount,
  fixedSide:      "a",
  txVersion:      TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
console.log("Add-liquidity tx:", txId);
내부적으로 SDK는 pooltype.includes("StablePool")이 true이므로 InstructionType.AmmV5AddLiquidity를 생성합니다. 해당하는 removeLiquidity 흐름은 대칭적입니다. lpAmount와 각 측에서 허용할 최소 금액을 입력하면 됩니다.

오프체인 견적 헬퍼 (stable.ts)

서버측 견적이나 백테스팅의 경우, SDK는 기본 Stable 곡선 수학을 노출합니다:
import {
  getStablePrice,
  getDxByDyBaseIn,
  getDyByDxBaseIn,
} from "@raydium-io/raydium-sdk-v2";

// 이 함수들을 사용하기 전에 initLayout()을 한 번 호출해야 합니다 (온체인
// `ModelDataInfo` PDA를 SDK의 StableLayout 캐시에 로드합니다).
await raydium.liquidity.initLayout();

const modelData = raydium.liquidity.stableLayout;

// 풀의 현재 보유량에서의 현물 가격입니다.
const price = getStablePrice(modelData, /* x */, /* y */, /* withFee */);
console.log("Spot price:", price);

// 견적: dx를 입력할 때 얼마나 많은 dy가 출력될까요 (수수료 미적용)?
const dyOut = getDyByDxBaseIn(modelData, /* x */, /* y */, /* dx */);

// 견적: dy 출력 목표가 주어졌을 때 필요한 dx 입력은 얼마일까요?
const dxIn  = getDxByDyBaseIn(modelData, /* x */, /* y */, /* dy */);
이들은 순수 함수입니다. RPC도 없고, 서명도 없습니다. 온체인 ModelDataInfoinitLayout()에 의해 한 번 가져와지고 raydium.liquidity.stableLayout에 캐시됩니다. 현재 보유량 (x, y)을 전달하면 헬퍼는 조회 테이블을 이진 검색하고 주변의 두 DataElement 행 사이를 선형 보간하여 계산합니다. 기본 알고리즘은 products/stable/math를 참고하세요.

AMM Routing을 통한 라우팅 (다중 홉 / 최적 가격)

장소를 직접 선택하지 않으려면, AMM Routing 프로그램이 모든 Raydium AMM (v4 / CPMM / CLMM / Stable)을 고려하고 최적의 조합을 통해 라우팅합니다:
const route = await raydium.tradeV2.fetchRoutes({
  inputMint:  mintA,
  outputMint: mintB,
  amount:     new BN(1_000_000),
  slippage,
});

// route.routes[0].poolType은 최적 경로가 사용하는 프로그램을 알려줍니다.
// Stable 풀이 최적 경로의 일부일 때마다 "Stable"이 여기에 나타납니다.
console.log(route.routes[0]);

const { execute } = await raydium.tradeV2.swap({
  inputMint:    mintA,
  outputMint:   mintB,
  inputAmount:  new BN(1_000_000),
  swapResult:   route.routes[0],
  slippage,
  txVersion:    TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
이것이 프로덕션 스왑 및 애그리게이터에 권장되는 경로입니다. Stable 풀이 존재하는지 또는 오늘의 더 나은 장소인지 수동으로 결정할 필요가 없습니다.

권장사항

  1. 엔드 사용자 스왑의 경우, tradeV2 라우팅 흐름을 선호합니다. Stable을 포함한 모든 Raydium 풀 유형을 처리합니다.
  2. 풀 특정 작업의 경우 (알려진 Stable 풀에서 LP 추가/제거), LiquidityModule을 직접 사용합니다. v5 풀을 자동으로 감지합니다.
  3. 오프체인 견적 / 분석의 경우, initLayout()getStablePrice / getDyByDxBaseIn / getDxByDyBaseIn을 호출합니다. 모델 데이터가 캐시된 후에는 견적당 RPC 트래픽이 없습니다.
  4. 원본 SwapBaseIn 명령어를 손으로 코딩하지 마세요. Stable AMM 프로그램 (AMM v4에서 포크됨)은 V1 스왑 진입점에 17–19개의 OpenBook 계정이 필요하며, model_data_account가 그들 중 하나로 삽입됩니다. SDK의 사전 구성된 헬퍼는 모든 계정과 순서를 올바르게 처리합니다. 직접 작성하는 것은 오류가 발생하기 쉽습니다.

다음 단계

  • Math — 조회 테이블 보간이 어떻게 작동하는지.
  • Instructions — 전체 명령어 참고.
  • AMM Routing — AMM v4, CPMM, CLMM, Stable을 통한 다중 풀 라우팅.
출처: