ローンチタイプ
ボンディングカーブ スワップ統合
Last updated April 9, 2026
Genesis SDKを使用してボンディングカーブの状態を読み取り、スワップ見積もりを計算し、売買トランザクションをオンチェーンで実行し、スリッページを処理し、クリエイター手数料を請求します。
構築する内容
このガイドでは以下をカバーします:
BondingCurveBucketV2アカウント状態の取得と解釈isSwappable、isSoldOut、isGraduatedでのライフサイクルステータスの確認getSwapResultによる正確なスワップ見積もりの取得applySlippageによるユーザーの保護swapBondingCurveV2での売買トランザクションの構築- カーブとグラデュエーション後のRaydiumプールからのクリエイター手数料の請求
Summary
ボンディングカーブのスワップはGenesis SDKを使用して BondingCurveBucketV2 オンチェーンアカウントを操作します — SOLを受け取りトークンを返す(購入)、またはトークンを受け取りSOLを返す(売却)定積AMMです。価格計算の基礎数学については動作理論を参照してください。
- 送信前に見積もりを取得 —
getSwapResultで正確な手数料調整後の入出力金額を取得する - スリッページ保護 —
applySlippageでminAmountOutScaledを導出し、インストラクションに渡す - wSOLは手動 — スワップインストラクションはネイティブSOLをラップ・アンラップしない。呼び出し元が自分でwSOL ATAを処理する必要がある
- プログラムID — Solanaメインネット上の
GNS1S5J5AspKXgpjz6SvKL66kPaKWAhaGRhCqPRxii2B
クイックスタート
ジャンプ: インストール · セットアップ · カーブの取得 · ライフサイクルヘルパー · 見積もり · スリッページ · スワップの実行 · クリエイター手数料 · エラー · APIリファレンス
- パッケージをインストールして
genesis()プラグインでUmiインスタンスを設定する BondingCurveBucketV2Pdaを導出してアカウントを取得するisSwappable(bucket)を確認 — falseの場合は中止するgetSwapResult(bucket, amountIn, SwapDirection.Buy)で手数料調整済み見積もりを取得するapplySlippage(quote.amountOut, slippageBps)を適用してminAmountOutScaledを取得する- wSOLのラッピングを手動で処理してから
swapBondingCurveV2を送信して確認する
前提条件
- Node.js 18+ — ネイティブBigIntサポートに必要
- Solanaウォレット — トランザクション手数料とスワップ入力のためのSOLが入金されている
- SolanaのRPCエンドポイント(mainnet-betaまたはdevnet)
- Umiフレームワークとasync/awaitパターンへの慣れ
テスト済み構成
| ツール | バージョン |
|---|---|
@metaplex-foundation/genesis | 1.x |
@metaplex-foundation/umi | 1.x |
@metaplex-foundation/umi-bundle-defaults | 1.x |
| Node.js | 18+ |
インストール
npm install @metaplex-foundation/genesis \
@metaplex-foundation/umi \
@metaplex-foundation/umi-bundle-defaults
UmiとGenesisプラグインのセットアップ
SDK関数を呼び出す前に、Umiインスタンスを設定して genesis() プラグインを登録します。
1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
2import { genesis } from '@metaplex-foundation/genesis';
3import { keypairIdentity } from '@metaplex-foundation/umi';
4import { readFileSync } from 'fs';
5
6const keypairFile = JSON.parse(readFileSync('/path/to/keypair.json', 'utf-8'));
7
8const umi = createUmi('https://api.mainnet-beta.solana.com')
9 .use(genesis());
10
11const keypair = umi.eddsa.createKeypairFromSecretKey(Uint8Array.from(keypairFile));
12umi.use(keypairIdentity(keypair));
ボンディングカーブBucketV2の取得
すでに知っていることに応じて、3つの検出戦略が利用可能です。
既知のGenesisアカウントから取得する
1import {
2 findBondingCurveBucketV2Pda,
3 fetchBondingCurveBucketV2,
4 genesis,
5} from '@metaplex-foundation/genesis';
6import { publicKey } from '@metaplex-foundation/umi';
7import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
8
9const umi = createUmi('https://api.mainnet-beta.solana.com').use(genesis());
10
11const genesisAccount = publicKey('YOUR_GENESIS_ACCOUNT_PUBKEY');
12
13const [bucketPda] = findBondingCurveBucketV2Pda(umi, {
14 genesisAccount,
15 bucketIndex: 0,
16});
17
18const bucket = await fetchBondingCurveBucketV2(umi, bucketPda);
1mplx genesis bucket fetch <GENESIS_ACCOUNT> --type bonding-curve
トークンミントから取得する
1import {
2 findGenesisAccountV2Pda,
3 findBondingCurveBucketV2Pda,
4 fetchBondingCurveBucketV2,
5} from '@metaplex-foundation/genesis';
6import { publicKey } from '@metaplex-foundation/umi';
7
8const baseMint = publicKey('TOKEN_MINT_PUBKEY');
9
10const [genesisAccount] = findGenesisAccountV2Pda(umi, {
11 baseMint,
12 genesisIndex: 0,
13});
14
15const [bucketPda] = findBondingCurveBucketV2Pda(umi, {
16 genesisAccount,
17 bucketIndex: 0,
18});
19
20const bucket = await fetchBondingCurveBucketV2(umi, bucketPda);
ボンディングカーブBucketV2の状態を読み取る
| フィールド | 型 | 説明 |
|---|---|---|
baseTokenBalance | bigint | カーブに残っているトークン。ゼロは売り切れを意味する。 |
baseTokenAllocation | bigint | 作成時にこのカーブに割り当てられた総トークン数。 |
quoteTokenDepositTotal | bigint | 購入者が入金した実際のSOL(ラムポート)。0から始まる。 |
virtualSol | bigint | 初期化時に追加された仮想SOLリザーブ(価格計算のみ)。 |
virtualTokens | bigint | 初期化時に追加された仮想トークンリザーブ(価格計算のみ)。 |
depositFee | number | すべてのスワップのSOL側に適用されるプロトコル手数料率。 |
withdrawFee | number | 売却のSOL出力側に適用されるプロトコル手数料率。 |
creatorFeeAccrued | bigint | 最後の請求以降に蓄積したクリエイター手数料(ラムポート)。 |
creatorFeeClaimed | bigint | 今日までの累計請求済みクリエイター手数料(ラムポート)。 |
swapStartCondition | object | 取引が許可される前に満たされなければならない条件。 |
swapEndCondition | object | トリガーされると取引を終了させる条件。 |
virtualSol と virtualTokens は価格計算にのみ存在します — 実際にはオンチェーンにリアルアセットとして入金されません。仮想リザーブが定積カーブをどのように形成するかについては動作理論を参照してください。
ボンディングカーブライフサイクルヘルパー
5つのヘルパー関数が追加のRPC呼び出しなしにカーブの状態を確認します(isGraduated を除く)。
1import {
2 isSwappable,
3 isFirstBuyPending,
4 isSoldOut,
5 getFillPercentage,
6 isGraduated,
7} from '@metaplex-foundation/genesis';
8
9const canSwap = isSwappable(bucket);
10const firstBuyPending = isFirstBuyPending(bucket);
11const soldOut = isSoldOut(bucket);
12const fillPercent = getFillPercentage(bucket);
13const graduated = await isGraduated(umi, bucket); // 非同期RPC呼び出し
| ヘルパー | 非同期 | 戻り値 | 説明 |
|---|---|---|---|
isSwappable(bucket) | いいえ | boolean | パブリックトレードを受け付けているとき true |
isFirstBuyPending(bucket) | いいえ | boolean | 指定されたファーストバイがまだ完了していないとき true |
isSoldOut(bucket) | いいえ | boolean | baseTokenBalance === 0n のとき true |
getFillPercentage(bucket) | いいえ | number | 売却済み割り当ての0〜100パーセント |
isGraduated(umi, bucket) | はい | boolean | Raydium CPMMプールがオンチェーンに存在するとき true |
スワップ見積もりの取得
getSwapResult(bucket, amountIn, swapDirection, isFirstBuy?) はトランザクションを送信せずに、スワップの正確な手数料調整済み金額を計算します。
{ amountIn, fee, creatorFee, amountOut } を返します:
amountIn— 調整後の実際の入力金額fee— 請求されるプロトコル手数料(ラムポート単位)creatorFee— 請求されるクリエイター手数料(ラムポート単位、クリエイター手数料未設定の場合は0)amountOut— 受け取るトークン(購入)またはSOL(売却)
購入見積もり(SOLからトークン)
1import {
2 genesis,
3 findBondingCurveBucketV2Pda,
4 fetchBondingCurveBucketV2,
5 getSwapResult,
6} from '@metaplex-foundation/genesis';
7import { publicKey } from '@metaplex-foundation/umi';
8import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
9
10const umi = createUmi('https://api.mainnet-beta.solana.com').use(genesis());
11
12const genesisAccount = publicKey('YOUR_GENESIS_ACCOUNT_PUBKEY');
13const [bucketPda] = findBondingCurveBucketV2Pda(umi, { genesisAccount, bucketIndex: 0 });
14const bucket = await fetchBondingCurveBucketV2(umi, bucketPda);
15
16const SOL_IN = 1_000_000_000n; // 1 SOL in lamports
17
18const buyQuote = getSwapResult(bucket, SOL_IN, 'buy');
19
20console.log('SOL input: ', buyQuote.amountIn.toString(), 'lamports');
21console.log('Total fee: ', buyQuote.fee.toString(), 'lamports');
22console.log('Tokens out: ', buyQuote.amountOut.toString());
23
24// SOL input: 1000000000 lamports
25// Total fee: 10000000 lamports
26// Tokens out: <calculated token amount>
1# Get a buy quote without executing a swap (--info flag)
2mplx genesis swap <GENESIS_ACCOUNT> --info --buyAmount 1000000000
売却見積もり(トークンからSOL)
1import {
2 genesis,
3 findBondingCurveBucketV2Pda,
4 fetchBondingCurveBucketV2,
5 getSwapResult,
6} from '@metaplex-foundation/genesis';
7import { publicKey } from '@metaplex-foundation/umi';
8import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
9
10const umi = createUmi('https://api.mainnet-beta.solana.com').use(genesis());
11
12const genesisAccount = publicKey('YOUR_GENESIS_ACCOUNT_PUBKEY');
13const [bucketPda] = findBondingCurveBucketV2Pda(umi, { genesisAccount, bucketIndex: 0 });
14const bucket = await fetchBondingCurveBucketV2(umi, bucketPda);
15
16const TOKENS_IN = 500_000_000_000n; // 500 tokens (9 decimals)
17
18const sellQuote = getSwapResult(bucket, TOKENS_IN, 'sell');
19
20console.log('Tokens input: ', sellQuote.amountIn.toString());
21console.log('Total fee: ', sellQuote.fee.toString(), 'lamports');
22console.log('SOL out: ', sellQuote.amountOut.toString(), 'lamports');
23
24// Tokens input: 500000000000
25// Total fee: <fee in lamports>
26// SOL out: <calculated SOL amount>
1# Get a sell quote without executing a swap (--info flag)
2mplx genesis swap <GENESIS_ACCOUNT> --info --sellAmount 500000000000
ファーストバイ手数料免除
手数料を免除したファーストバイを見積もるには、4番目の引数として true を渡します:
1const firstBuyQuote = getSwapResult(bucket, SOL_IN, SwapDirection.Buy, true);
2console.log('Fee (waived): ', firstBuyQuote.fee.toString()); // 0n
現在の価格ヘルパー
1import {
2 getCurrentPrice,
3 getCurrentPriceQuotePerBase,
4 getCurrentPriceComponents,
5} from '@metaplex-foundation/genesis';
6
7const tokensPerSol = getCurrentPrice(bucket); // bigint
8const lamportsPerToken = getCurrentPriceQuotePerBase(bucket); // bigint
9const { baseReserves, quoteReserves } = getCurrentPriceComponents(bucket);
スリッページ保護
applySlippage(expectedAmountOut, slippageBps) は期待される出力をスリッページ許容範囲で減らします。結果を minAmountOutScaled としてスワップインストラクションに渡します — オンチェーンプログラムは実際の出力がこの値を下回った場合にトランザクションを拒否します。
1import { getSwapResult, applySlippage, SwapDirection } from '@metaplex-foundation/genesis';
2
3const quote = getSwapResult(bucket, 1_000_000_000n, SwapDirection.Buy);
4const minAmountOutScaled = applySlippage(quote.amountOut, 100); // 1%スリッページ
applySlippage から導出した minAmountOutScaled なしでスワップを送信しないでください。ボンディングカーブの価格はすべての取引で変化します。スリッページ保護なしでは、ユーザーが見積もりより大幅に少ないトークンを受け取る可能性があります。
一般的な値:安定した条件では50 bps(0.5%)、ボラティリティの高いローンチ中は200 bps(2%)。
スワップトランザクションの構築
swapBondingCurveV2(umi, accounts) はスワップインストラクションを構築します。呼び出し元はトランザクションの前後でラップドSOL(wSOL)の処理を担当します。
購入トランザクション(SOLからトークン)
1import {
2 genesis,
3 findBondingCurveBucketV2Pda,
4 fetchBondingCurveBucketV2,
5 getSwapResult,
6 applySlippage,
7 swapBondingCurveV2,
8 isSwappable,
9} from '@metaplex-foundation/genesis';
10import { findAssociatedTokenPda } from '@metaplex-foundation/mpl-toolbox';
11import { publicKey } from '@metaplex-foundation/umi';
12import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
13
14const umi = createUmi('https://api.mainnet-beta.solana.com').use(genesis());
15
16const genesisAccount = publicKey('YOUR_GENESIS_ACCOUNT_PUBKEY');
17const baseMint = publicKey('TOKEN_MINT_PUBKEY');
18const quoteMint = publicKey('So11111111111111111111111111111111111111112'); // wSOL
19
20const [bucketPda] = findBondingCurveBucketV2Pda(umi, { genesisAccount, bucketIndex: 0 });
21const bucket = await fetchBondingCurveBucketV2(umi, bucketPda);
22
23if (!isSwappable(bucket)) throw new Error('Curve is not currently accepting swaps');
24
25const SOL_IN = 1_000_000_000n; // 1 SOL in lamports
26const quote = getSwapResult(bucket, SOL_IN, 'buy');
27const minAmountOut = applySlippage(quote.amountOut, 100); // 1% slippage
28
29const [userBaseTokenAccount] = findAssociatedTokenPda(umi, { mint: baseMint, owner: umi.identity.publicKey });
30const [userQuoteTokenAccount] = findAssociatedTokenPda(umi, { mint: quoteMint, owner: umi.identity.publicKey });
31
32// NOTE: Fund the wSOL ATA before this call — see the wSOL Wrapping Note on this page.
33const result = await swapBondingCurveV2(umi, {
34 genesisAccount,
35 bucketPda,
36 baseMint,
37 quoteMint,
38 userBaseTokenAccount,
39 userQuoteTokenAccount,
40 amountIn: quote.amountIn,
41 minAmountOut,
42 direction: 'buy',
43}).sendAndConfirm(umi);
44
45console.log('Buy confirmed:', result.signature);
46
47// Buy confirmed: <base58 transaction signature>
1# Buy tokens — SOL is wrapped automatically
2# --buyAmount is in lamports (1 SOL = 1000000000)
3mplx genesis swap <GENESIS_ACCOUNT> --buyAmount 1000000000
4
5# With custom slippage (100 bps = 1%)
6mplx genesis swap <GENESIS_ACCOUNT> --buyAmount 1000000000 --slippage 100
売却トランザクション(トークンからSOL)
1import {
2 genesis,
3 findBondingCurveBucketV2Pda,
4 fetchBondingCurveBucketV2,
5 getSwapResult,
6 applySlippage,
7 swapBondingCurveV2,
8} from '@metaplex-foundation/genesis';
9import { findAssociatedTokenPda } from '@metaplex-foundation/mpl-toolbox';
10import { publicKey } from '@metaplex-foundation/umi';
11import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
12
13const umi = createUmi('https://api.mainnet-beta.solana.com').use(genesis());
14
15const genesisAccount = publicKey('YOUR_GENESIS_ACCOUNT_PUBKEY');
16const baseMint = publicKey('TOKEN_MINT_PUBKEY');
17const quoteMint = publicKey('So11111111111111111111111111111111111111112'); // wSOL
18
19const [bucketPda] = findBondingCurveBucketV2Pda(umi, { genesisAccount, bucketIndex: 0 });
20const bucket = await fetchBondingCurveBucketV2(umi, bucketPda);
21
22const [userBaseTokenAccount] = findAssociatedTokenPda(umi, { mint: baseMint, owner: umi.identity.publicKey });
23const [userQuoteTokenAccount] = findAssociatedTokenPda(umi, { mint: quoteMint, owner: umi.identity.publicKey });
24
25const TOKENS_IN = 500_000_000_000n; // 500 tokens (9 decimals)
26const quote = getSwapResult(bucket, TOKENS_IN, 'sell');
27const minAmountOut = applySlippage(quote.amountOut, 100); // 1% slippage
28
29const result = await swapBondingCurveV2(umi, {
30 genesisAccount,
31 bucketPda,
32 baseMint,
33 quoteMint,
34 userBaseTokenAccount,
35 userQuoteTokenAccount,
36 amountIn: quote.amountIn,
37 minAmountOut,
38 direction: 'sell',
39}).sendAndConfirm(umi);
40
41// NOTE: Close the wSOL ATA after confirming to unwrap back to native SOL.
42console.log('Sell confirmed:', result.signature);
43
44// Sell confirmed: <base58 transaction signature>
1# Sell tokens — SOL is unwrapped automatically
2# --sellAmount is in base token units (with decimals)
3mplx genesis swap <GENESIS_ACCOUNT> --sellAmount 500000000000
4
5# With custom slippage (100 bps = 1%)
6mplx genesis swap <GENESIS_ACCOUNT> --sellAmount 500000000000 --slippage 100
wSOLラッピングに関する注意
wSOLの手動処理が必要
swapBondingCurveV2 はクォートトークンとしてラップドSOL(wSOL)を使用し、ネイティブSOLを自動的にラップ・アンラップしません。
購入の場合: wSOL ATAを作成し、必要なラムポートを転送して、スワップを送信する前に syncNative を呼び出してください。
売却の場合: スワップが確認された後にwSOL ATAを閉じてネイティブSOLにアンラップしてください。
現在のバージョンでは、クォートトークンとしてwSOLのみが受け入れられます。
1import {
2 findAssociatedTokenPda,
3 createAssociatedTokenAccountIdempotentInstruction,
4 syncNative,
5 closeToken,
6} from '@metaplex-foundation/mpl-toolbox';
7import { transactionBuilder, sol, publicKey } from '@metaplex-foundation/umi';
8
9const wSOL = publicKey('So11111111111111111111111111111111111111112');
10const [wSolAta] = findAssociatedTokenPda(umi, { mint: wSOL, owner: umi.identity.publicKey });
11
12// --- 購入前にSOLをラップする ---
13const wrapBuilder = transactionBuilder()
14 .add(createAssociatedTokenAccountIdempotentInstruction(umi, {
15 mint: wSOL,
16 owner: umi.identity.publicKey,
17 }))
18 .add(syncNative(umi, { account: wSolAta }));
19
20await wrapBuilder.sendAndConfirm(umi);
21
22// --- 売却後にSOLをアンラップする ---
23const unwrapBuilder = closeToken(umi, {
24 account: wSolAta,
25 destination: umi.identity.publicKey,
26 authority: umi.identity,
27});
28
29await unwrapBuilder.sendAndConfirm(umi);
クリエイター手数料の請求
クリエイター手数料はスワップごとに直接転送されるのではなく、バケット(creatorFeeAccrued)に蓄積されます。カーブがアクティブな間はパーミッションレスの claimBondingCurveCreatorFeeV2 インストラクションで、グラデュエーション後は claimRaydiumCreatorFeeV2 で回収します。
蓄積残高の確認方法やグラデュエーション後のRaydium LP手数料の処理を含む完全な請求フローについては、クリエイター手数料を参照してください。
エラーハンドリング
| エラー | 原因 | 対処法 |
|---|---|---|
BondingCurveInsufficientFunds | 残りのトークン(購入)またはSOL(売却)が不足している | バケットを再取得して再見積もりする。カーブがほぼ売り切れの可能性がある |
InsufficientOutputAmount | 実際の出力が minAmountOutScaled を下回った | slippageBps を増やすか、すぐに再試行する |
InvalidSwapDirection | swapDirection の値が無効 | @metaplex-foundation/genesis インポートから SwapDirection.Buy または SwapDirection.Sell を渡す |
BondingCurveNotStarted | swapStartCondition がまだ満たされていない | bucket.swapStartCondition を確認して待つ |
BondingCurveEnded | カーブが売り切れまたはグラデュエーション済み | ユーザーをRaydium CPMMプールに誘導する |
1async function executeBuy(bucket, amountIn: bigint, slippageBps: number) {
2 if (!isSwappable(bucket)) {
3 if (isSoldOut(bucket)) throw new Error('Token sold out. Trade on Raydium.');
4 throw new Error('Curve not yet active. Check the start time.');
5 }
6
7 const quote = getSwapResult(bucket, amountIn, SwapDirection.Buy);
8 const minAmountOutScaled = applySlippage(quote.amountOut, slippageBps);
9
10 try {
11 return await swapBondingCurveV2(umi, {
12 amount: quote.amountIn,
13 minAmountOutScaled,
14 swapDirection: SwapDirection.Buy,
15 // ... アカウント
16 }).sendAndConfirm(umi);
17 } catch (err: any) {
18 if (err.message?.includes('InsufficientOutputAmount'))
19 throw new Error('Price moved. Try again with higher slippage.');
20 if (err.message?.includes('BondingCurveInsufficientFunds'))
21 throw new Error('Not enough tokens remaining. Reduce amount.');
22 throw err;
23 }
24}
Notes
- 本番環境ではスワップごとにバケットを再取得してください — 他のユーザーの取引ごとに価格が変わります
virtualSolとvirtualTokensはカーブ作成後は不変です — キャッシュしてください。リアルリザーブフィールドのみスワップごとに変化しますisGraduatedは呼び出しのたびにRPC呼び出しを行います — インデクサーで結果をキャッシュしてくださいisSoldOutがtrueを返してからisGraduatedがtrueを返すまでの間、カーブは売り切れてもRaydiumはまだ資金調達されていません。isGraduatedがプールの存在を確認するまでユーザーをRaydiumに誘導しないでください- イベントのデコードとライフサイクルのインデックス作成についてはインデックス作成とイベントを参照してください
- すべての手数料金額はラムポート(SOL側)です。現在の手数料率についてはプロトコル手数料を参照してください
APIリファレンス
見積もりと価格関数
| 関数 | 非同期 | 戻り値 | 説明 |
|---|---|---|---|
getSwapResult(bucket, amountIn, swapDirection, isFirstBuy?) | いいえ | { amountIn, fee, creatorFee, amountOut } | 手数料調整済みスワップ見積もり |
getCurrentPrice(bucket) | いいえ | bigint | SOL単位あたりのベーストークン(整数除算) |
getCurrentPriceQuotePerBase(bucket) | いいえ | bigint | ベーストークン単位あたりのラムポート(整数除算) |
getCurrentPriceComponents(bucket) | いいえ | { baseReserves, quoteReserves } | bigintとして結合した仮想+リアルリザーブ |
ライフサイクル関数
| 関数 | 非同期 | 戻り値 | 説明 |
|---|---|---|---|
isSwappable(bucket) | いいえ | boolean | パブリックトレードを受け付けているとき true |
isFirstBuyPending(bucket) | いいえ | boolean | 指定されたファーストバイがまだ完了していないとき true |
isSoldOut(bucket) | いいえ | boolean | baseTokenBalance === 0n のとき true |
getFillPercentage(bucket) | いいえ | number | 売却済み割り当ての0〜100パーセント |
isGraduated(umi, bucket) | はい | boolean | Raydium CPMMプールがオンチェーンに存在するとき true |
スリッページ
| 関数 | 戻り値 | 説明 |
|---|---|---|
applySlippage(amountOut, slippageBps) | bigint | amountOut を slippageBps / 10_000 で減らす |
スワップインストラクションアカウント
| アカウント | 書き込み可能 | 署名者 | 説明 |
|---|---|---|---|
genesisAccount | はい | いいえ | Genesis調整PDA |
bucket | はい | いいえ | BondingCurveBucketV2 PDA |
baseMint | いいえ | いいえ | SPLトークンミント |
quoteMint | いいえ | いいえ | wSOLミント |
baseTokenAccount | はい | いいえ | ユーザーのベーストークンATA |
quoteTokenAccount | はい | いいえ | ユーザーのwSOL ATA |
payer | はい | はい | トランザクション手数料の支払者 |
アカウント検出
| 関数 | 戻り値 | 説明 |
|---|---|---|
findBondingCurveBucketV2Pda(umi, { genesisAccount, bucketIndex }) | [PublicKey, bump] | バケットPDAを導出する |
findGenesisAccountV2Pda(umi, { baseMint, genesisIndex }) | [PublicKey, bump] | genesisアカウントPDAを導出する |
fetchBondingCurveBucketV2(umi, pda) | BondingCurveBucketV2 | アカウントを取得してデシリアライズする |
FAQ
isSwappableとisSoldOutの違いは何ですか?
isSwappable はカーブがアクティブにパブリックトレードを受け付けているときのみ true を返します。isSoldOut は baseTokenBalance がゼロになった瞬間に true を返し、取引が終了してグラデュエーションがトリガーされます。カーブは売り切れでもまだグラデュエーションしていない場合があります。
swapBondingCurveV2を呼び出す前にSOLをラップする必要がありますか?
はい。ボンディングカーブはクォートトークンとしてwSOLを使用し、swapBondingCurveV2 はネイティブSOLを自動的にラップ・アンラップしません。wSOLラッピングに関する注意を参照してください。
getSwapResultは何を返し、手数料はどのように処理されますか?
getSwapResult は { amountIn, fee, creatorFee, amountOut } を返します。購入の場合、手数料はAMM公式が実行される前にSOL入力から差し引かれます。売却の場合、手数料はAMM実行後にSOL出力から差し引かれます。ファーストバイ手数料免除のシミュレーション(すべての手数料をゼロにする)には、4番目の引数として true を渡してください。
スリッページから保護するにはどうすればよいですか?
applySlippage(quote.amountOut, slippageBps) を呼び出して minAmountOutScaled を導出し、swapBondingCurveV2 に minAmountOutScaled フィールドとして渡してください。オンチェーンプログラムは実際の出力がこの値を下回った場合にトランザクションを拒否します。
