メインコンテンツへスキップ

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 による自動翻訳です。すべての内容は英語版を正とします。英語版を表示 →
バージョン情報。 すべての TypeScript デモは、Solana mainnet-beta に対して @raydium-io/raydium-sdk-v2@0.2.42-alpha を対象としており、2026年4月時点で検証済みです。Rust CPI スケルトンは master ブランチの raydium-cp-swap を対象とし、Anchor 0.30.x に対応しています。プログラム ID は reference/program-addresses の定数から取得されます。

前提条件

npm install @raydium-io/raydium-sdk-v2 @solana/web3.js @solana/spl-token bn.js decimal.js
このページのすべてのデモは raydium-sdk-V2-demo/src/cpmm 内のファイルと対応しており、各セクションの横に GitHub リンクがあります。初期化はデモリポジトリの config.ts.template に従っています(ソース):
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",
  disableFeatureCheck: true,
  blockhashCommitment: "finalized",
});
Raydium インスタンスは SDK のファサードであり、以下のすべてのデモで使用されます。api-v3.raydium.io からトークンリストと手数料設定を遅延フェッチします。オフライン環境では独自データでシードすることができます。

CPMM プールの作成

ソース:src/cpmm/createCpmmPool.ts
import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";
import { getCpmmPdas, CREATE_CPMM_POOL_PROGRAM, CREATE_CPMM_POOL_FEE_ACC }
  from "@raydium-io/raydium-sdk-v2";

const mintA = new PublicKey("So11111111111111111111111111111111111111112"); // wSOL
const mintB = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"); // USDC

// 1. 手数料設定を選択する。index=0 は 0.25% ティア。
const feeConfigs = await raydium.api.getCpmmConfigs();
const feeConfig  = feeConfigs.find((c) => c.index === 0)!;

// 2. ミントメタデータを取得して、SDK が Token-2022 拡張機能を処理できるようにする。
const mintAInfo = await raydium.token.getTokenInfo(mintA);
const mintBInfo = await raydium.token.getTokenInfo(mintB);

// 3. トランザクションをビルドする。
const { execute, extInfo } = await raydium.cpmm.createPool({
  programId:       CREATE_CPMM_POOL_PROGRAM,
  poolFeeAccount:  CREATE_CPMM_POOL_FEE_ACC,
  mintA:           mintAInfo,
  mintB:           mintBInfo,
  mintAAmount:     new BN(1_000_000_000),   // 1 SOL (9 デシマル想定)
  mintBAmount:     new BN(   160_000_000),  // 160 USDC (160/SOL レート)
  startTime:       new BN(0),               // 即座に開始
  feeConfig,
  associatedOnly:  false,
  ownerInfo:       { useSOLBalance: true },
  txVersion:       TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
console.log("Pool created at", extInfo.address.poolId.toBase58());
console.log("Tx:", txId);
SDK が自動的に処理することがいくつかあります:
  • PDA を導出する前に、ミントを token0/token1 順にソートします。
  • ワンタイム create_pool_feepoolFeeAccount に支払います。
  • 呼び出し元の関連付けられたトークン アカウントがない場合は作成します。
  • 各側に対して正しいトークン プログラム(SPL Token または Token-2022)を選択します。
確認後、以下で ライブプール状態を取得できます:
const { poolKeys, poolInfo, rpcData } = await raydium.cpmm.getPoolInfoFromRpc(
  extInfo.address.poolId,
);

スワップ(ベース入力)

ソース:src/cpmm/swap.ts
import { CurveCalculator } from "@raydium-io/raydium-sdk-v2";

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

// 1. RPC から直接現在のプール状態をロードする(API からではなく)。
const { poolInfo, poolKeys, rpcData } = await raydium.cpmm.getPoolInfoFromRpc(poolId);

const inputMint  = new PublicKey(poolInfo.mintA.address); // A → B をスワップ
const amountIn   = new BN(100_000_000);                   // 0.1 SOL
const slippage   = 0.005;                                 // 0.5%

// 2. ローカルで見積もりを取得する。SDK の CurveCalculator は
//    両側の Token-2022 転送手数料を含む、オンチェーン計算を反映します。
const baseIn = inputMint.equals(new PublicKey(poolInfo.mintA.address));
const swapResult = CurveCalculator.swap(
  amountIn,
  baseIn ? rpcData.baseReserve : rpcData.quoteReserve,
  baseIn ? rpcData.quoteReserve : rpcData.baseReserve,
  rpcData.configInfo!.tradeFeeRate,
);
const minimumAmountOut =
  swapResult.destinationAmountSwapped.muln(1 - slippage * 100).divn(100);

// 3. ビルドして送信する。
const { execute } = await raydium.cpmm.swap({
  poolInfo,
  poolKeys,
  inputAmount: amountIn,
  swapResult,
  slippage,
  baseIn,
  txVersion: TxVersion.V0,
});

const { txId } = await execute({ sendAndConfirm: true });
console.log("Swap tx:", txId);
注意:SDK は getPoolInfoFromRpc の内部で常に RPC からプール状態を再フェッチします。署名しようとするトランザクションに対して api-v3.raydium.io から見積もりを取得しないでください。1ブロック古い見積もりはランド時に ExceededSlippage にスリップできます。

スワップ(ベース出力)

ソース:src/cpmm/swapBaseOut.ts
const amountOutWanted = new BN(15_000_000);        // 15 USDC
const slippage        = 0.005;

const baseIn = false; // B はインプット、A はアウトプット?方向に応じて
const swapResult = CurveCalculator.swapBaseOutput(
  amountOutWanted,
  rpcData.baseReserve,
  rpcData.quoteReserve,
  rpcData.configInfo!.tradeFeeRate,
);
const maxAmountIn = swapResult.sourceAmountSwapped.muln(1 + slippage * 100).divn(100);

const { execute } = await raydium.cpmm.swap({
  poolInfo,
  poolKeys,
  inputAmount: maxAmountIn,
  fixedOut:    true,
  amountOut:   amountOutWanted,
  baseIn,
  slippage,
  txVersion:   TxVersion.V0,
});

await execute({ sendAndConfirm: true });

流動性供給

ソース:src/cpmm/deposit.ts
const lpAmount = new BN(100_000);           // 希望する LP ミント量
const slippage = 0.01;

const { execute } = await raydium.cpmm.addLiquidity({
  poolInfo,
  poolKeys,
  lpAmount,
  slippage,
  baseIn: true,           // mintA 側から見積もり
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });
SDK は lpAmount をプールの現在のリザーブを使用して needed_token_0needed_token_1 に変換し、各インストラクションの maximum_* 引数用に 1 + slippage を乗じ、必要に応じて ATA 作成をビルドします。

流動性撤回

ソース:src/cpmm/withdraw.ts
const lpAmount = new BN(100_000);           // 焼却する LP
const slippage = 0.01;

const { execute } = await raydium.cpmm.withdrawLiquidity({
  poolInfo,
  poolKeys,
  lpAmount,
  slippage,
  txVersion: TxVersion.V0,
});

await execute({ sendAndConfirm: true });

プロトコル手数料・ファンド手数料・クリエーター手数料の収集

ソース:src/cpmm/collectCreatorFee.tssrc/cpmm/collectAllCreatorFee.ts これらのインストラクションは管理者またはクリエーター権限があり、通常は Raydium マルチシグまたはプール クリエーターが保有する署名者から呼び出されます。SDK はそれらをローレベルビルダーとして公開します:
import {
  makeCollectProtocolFeeInstruction,
  makeCollectFundFeeInstruction,
  makeCollectCreatorFeeInstruction,
} from "@raydium-io/raydium-sdk-v2";

// PDA と権限はプール作成時に設定されました。canonical seeds については
// reference/program-addresses を参照してください。SDK はお好みであれば
// ヘルパーを公開しています。
オフチェーンでは PoolState から直接蓄積手数料を読み取ることができます:
const pool = await raydium.cpmm.getRpcPoolInfo(poolId);
console.log("Accrued protocol fee token0:", pool.protocolFeesToken0.toString());
console.log("Accrued protocol fee token1:", pool.protocolFeesToken1.toString());

Rust CPI スケルトン

独自の Anchor プログラムから CPMM を呼び出したい場合(例えば、預金者に代わってスワップを行うボールト)、CPI コンテキストは次のようになります。アカウント順は products/cpmm/instructions に従います。
// Cargo.toml
// raydium-cp-swap = { git = "https://github.com/raydium-io/raydium-cp-swap" }
// anchor-spl       = "0.30"

use anchor_lang::prelude::*;
use anchor_spl::token_interface::{TokenAccount, TokenInterface, Mint};
use raydium_cp_swap::cpi::accounts::Swap;
use raydium_cp_swap::cpi;
use raydium_cp_swap::program::RaydiumCpSwap;

#[derive(Accounts)]
pub struct ProxySwap<'info> {
    #[account(mut)]
    pub payer: Signer<'info>,

    /// CHECK: validated by the CPMM program
    pub authority:     UncheckedAccount<'info>,
    /// CHECK:
    pub amm_config:    UncheckedAccount<'info>,
    #[account(mut)]
    /// CHECK:
    pub pool_state:    UncheckedAccount<'info>,

    #[account(mut)]
    pub input_token_account:  InterfaceAccount<'info, TokenAccount>,
    #[account(mut)]
    pub output_token_account: InterfaceAccount<'info, TokenAccount>,

    #[account(mut)]
    pub input_vault:  InterfaceAccount<'info, TokenAccount>,
    #[account(mut)]
    pub output_vault: InterfaceAccount<'info, TokenAccount>,

    pub input_token_program:  Interface<'info, TokenInterface>,
    pub output_token_program: Interface<'info, TokenInterface>,

    pub input_token_mint:  InterfaceAccount<'info, Mint>,
    pub output_token_mint: InterfaceAccount<'info, Mint>,

    #[account(mut)]
    /// CHECK: ring buffer
    pub observation_state: UncheckedAccount<'info>,

    pub cpmm_program: Program<'info, RaydiumCpSwap>,
}

pub fn proxy_swap_base_input(
    ctx: Context<ProxySwap>,
    amount_in: u64,
    minimum_amount_out: u64,
) -> Result<()> {
    let cpi_accounts = Swap {
        payer:                ctx.accounts.payer.to_account_info(),
        authority:            ctx.accounts.authority.to_account_info(),
        amm_config:           ctx.accounts.amm_config.to_account_info(),
        pool_state:           ctx.accounts.pool_state.to_account_info(),
        input_token_account:  ctx.accounts.input_token_account.to_account_info(),
        output_token_account: ctx.accounts.output_token_account.to_account_info(),
        input_vault:          ctx.accounts.input_vault.to_account_info(),
        output_vault:         ctx.accounts.output_vault.to_account_info(),
        input_token_program:  ctx.accounts.input_token_program.to_account_info(),
        output_token_program: ctx.accounts.output_token_program.to_account_info(),
        input_token_mint:     ctx.accounts.input_token_mint.to_account_info(),
        output_token_mint:    ctx.accounts.output_token_mint.to_account_info(),
        observation_state:    ctx.accounts.observation_state.to_account_info(),
    };
    let cpi_ctx = CpiContext::new(
        ctx.accounts.cpmm_program.to_account_info(),
        cpi_accounts,
    );
    cpi::swap_base_input(cpi_ctx, amount_in, minimum_amount_out)
}
CPI が PDA として署名する場合(例えば、預金者に代わってボールトを管理している場合)、CpiContext::newCpiContext::new_with_signer に置き換え、シードを渡してください。

よくあるミス

サポート チケットを開く前の簡単なチェックリスト:
  • ソート済みミント。 導出した poolState PDA がオンチェーン プールと一致しない場合は、ミントをソートするのを忘れた可能性があります。
  • 古い API 見積もり。 api-v3.raydium.io からのリザーブ値を CurveCalculator.swap に渡さないようにしてください。RPC からフェッチしてください。
  • 間違ったトークン プログラム。 Token-2022 ミントのボールトは SPL Token ではなく Token-2022 プログラムで管理されています。常にプールの token_0_program / token_1_program フィールドを使用してください。
  • 転送手数料ミント用の不十分なスリッページ。 プールのどちらかが Token-2022 転送手数料ミントの場合、minimum_amount_out はボールトが送信するもの(金額)ではなく、ユーザーが実際に受け取るもの(金額)を単位として表す必要があります。
  • スワップで NotApproved PoolState.status を確認してください。管理者がそのプールでスワップを一時停止している可能性があります。ステータス ビットマスクについては products/cpmm/instructions を参照してください。

次のステップ

ソース: