메인 콘텐츠로 건너뛰기

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 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.영문판 보기 →
버전 배너. 모든 데모는 Solana mainnet-beta에 대해 @raydium-io/raydium-sdk-v2@0.2.42-alpha를 대상으로 하며, 2026년 4월에 확인됨. 프로그램 ID: 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 (reference/program-addresses 참조).
새 풀 생성은 여기에 표시되지 않습니다. Raydium UI는 더 이상 AMM v4 풀 생성을 제공하지 않습니다 — 새 페어는 기본적으로 CPMM으로 설정됩니다. AMM v4 프로그램 자체는 여전히 온체인에서 Initialize2를 허용하지만, 권장 경로는 아닙니다. 아래 데모는 모든 통합자가 여전히 필요로 하는 라이브 풀 작업을 다룹니다: 스왑, 입금, 출금.

설정

import { Connection, Keypair, clusterApiUrl } from "@solana/web3.js";
import { Raydium, TxVersion } from "@raydium-io/raydium-sdk-v2";
import fs from "node:fs";

const connection = new Connection(process.env.RPC_URL ?? clusterApiUrl("mainnet-beta"));
const owner = Keypair.fromSecretKey(
  new Uint8Array(JSON.parse(fs.readFileSync(process.env.KEYPAIR!, "utf8"))),
);
const raydium = await Raydium.load({ owner, connection, cluster: "mainnet" });

ID로 풀 조회

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

const poolId = new PublicKey("<AMM_V4_POOL_ID>");

// SDK 정규화된 풀 객체를 가져옵니다. AMM v4의 경우 이는 명령어 빌더가
// 필요로 하는 OpenBook 계정을 포함합니다.
const data = await raydium.liquidity.getPoolInfoFromRpc({ poolId });
const { poolInfo, poolKeys, poolRpcData } = data;

console.log("Pair:", poolInfo.mintA.symbol, "/", poolInfo.mintB.symbol);
console.log("Version:", poolInfo.version);       // AMM v4의 경우 4
console.log("Market:", poolKeys.marketId.toBase58());
poolKeys는 명령어 빌더가 사용하는 구조체입니다. 프로그램이 예상하는 순서대로 모든 AMM v4 및 OpenBook 계정을 포함합니다.

스왑 (베이스 인)

import BN from "bn.js";

const amountIn = new BN(1_000_000);            // 1 USDC (6자리 쿼트)
const inputMint = new PublicKey(poolInfo.mintB.address);  // USDC
const slippage  = 0.005;

const computed = raydium.liquidity.computeAmountOut({
  poolInfo,
  amountIn,
  mintIn: inputMint,
  mintOut: new PublicKey(poolInfo.mintA.address),
  slippage,
});

const { execute } = await raydium.liquidity.swap({
  poolInfo,
  poolKeys,
  amountIn,
  amountOut: computed.minAmountOut,
  fixedSide: "in",
  inputMint,
  txVersion: TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
console.log("Swap tx:", txId);
SDK는 모든 OpenBook 계정을 자동으로 추가합니다. 이를 수동으로 대체하려고 시도하지 마세요 — 프로그램이 모든 슬롯을 검증합니다.

스왑 (베이스 아웃)

const amountOut = new BN(1_000_000_000);       // 1 SOL (9자리 베이스)
const slippage  = 0.005;

const computed = raydium.liquidity.computeAmountIn({
  poolInfo,
  amountOut,
  mintOut: new PublicKey(poolInfo.mintA.address),
  mintIn: new PublicKey(poolInfo.mintB.address),
  slippage,
});

const { execute } = await raydium.liquidity.swap({
  poolInfo,
  poolKeys,
  amountIn: computed.maxAmountIn,
  amountOut,
  fixedSide: "out",
  inputMint: new PublicKey(poolInfo.mintB.address),
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });

유동성 추가

const amountA = new BN(100_000_000);           // 0.1 SOL

const { anotherAmount, maxAnotherAmount } = raydium.liquidity.computePairAmount({
  poolInfo,
  amount: amountA,
  baseIn: true,
  slippage: 0.01,
});

const { execute } = await raydium.liquidity.addLiquidity({
  poolInfo,
  poolKeys,
  amountInA: amountA,
  amountInB: maxAnotherAmount,
  fixedSide: "a",
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });
fixedSide: "a"는 정확한 amountInA를 공급했으며 amountInB는 최대 maxAnotherAmount여야 함을 SDK에 알립니다. 풀의 온체인 유동성은 비례 수학 이전에 정산되므로 예금 비율이 최신 보유량과 일치합니다.

유동성 제거

const lpAmount = new BN(50_000);               // 소각할 LP

const { execute } = await raydium.liquidity.removeLiquidity({
  poolInfo,
  poolKeys,
  lpAmount,
  baseAmountMin: new BN(0),
  quoteAmountMin: new BN(0),
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });
슬리피지 최소값은 사전 견적과 도착 시간 사이에 풀의 상태가 변하는 것으로부터 보호합니다.

컴퓨트 유닛 / 우선 수수료 조정

AMM v4 스왑은 모든 명령어가 전체 OpenBook 상태를 검증하기 때문에 컴퓨트 집약적입니다. 일반적인 스왑은 프로세스에서 정산해야 할 미결 주문의 수에 따라 180k–250k CU를 사용합니다. 항상 컴퓨트 유닛 한계를 전달하세요:
import { ComputeBudgetProgram } from "@solana/web3.js";

const { execute, innerTransactions } = await raydium.liquidity.swap({
  /* ...params... */
  computeBudgetConfig: {
    units: 400_000,
    microLamports: 50_000,       // 우선 수수료
  },
});
computeBudgetConfig를 생략하면 SDK는 여전히 자체 기본값을 사용할 수 있습니다. innerTransactions을 검토하여 확인하세요. integration-guides/priority-fee-tuning을 참조하세요.

직접 Rust CPI

자신의 Anchor 프로그램에서 AMM v4로 CPI를 수행해야 하는 경우, SwapBaseIn의 계정 목록을 정확히 모델링해야 합니다. 최소한의 스케치:
use anchor_lang::prelude::*;
use anchor_lang::solana_program::program::invoke_signed;
use anchor_lang::solana_program::instruction::Instruction;

const AMM_V4_PROGRAM_ID: Pubkey = pubkey!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8");

#[derive(Accounts)]
pub struct ProxyAmmV4Swap<'info> {
    /// CHECK:
    pub token_program: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub amm:          UncheckedAccount<'info>,
    /// CHECK:
    pub amm_authority: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub amm_open_orders: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub amm_target_orders: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub pool_coin_token_account: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub pool_pc_token_account: UncheckedAccount<'info>,
    /// CHECK:
    pub market_program: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_bids: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_asks: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_event_queue: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_coin_vault: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub market_pc_vault: UncheckedAccount<'info>,
    /// CHECK:
    pub market_vault_signer: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub user_source: UncheckedAccount<'info>,
    #[account(mut)] /// CHECK:
    pub user_dest: UncheckedAccount<'info>,
    pub user_owner: Signer<'info>,
}

pub fn proxy_swap(
    ctx: Context<ProxyAmmV4Swap>,
    amount_in: u64,
    minimum_amount_out: u64,
) -> Result<()> {
    // SwapBaseIn의 명령어 판별자는 AMM v4에서 9입니다.
    let mut data = vec![9u8];
    data.extend_from_slice(&amount_in.to_le_bytes());
    data.extend_from_slice(&minimum_amount_out.to_le_bytes());

    let ix = Instruction {
        program_id: AMM_V4_PROGRAM_ID,
        accounts: vec![
            AccountMeta::new_readonly(ctx.accounts.token_program.key(), false),
            AccountMeta::new(ctx.accounts.amm.key(), false),
            AccountMeta::new_readonly(ctx.accounts.amm_authority.key(), false),
            AccountMeta::new(ctx.accounts.amm_open_orders.key(), false),
            AccountMeta::new(ctx.accounts.amm_target_orders.key(), false),
            AccountMeta::new(ctx.accounts.pool_coin_token_account.key(), false),
            AccountMeta::new(ctx.accounts.pool_pc_token_account.key(), false),
            AccountMeta::new_readonly(ctx.accounts.market_program.key(), false),
            AccountMeta::new(ctx.accounts.market.key(), false),
            AccountMeta::new(ctx.accounts.market_bids.key(), false),
            AccountMeta::new(ctx.accounts.market_asks.key(), false),
            AccountMeta::new(ctx.accounts.market_event_queue.key(), false),
            AccountMeta::new(ctx.accounts.market_coin_vault.key(), false),
            AccountMeta::new(ctx.accounts.market_pc_vault.key(), false),
            AccountMeta::new_readonly(ctx.accounts.market_vault_signer.key(), false),
            AccountMeta::new(ctx.accounts.user_source.key(), false),
            AccountMeta::new(ctx.accounts.user_dest.key(), false),
            AccountMeta::new_readonly(ctx.accounts.user_owner.key(), true),
        ],
        data,
    };
    invoke_signed(&ix, &ctx.accounts.to_account_infos(), &[])?;
    Ok(())
}
AMM v4는 CPI용 Anchor 크레이트를 제공하지 않습니다. 위의 스케치는 수동으로 구성된 Instruction을 사용합니다.

함정

  • OpenBook 계정 누락. 모든 8개의 OpenBook 계정은 모든 스왑, 입금 및 출금에 필요합니다. SDK는 이를 처리하지만 수동으로 구성된 명령어는 종종 그렇지 않습니다.
  • 원본 볼트 잔액 읽기. 온체인 예탁 금액이나 누적된 손익을 반영하지 않습니다. SDK의 견적 또는 api-v3.raydium.io/pools/info/ids를 사용하세요.
  • OpenBook 이벤트 큐 가득 찬 상태. 풀이 시장의 이벤트 큐가 크랭킹되어야 할 때 SerumOrderError로 스왑을 되돌릴 수 있습니다. 크랭킹은 무허가(시장의 OpenBook 계정에서 MonitorStep)입니다.
  • Token-2022 민트. 지원되지 않습니다. AMM v4 풀은 Token-2022 민트에 대해 생성될 수 없습니다. 모든 Token-2022 페어는 CPMM 또는 CLMM에 있어야 합니다.

다음으로 이동할 위치

출처: