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 인자는 필요하지 않습니다.
유동성 추가 및 제거
addLiquidity와 removeLiquidity는 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도 없고, 서명도 없습니다. 온체인 ModelDataInfo는 initLayout()에 의해 한 번 가져와지고 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 풀이 존재하는지 또는 오늘의 더 나은 장소인지 수동으로 결정할 필요가 없습니다.
권장사항
- 엔드 사용자 스왑의 경우,
tradeV2 라우팅 흐름을 선호합니다. Stable을 포함한 모든 Raydium 풀 유형을 처리합니다.
- 풀 특정 작업의 경우 (알려진 Stable 풀에서 LP 추가/제거),
LiquidityModule을 직접 사용합니다. v5 풀을 자동으로 감지합니다.
- 오프체인 견적 / 분석의 경우,
initLayout() 후 getStablePrice / getDyByDxBaseIn / getDxByDyBaseIn을 호출합니다. 모델 데이터가 캐시된 후에는 견적당 RPC 트래픽이 없습니다.
- 원본
SwapBaseIn 명령어를 손으로 코딩하지 마세요. Stable AMM 프로그램 (AMM v4에서 포크됨)은 V1 스왑 진입점에 17–19개의 OpenBook 계정이 필요하며, model_data_account가 그들 중 하나로 삽입됩니다. SDK의 사전 구성된 헬퍼는 모든 계정과 순서를 올바르게 처리합니다. 직접 작성하는 것은 오류가 발생하기 쉽습니다.
다음 단계
출처: