carbium について
Carbium は、Solana 開発者向けインフラの接続方法をまとめたスキルです。RPC、WebSocket、gRPC の全ブロックストリーミング、DEX 集約 Swap API を扱い、アカウント参照やリアルタイム購読、プログラムからのスワップを説明します。
主な機能
- 01Solana JSON-RPC の読み書きと購読
- 02WebSocket によるアカウント・トランザクション通知
- 03Yellowstone の全ブロックストリーミング
- 04DEX の見積もり集約とスワップ実行
- 05Jito バンドルとガスレススワップの選択肢
活用シーン
- 01アカウント残高の参照とトランザクション送信
- 02ウォレットやプログラムログのリアルタイム監視
- 03全ブロックとトランザクションのストリーム処理
- 04DEX 見積もりの比較とスワップ実行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sendaifun/ skills --skill carbiumインストール後、Claude Code で/carbiumを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
docs/migration.mdtrading-bots.mdtroubleshooting.mdexamples/gasless-swap/README.mdexamples/grpc-stream/README.mdexamples/pump-snipe/README.mdexamples/rpc-basic/README.mdexamples/swap-bundle/README.mdexamples/swap-quote/README.mdexamples/websocket-monitor/README.mdresources/endpoints-and-auth.mdgrpc-reference.mdswap-api-reference.mdwebsocket-reference.mdtemplates/carbium-setup.ts詳細
Carbium — Solana フルスタックインフラストラクチャ
Carbium はベアメタルの Solana インフラストラクチャです。スイスの技術で設計され、クラウド事業者を介しません。トランザクションのライフサイクル全体をカバーする単一のプラットフォームです。
概要
| 製品 | エンドポイント | 用途 |
|---|---|---|
| RPC | https://rpc.carbium.io | 読み取り、書き込み、サブスクリプションに対応する標準 JSON-RPC |
| 標準 WebSocket | wss://wss-rpc.carbium.io | Solana ネイティブの pubsub(アカウント変更、スロット、ログ、署名) |
| gRPC / Stream | wss://grpc.carbium.io | Yellowstone のフルブロックストリーミング(レイテンシ約 22ms) |
| Swap API | https://api.carbium.io | CQ1 エンジンを活用した DEX アグリゲーションと実行 |
| DEX アプリ | https://app.carbium.io | 一般ユーザー向けの取引インターフェース |
| ドキュメント | https://docs.carbium.io | ドキュメント一式 |
主な差別化要因:
- CQ1 ルーティングエンジンとバイナリネイティブの状態管理による、1 ミリ秒未満の DEX 見積もり
- 約 22ms のフルブロック gRPC — アトミックで完全なブロック(シュレッドの再構築は不要)
- ガスレススワップ — ユーザーは SOL を保有せずに取引できます
- MEV 保護 — Jito バンドリングが Swap API に組み込まれています
- スイスのベアメタルサーバー — RPC レイテンシ 50ms 未満、稼働率 99.99%
このスキルを使う場面
| やりたいこと | 使用するもの | 必要なキー |
|---|---|---|
| アカウントデータや残高を読み取る | RPC | RPC キー |
| トランザクションを送信する | RPC | RPC キー |
| ウォレットをリアルタイムで監視する | 標準 WebSocket | RPC キー |
| ポーリングせずにトランザクションを確認する | 標準 WebSocket | RPC キー |
| プログラムアカウントの変更を監視する | 標準 WebSocket | RPC キー |
| ウォレットアプリを構築する | RPC + Swap API | 両方 |
| トークンスワップの見積もりを取得する | Swap API | API キー |
| プログラムからスワップを実行する | Swap API | API キー |
| Jito バンドリングでスワップを実行する | Swap API(バンドルエンドポイント) | API キー |
| すべての DEX プロバイダーの見積もりを比較する | Swap API(quote/all) | API キー |
| ユーザーが SOL を保有せずにスワップする | Swap API(gasless フラグ) | API キー |
| pump.fun トークンをスナイプする(卒業前) | gRPC + ボンディングカーブへの直接 tx | RPC キー(Business 以上) |
| オンチェーンイベントにリアルタイムで反応する | gRPC(ストリーミング) | RPC キー(Business 以上) |
| プログラムのトランザクションをインデックス化する | gRPC(ストリーミング) | RPC キー(Business 以上) |
| アービトラージ/MEV ボットを構築する | gRPC + Swap API | 両方 |
クイックスタート
1. API キーを取得する
| 製品 | サインアップ | 備考 |
|---|---|---|
| RPC + gRPC + WebSocket | rpc.carbium.io/signup | 1 つのキーで RPC、WebSocket、gRPC を利用できます |
| Swap API | api.carbium.io/login | 別のキーが必要です。無料アカウントですぐに利用できます |
プログラムによるキーの発行にはまだ対応していません。キーはダッシュボードから作成する必要があります。
2. 環境変数を設定する
export CARBIUM_RPC_KEY="your-rpc-key"
export CARBIUM_API_KEY="your-swap-api-key"
3. セキュリティルール(必須)
- キーをフロントエンドやクライアント側のコードに埋め込まないでください
- キーをバージョン管理にコミットしないでください
- 環境変数
CARBIUM_RPC_KEY、CARBIUM_API_KEYを使用してください - キーが漏えいした場合は、直ちにローテーションしてください
- キーはサーバー側だけで管理してください
料金プラン
| プラン | 価格 | 月間クレジット | 最大 RPS | gRPC | WebSocket |
|---|---|---|---|---|---|
| Free | $0 | 500K | 10 | なし | あり |
| Developer | $32/mo | 10M | 50 | なし | あり |
| Business | $320/mo | 100M | 200 | あり | あり |
| Professional | $640/mo | 200M | 500 | あり | あり |
gRPC ストリーミングを利用するには、Business 以上のプランが必要です。
RPC
標準の Solana JSON-RPC です。@solana/web3.js、solana-py、solana Rust クレートなど、あらゆる Solana SDK を利用できます。
エンドポイント:
https://rpc.carbium.io/?apiKey=YOUR_RPC_KEY
TypeScript
import { Connection, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";
const connection = new Connection(
`https://rpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`,
"confirmed"
);
// Read balance
const pubkey = new PublicKey("YOUR_WALLET_ADDRESS");
const balance = await connection.getBalance(pubkey);
console.log(`Balance: ${balance / LAMPORTS_PER_SOL} SOL`);
// Send transaction
const sig = await connection.sendRawTransaction(transaction.serialize(), {
skipPreflight: false,
maxRetries: 3,
});
await connection.confirmTransaction(sig, "confirmed");
Python
from solana.rpc.api import Client
from solders.pubkey import Pubkey
import os
rpc = Client(f"https://rpc.carbium.io/?apiKey={os.environ['CARBIUM_RPC_KEY']}")
pubkey = Pubkey.from_string("YOUR_WALLET_ADDRESS")
resp = rpc.get_balance(pubkey)
print(f"Balance: {resp.value / 1e9} SOL")
Rust
use solana_client::rpc_client::RpcClient;
use solana_sdk::pubkey::Pubkey;
use std::str::FromStr;
let url = format!(
"https://rpc.carbium.io/?apiKey={}",
std::env::var("CARBIUM_RPC_KEY").unwrap()
);
let client = RpcClient::new(url);
let pubkey = Pubkey::from_str("YOUR_WALLET_ADDRESS").unwrap();
let balance = client.get_balance(&pubkey).unwrap();
println!("Balance: {} lamports", balance);
コミットメントレベル
| レベル | 速度 | 保証 | 用途 |
|---|---|---|---|
processed | 約 400ms | ロールバックされる可能性があります | 価格フィード、重要度の低い UX |
confirmed | 約 2s | 超多数の投票済み | デフォルト — 最適なバランス |
finalized | 約 32s | 完全に確定済み | 取り消せない確認、高額な操作 |
標準 WebSocket(Solana Pubsub)
ネイティブの Solana WebSocket pubsub です。Solana WebSocket 用に構築された SDK なら、変更なしで利用できます。
エンドポイント:
wss://wss-rpc.carbium.io/?apiKey=YOUR_RPC_KEY
認証:クエリパラメーターに RPC キーを指定します。本機能はすべてのティアで利用できます(本番環境では Developer 以上を推奨します)。
WSS と gRPC — どちらを使うべきか
| 標準 WSS | gRPC / Yellowstone | |
|---|---|---|
| プロトコル | WebSocket 経由の JSON-RPC | WebSocket(または HTTP/2)経由のバイナリー protobuf |
| 取得できるもの | アカウントの変更、スロットの更新、ログ、署名 | 完全なアトミックブロック、すべてのトランザクション |
| SDK のサポート | あらゆる Solana SDK(@solana/web3.js、solana-py) | Yellowstone クライアント、または JSON フィルターを使う生の WS |
| レイテンシ | サブスクリプション確認応答は 100 ms 未満 | 完全なブロックの配信は約 22 ms |
| 必要なティア | Developer 以上 | Business 以上 |
| 最適な用途 | ウォレット、dApps、特定のアカウントのモニタリング | MEV ボット、インデクサー、完全なブロックの処理 |
目安: 特定のアカウントや署名を監視する場合は WSS、すべてのトランザクションを処理する場合や完全なブロックデータが必要な場合は gRPC を使用します。
サブスクリプションメソッド
| メソッド | ストリームされる内容 | 主な用途 |
|---|---|---|
slotSubscribe | 新しいスロット番号 | ブロッククロック、稼働確認 |
rootSubscribe | ファイナライズされたスロット | ファイナリティの追跡 |
accountSubscribe | アカウントデータの変更 | ウォレット残高の更新、PDA 状態の変更 |
programSubscribe | プログラムが所有するすべてのアカウント | DEX プールの状態、ステーキングの更新 |
signatureSubscribe | トランザクションの確認ステータス | 送信したトランザクションのリアルタイム確認 |
logsSubscribe | フィルターに一致するトランザクションログ | プログラムイベントのモニタリング |
blockSubscribe | 完全なブロックデータ | ブロックエクスプローラー、インデクサー |
slotsUpdatesSubscribe | スロットのライフサイクルに関する詳細イベント | 高度なタイミング計測、バリデーターのモニタリング |
voteSubscribe | 投票トランザクション | バリデーターのモニタリング |
TypeScript — ウォレットを監視する
import WebSocket from "ws";
const ws = new WebSocket(
`wss://wss-rpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`
);
ws.on("open", () => {
ws.send(JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "accountSubscribe",
params: [
"YOUR_WALLET_ADDRESS",
{ encoding: "base64", commitment: "confirmed" },
],
}));
});
ws.on("message", (raw) => {
const msg = JSON.parse(raw.toString());
if (msg.result !== undefined) {
console.log(`Subscribed, id: ${msg.result}`);
return;
}
if (msg.method === "accountNotification") {
const { lamports } = msg.params.result.value;
console.log(`Balance changed: ${lamports / 1e9} SOL`);
}
});
TypeScript — WSS 経由でトランザクションを確認する
ws.send(JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "signatureSubscribe",
params: ["YOUR_TX_SIGNATURE", { commitment: "confirmed" }],
}));
// signatureSubscribe auto-unsubscribes after first notification
TypeScript — プログラムログをストリームする
ws.send(JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "logsSubscribe",
params: [
{ mentions: ["PROGRAM_ID"] },
{ commitment: "confirmed" },
],
}));
@solana/web3.js の使用(推奨)
Connection クラスはサブスクリプションをネイティブに処理します。
import { Connection, PublicKey } from "@solana/web3.js";
const connection = new Connection(
`https://rpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`,
{
commitment: "confirmed",
wsEndpoint: `wss://wss-rpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`,
}
);
// Account subscription
connection.onAccountChange(
new PublicKey("YOUR_WALLET"),
(info, ctx) => console.log(`Balance: ${info.lamports / 1e9} SOL at slot ${ctx.slot}`),
"confirmed"
);
// Slot subscription
connection.onSlotChange((slotInfo) => {
console.log(`Slot: ${slotInfo.slot}`);
});
// Log subscription
connection.onLogs(
new PublicKey("PROGRAM_ID"),
(logs, ctx) => {
console.log(`Tx: ${logs.signature}`);
logs.logs.forEach(log => console.log(" ", log));
},
"confirmed"
);
Python — アカウントを監視する
import asyncio, json, os
import websockets
WALLET = "YOUR_WALLET_ADDRESS"
async def watch_account():
uri = f"wss://wss-rpc.carbium.io/?apiKey={os.environ['CARBIUM_RPC_KEY']}"
async with websockets.connect(uri) as ws:
await ws.send(json.dumps({
"jsonrpc": "2.0", "id": 1,
"method": "accountSubscribe",
"params": [WALLET, {"encoding": "base64", "commitment": "confirmed"}],
}))
ack = json.loads(await ws.recv())
print(f"Subscribed: {ack['result']}")
async for raw in ws:
msg = json.loads(raw)
if msg.get("method") == "accountNotification":
val = msg["params"]["result"]["value"]
print(f"Balance: {val['lamports'] / 1e9} SOL")
asyncio.run(watch_account())
サブスクリプションを解除する
各サブスクリプションメソッドには対応する解除メソッドがあります。確認応答で返されるサブスクリプション ID を使用します。
{"jsonrpc": "2.0", "id": 2, "method": "accountUnsubscribe", "params": [SUBSCRIPTION_ID]}
| 登録 | 解除 |
|---|---|
slotSubscribe | slotUnsubscribe |
accountSubscribe | accountUnsubscribe |
programSubscribe | programUnsubscribe |
signatureSubscribe | signatureUnsubscribe(最初の通知後に自動解除) |
logsSubscribe | logsUnsubscribe |
blockSubscribe | blockUnsubscribe |
rootSubscribe | rootUnsubscribe |
通知の完全な形式と高度なパターンについては、resources/websocket-reference.md を参照してください。
gRPC / 完全なブロックのストリーミング
Yellowstone 互換のリアルタイム完全ブロックストリームです。レイテンシは約 22 ms。アトミックな完全ブロックが配信されるため、シュレッドの再構築は不要です。
エンドポイントと認証
| 方法 | 形式 | 用途 |
|---|---|---|
| WebSocket クエリパラメーター | wss://grpc.carbium.io/?apiKey=YOUR_RPC_KEY | TS/Python に推奨 |
| HTTP/2 ヘッダー | x-token: YOUR_RPC_KEY | Rust の yellowstone-grpc-client 用 |
Business ティア以上が必要です。
利用可能なメソッド
| メソッド | 説明 |
|---|---|
transactionSubscribe | フィルターを使ってリアルタイムトランザクションを購読する |
transactionUnsubscribe | トランザクションストリームの購読を解除する |
TypeScript — プログラムのトランザクションを購読する
import WebSocket from "ws";
const PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";
const ws = new WebSocket(
`wss://grpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`
);
ws.on("open", () => {
ws.send(JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "transactionSubscribe",
params: [
{
vote: false,
failed: false,
accountInclude: [PROGRAM_ID],
accountExclude: [],
accountRequired: [],
},
{
commitment: "confirmed",
encoding: "base64",
transactionDetails: "full",
showRewards: false,
maxSupportedTransactionVersion: 0,
},
],
}));
});
ws.on("message", (raw) => {
const msg = JSON.parse(raw.toString());
if (msg.result !== undefined) {
console.log(`Subscribed, ID: ${msg.result}`);
return;
}
if (msg.method === "transactionNotification") {
const { signature, slot } = msg.params.result;
console.log(`tx ${signature} in slot ${slot}`);
}
});
// Always reconnect on close — see Production Patterns
ws.on("close", (code) => {
console.warn(`Disconnected (${code}), reconnecting...`);
});
フィルターフィールド
| フィールド | 型 | 説明 |
|---|---|---|
vote | bool | 投票トランザクションを含める |
failed | bool | 失敗したトランザクションを含める |
accountInclude | string[] | これらのアカウントのいずれかに関与するトランザクションを含める |
accountExclude | string[] | これらのアカウントに関与するトランザクションを除外する |
accountRequired | string[] | これらすべてのアカウントに関与するトランザクションのみを含める |
accountInclude または accountRequired の少なくとも一方に値を指定する必要があります。
サブスクリプションのオプション
| フィールド | 型 | 値 |
|---|---|---|
commitment | string | processed / confirmed / finalized |
encoding | string | base64 / base58 / jsonParsed |
transactionDetails | string | full / signatures / none |
showRewards | bool | 報酬情報を含める |
maxSupportedTransactionVersion | number | レガシーと v0 の場合は 0 |
Python
import asyncio, json, os
import websockets
PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
async def subscribe():
uri = f"wss://grpc.carbium.io/?apiKey={os.environ['CARBIUM_RPC_KEY']}"
async with websockets.connect(uri) as ws:
await ws.send(json.dumps({
"jsonrpc": "2.0", "id": 1,
"method": "transactionSubscribe",
"params": [
{
"vote": False, "failed": False,
"accountInclude": [PROGRAM_ID],
"accountExclude": [], "accountRequired": [],
},
{
"commitment": "confirmed", "encoding": "base64",
"transactionDetails": "full", "showRewards": False,
"maxSupportedTransactionVersion": 0,
},
],
}))
async for message in ws:
data = json.loads(message)
if "result" in data:
print(f"Subscribed: {data['result']}")
elif data.get("method") == "transactionNotification":
print(f"tx: {data['params']['result']['signature'][:20]}...")
asyncio.run(subscribe())
Rust(HTTP/2 gRPC)
use yellowstone_grpc_client::GeyserGrpcClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = GeyserGrpcClient::connect(
"https://grpc.carbium.io",
"YOUR_RPC_KEY", // passed as x-token header automatically
None,
)?;
let (_subscribe_tx, mut stream) = client.subscribe().await?;
// Define subscription filters and consume stream
Ok(())
}
フルブロックとシャード
| 指標 | 値 | コンテキスト |
|---|---|---|
| Solana スロットの時間 | 約400ms | ブロックが生成される時間枠 |
| 競合他社の「シャード」 | 約9ms | クライアント側での再構成が必要な断片化データ |
| Carbium フルブロック | 約22ms | アトミックで完全な、すぐに使えるデータ |
13ms の差は、400ms のスロット内ではごくわずかです。フルブロックにより、アトミックな整合性、ロジック不要の取り込み、効率的な解析を実現できます。
購読解除
{"jsonrpc": "2.0", "id": 2, "method": "transactionUnsubscribe", "params": [SUBSCRIPTION_ID]}
レスポンス形式を含む完全な gRPC リファレンスについては、resources/grpc-reference.md を参照してください。
スワップ API
CQ1 エンジンを活用した、集約型 DEX の見積もりと実行機能です。ミリ秒未満の見積もり、約10ms のチェーンからクエリ可能になるまでのレイテンシ、バイナリネイティブな状態を実現します。
ベース URL: https://api.carbium.io
認証: すべてのリクエストに X-API-KEY: YOUR_API_KEY ヘッダーを指定
キーの取得: api.carbium.io/login(無料アカウント)
API バージョン
| バージョン | インターフェース | 状態 |
|---|---|---|
| v2 (Q1) | GET /api/v2/quote | 現行 — 新しい統合ではこちらを使用してください |
| v1(レガシー) | GET /api/v1/quote、/api/v1/swap、/api/v1/quote/all、/api/v1/swap/bundle | レガシー — 引き続き利用可能 |
重要: v2 と v1 ではパラメーター名が異なります。混在させないでください。v2 (Q1) では
src_mint/dst_mint/amount_in/slippage_bpsを使用します。v1 ではfromMint/toMint/amount/slippageを使用します。
v2 / Q1 — 見積もり + 実行可能なトランザクション(推奨)
user_account を含めると、Q1 エンジンは1回の呼び出しで見積もりと実行可能なトランザクションの両方を返します。別途スワップエンドポイントを呼び出す必要はありません。
GET /api/v2/quote
| パラメーター | 必須 | 説明 |
|---|---|---|
src_mint | はい | 入力トークンのミントアドレス |
dst_mint | はい | 出力トークンのミントアドレス |
amount_in | はい | 最小単位(lamports)での入力額 |
slippage_bps | はい | ベーシスポイント単位のスリッページ許容値 |
user_account | いいえ | ウォレットアドレス — 含めると、レスポンスに実行可能な txn フィールドが含まれます |
見積もりのみ(トランザクションなし):
const quote = await fetch(
"https://api.carbium.io/api/v2/quote" +
"?src_mint=So11111111111111111111111111111111111111112" +
"&dst_mint=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" +
"&amount_in=1000000000" +
"&slippage_bps=100",
{ headers: { "X-API-KEY": process.env.CARBIUM_API_KEY! } }
).then(r => r.json());
// Returns: { srcAmountIn, destAmountOut, destAmountOutMin, priceImpactPct, routePlan }
見積もり + 実行可能なトランザクション(user_account を含める):
const quote = await fetch(
"https://api.carbium.io/api/v2/quote" +
"?src_mint=So11111111111111111111111111111111111111112" +
"&dst_mint=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" +
"&amount_in=1000000000" +
"&slippage_bps=100" +
"&user_account=YOUR_WALLET_ADDRESS",
{ headers: { "X-API-KEY": process.env.CARBIUM_API_KEY! } }
).then(r => r.json());
// Returns: { srcAmountIn, destAmountOut, destAmountOutMin, priceImpactPct, routePlan, txn }
// txn is base64-encoded, ready for deserialization and signing
import httpx, os
resp = httpx.get(
"https://api.carbium.io/api/v2/quote",
params={
"src_mint": "So11111111111111111111111111111111111111112",
"dst_mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount_in": 1_000_000_000,
"slippage_bps": 100,
"user_account": "YOUR_WALLET_ADDRESS", # include for executable txn
},
headers={"X-API-KEY": os.environ["CARBIUM_API_KEY"]},
)
print(resp.json())
v1 レガシーエンドポイント
これらのエンドポイントは引き続き利用できますが、古いパラメータ形式を使用します。v1 のパラメーターを v2 の URL と混在させないでください。
| エンドポイント | メソッド | パラメーター | 説明 |
|---|---|---|---|
/api/v1/quote | GET | fromMint、toMint、amount、slippage、provider | プロバイダー固有の見積もり |
/api/v1/quote/all | GET | fromMint、toMint、amount、slippage | すべてのプロバイダーの見積もりを比較 |
/api/v1/swap | GET | owner、fromMint、toMint、amount、slippage、provider + オプションのフラグ | シリアライズ済みスワップトランザクションを取得 |
/api/v1/swap/bundle | GET | signedTransaction | Jito バンドル経由で送信(MEV 保護) |
/api/v1/fee/custom | GET | payer、receiver、lamports | カスタム手数料送金トランザクションを生成 |
v1 の /swap は、追加の実行フラグとして gasless、mevSafe、priorityMicroLamports、feeLamports、feeReceiver、pool をサポートします。
スワップ実行の全フロー(TypeScript)— v2/Q1
import { Connection, VersionedTransaction, Keypair } from "@solana/web3.js";
const connection = new Connection(
`https://rpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`,
"confirmed"
);
// 1. Get quote with executable transaction (single call)
const url = new URL("https://api.carbium.io/api/v2/quote");
url.searchParams.set("src_mint", "So11111111111111111111111111111111111111112");
url.searchParams.set("dst_mint", "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
url.searchParams.set("amount_in", "100000000");
url.searchParams.set("slippage_bps", "100");
url.searchParams.set("user_account", "YOUR_WALLET_ADDRESS");
const quote = await fetch(url, {
headers: { "X-API-KEY": process.env.CARBIUM_API_KEY! },
}).then(r => r.json());
if (!quote.txn) throw new Error("No executable transaction — check user_account param");
// 2. Deserialize and sign
const tx = VersionedTransaction.deserialize(Buffer.from(quote.txn, "base64"));
// tx.sign([yourKeypair]);
// 3. Submit via RPC
const sig = await connection.sendRawTransaction(tx.serialize(), { maxRetries: 3 });
// 4. Confirm
await connection.confirmTransaction(sig, "confirmed");
console.log("Swap confirmed:", sig);
サポートされている DEX プロバイダー
| プロバイダー | ID |
|---|---|
| Raydium | raydium |
| Raydium CPMM | raydium-cpmm |
| Orca | orca |
| Meteora | meteora |
| Meteora DLMM | meteora-dlmm |
| Pump.fun | pump-fun |
| Moonshot | moonshot |
| Stabble | stabble |
| PrintDEX | printdex |
| GooseFX | goosefx |
スリッページの推奨値
| ペアの種類 | 推奨 BPS | 割合 |
|---|---|---|
| ステーブルコインのスワップ | 5-10 | 0.05-0.1% |
| 主要ペア(SOL/USDC) | 10-50 | 0.1-0.5% |
| 価格変動の大きいトークン | 50-100 | 0.5-1% |
| アービトラージ | 10 | 0.1%(低め) |
OpenAPI パラメーターの完全な仕様については、resources/swap-api-reference.md を参照してください。
ガスレススワップ
ガスレススワップを使用すると、ユーザーは手数料を支払うための SOL を保有せずに、オンチェーン取引を実行できます。
仕組み
- ユーザーがスワップを開始します
- Carbium が内部の手数料プールから SOL 手数料を立て替えます
- 取引は通常どおりオンチェーンで確定します
- スワップ出力に微調整を加え、手数料プールの残高を調整します
制約
ガスレススワップでは、出力トークンが SOL である必要があります。現在、v1 スワップエンドポイントで利用できます。
使用する場面
- SOL を持たずにトークンを受け取った初回ユーザー
- 手間の少ないオンボーディングを実現する組み込みウォレット
- ガス代の入金がコンバージョンを妨げる、スワップ優先の UX
組み込み方法
v1 スワップリクエストに gasless=true を追加します。
const res = await fetch(
"https://api.carbium.io/api/v1/swap" +
"?owner=WALLET&fromMint=USDC_MINT&toMint=SOL_MINT" +
"&amount=1000000&slippage=100&provider=raydium&gasless=true",
{ headers: { "X-API-KEY": process.env.CARBIUM_API_KEY! } }
);
Pump.fun の卒業前トークンのスナイピング
Carbium Swap API では、卒業前の pump.fun トークンをルーティングできません(ルート数 0 を返します)。gRPC でローンチを検出 → ボンディングカーブの生トランザクションを構築 → RPC 経由で送信してください。
Business tier の RPC キー(gRPC アクセス)が必要です。
主な定数
const PUMP_PROGRAM = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P";
const PUMP_GLOBAL = "4wTV1YmiEkRvAtNtsSGPtUrqRYQMe5SKy2uB4Jjaxnjf";
const PUMP_FEE_RECIPIENT = "CebN5WGQ4jvEPvsVU4EoHEpgzq1VV7AbicfhtW4xC9iM";
const PUMP_EVENT_AUTH = "Ce6TQqeHC9p8KetsN6JsjHK7UTZk7nasjjnr7XxXp9F1";
const GRADUATION_SOL = 85_000_000_000n; // 85 SOL in lamports
const TOTAL_SUPPLY = 1_000_000_000_000_000n; // 1 quadrillion (6 decimals)
const DISCRIMINATORS = {
create: [0xe4, 0x45, 0xa5, 0x2e, 0x51, 0xcb, 0x9a, 0x1d],
buy: [0x66, 0x06, 0x3d, 0x12, 0x01, 0xda, 0xeb, 0xea],
sell: [0x33, 0xe6, 0x85, 0xa4, 0x01, 0x7f, 0x83, 0xad],
};
ステップ 1 — gRPC 経由でローンチをサブスクライブする
import WebSocket from "ws";
const ws = new WebSocket(
`wss://grpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`
);
ws.on("open", () => {
ws.send(JSON.stringify({
jsonrpc: "2.0", id: 1,
method: "transactionSubscribe",
params: [
{ vote: false, failed: false, accountInclude: [PUMP_PROGRAM] },
{ commitment: "confirmed", encoding: "jsonParsed",
transactionDetails: "full", showRewards: false,
maxSupportedTransactionVersion: 0 },
],
}));
});
setInterval(() => ws.ping(), 30_000); // keepalive
ws.on("message", (raw) => {
const msg = JSON.parse(raw.toString());
if (msg.method !== "transactionNotification") return;
const { signature, transaction } = msg.params.result;
const logs = transaction.meta.logMessages || [];
for (const log of logs) {
if (log.includes("Instruction: Create")) {
const mint = transaction.meta.postTokenBalances[0]?.mint;
if (mint) handleNewToken(mint, signature);
}
}
});
ステップ 2 — ボンディングカーブ PDA を導出する
import { PublicKey } from "@solana/web3.js";
function deriveBondingCurve(mint: string): PublicKey {
const [address] = PublicKey.findProgramAddressSync(
[Buffer.from("bonding-curve"), new PublicKey(mint).toBuffer()],
new PublicKey(PUMP_PROGRAM)
);
return address;
}
ステップ 3 — ボンディングカーブの状態を取得して解析する
// Bonding curve layout (81 bytes):
// [0-7] discriminator
// [8-15] virtualTokenReserves (u64 LE)
// [16-23] virtualSolReserves (u64 LE)
// [24-31] realTokenReserves (u64 LE)
// [32-39] realSolReserves (u64 LE)
// [40-47] tokenTotalSupply (u64 LE)
// [72] complete (bool)
async function fetchBondingCurve(address: PublicKey) {
const res = await fetch(`https://rpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0", id: 1,
method: "getAccountInfo",
params: [address.toBase58(), { encoding: "base64" }],
}),
});
const { result } = await res.json();
const data = Buffer.from(result.value.data[0], "base64");
return {
virtualTokenReserves: data.readBigUInt64LE(8),
virtualSolReserves: data.readBigUInt64LE(16),
realTokenReserves: data.readBigUInt64LE(24),
realSolReserves: data.readBigUInt64LE(32),
complete: data.readUInt8(72) === 1,
};
}
ステップ 4 — 見積もる(定積 AMM)
function quoteBuy(curve: any, solLamports: number): bigint {
const num = curve.virtualTokenReserves * BigInt(solLamports);
const den = curve.virtualSolReserves + BigInt(solLamports);
return num / den;
}
function quoteSell(curve: any, tokens: bigint): bigint {
const num = curve.virtualSolReserves * tokens;
const den = curve.virtualTokenReserves + tokens;
return num / den;
}
ステップ 5 — 買い注文のトランザクションを構築して送信する
買い注文の命令アカウント(順序は重要、合計 13 個):
| # | アカウント | アクセス |
|---|---|---|
| 0 | PUMP_GLOBAL | 読み取り |
| 1 | PUMP_FEE_RECIPIENT | 書き込み |
| 2 | mint | 読み取り |
| 3 | bondingCurve | 書き込み |
| 4 | bondingCurve ATA | 書き込み |
| 5 | user ATA | 書き込み |
| 6 | user/payer | 書き込み、署名者 |
| 7 | SystemProgram | - |
| 8 | TokenProgram | - |
| 9 | AssociatedTokenProgram | - |
| 10 | Rent sysvar | - |
| 11 | PUMP_EVENT_AUTH | 読み取り |
| 12 | PUMP_PROGRAM | 読み取り |
約 200ms 節約するには、skipPreflight: true を指定して送信します。
const sig = await connection.sendRawTransaction(signedTx.serialize(), {
skipPreflight: true,
preflightCommitment: "confirmed",
maxRetries: 3,
});
スナイピングフローの概要
gRPC "Create" event → extract mint
→ deriveBondingCurve(mint)
→ [optional] fetchBondingCurve() for price check
→ build buy instruction with desired SOL
→ sendTransaction(skipPreflight: true)
→ monitor bonding curve state for exit
→ sell when target % reached or graduation imminent (85 SOL)
Pump.fun のエラー処理
| エラー | 原因 | 解決方法 |
|---|---|---|
| Blockhash expired | Tx の処理に時間がかかりすぎました | より新しい blockhash を使用します。レイテンシを減らします |
| Insufficient funds | SOL が不足しています | 残高には金額と手数料(約 0.005 SOL)をカバーできる額が必要です |
| Account not found | トークンが作成された直後です | 少し待ってから再試行します(50-100ms) |
| Slippage exceeded | 価格が変動しました | maxSolCost を増やすか、取引サイズを小さくします |
スナイピングの完全な例については、examples/pump-snipe/example.ts を参照してください。
移行
他の RPC プロバイダー(Helius、QuickNode、Triton、Alchemy)からの移行
URL を差し替えるだけです。すべて標準の JSON-RPC を使用します。
// Before
const connection = new Connection("https://mainnet.helius-rpc.com/?api-key=...");
// After
const connection = new Connection(
`https://rpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`
);
Jupiter Swap API からの移行
パラメーターの対応関係(v2/Q1):
| Jupiter | Carbium v2/Q1(/api/v2/quote) |
|---|---|
inputMint | src_mint |
outputMint | dst_mint |
amount | amount_in |
slippageBps | slippage_bps |
主な違い:Carbium Q1 では、user_account を含めると、実行可能なトランザクションが見積もりのレスポンスに返されます。別途スワップを呼び出す必要はありません。
Triton gRPC からの移行
同じ Yellowstone プロトコルです。エンドポイントのみ更新してください。
wss://grpc.carbium.io/?apiKey=YOUR_RPC_KEY
詳しい移行ガイドについては、docs/migration.md を参照してください。
本番環境でのパターン
指数バックオフによる再試行
const delay = (ms: number) => new Promise(r => setTimeout(r, ms));
async function withRetry<T>(fn: () => Promise<T>, retries = 3, baseMs = 300): Promise<T> {
for (let i = 0; i < retries; i++) {
try { return await fn(); }
catch (e) {
if (i === retries - 1) throw e;
await delay(baseMs * 2 ** i + Math.random() * 100);
}
}
throw new Error("unreachable");
}
sendTransactionをむやみに再試行してはいけません。まずgetSignatureStatusを確認して、トランザクションがすでに確定していないことを確かめてください。
WebSocket / gRPC の再接続
async function connectWithReconnect(connectFn: () => Promise<void>) {
let backoff = 1000;
while (true) {
try {
await connectFn();
backoff = 1000; // reset on success
} catch {
await delay(backoff);
backoff = Math.min(backoff * 2, 30_000); // cap at 30s
}
}
}
意図しない切断を防ぐため、30 秒ごとに ping を送信してください。
タイムアウトの推奨値
| 操作 | タイムアウト |
|---|---|
| RPC 読み取り呼び出し | 5-10s |
| スワップの見積もり | 3-5s |
| トランザクションの確認 | 30-60s(ポーリングあり) |
障害対応
| 障害 | 対応 |
|---|---|
| Quote: no route found | スリッページを広げるか、別のプロバイダーで再試行します |
| Simulation failed | 送信しないでください。エラーを調査し、ログに記録して、アラートを出します |
| sendTransaction failed | 再試行する前に getSignatureStatus を確認します |
| Transaction not confirmed | タイムアウトを設定してポーリングし、ブロックハッシュの有効期限を確認します |
| Stream disconnected | 指数バックオフで再接続します |
| HTTP 429 rate limit | 直ちにバックオフし、アーキテクチャ上の問題を示すシグナルとして扱います |
エラーリファレンス
HTTP ステータスコード
| コード | 意味 | 対応 |
|---|---|---|
| 401 | API キーが無効、または指定されていません | キーと認証形式を確認します |
| 403 | プランによる制限(例:無料プランでの gRPC) | rpc.carbium.io でアップグレードします |
| 429 | レート制限を超過しました | バックオフして再試行し、アーキテクチャを見直します |
| 400 | ルートが見つからない、またはパラメーターが不正です | ミントアドレス、スリッページ、必須パラメーターを確認します |
| 500 | サーバーエラー | 1 秒後に再試行します |
| 503 | 一時的に利用できません | 指数バックオフで再試行します |
WebSocket エラーコード
| コード | メッセージ | 原因 |
|---|---|---|
-32700 | 解析エラー | JSON の形式が不正、または必須パラメーターがありません |
-32601 | メソッドが見つかりません | メソッド名の誤記、またはサポートされていないメソッドです |
-32602 | パラメーターが無効です | パラメーターの型が誤っているか、フィールドがありません |
-32603 | 内部エラー | サーバー側のエラーです。再試行してください |
一般的なトークンミント
| トークン | ミントアドレス |
|---|---|
| SOL(ラップ済み) | So11111111111111111111111111111111111111112 |
| USDC | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
| USDT | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |
ベストプラクティス
セキュリティ
- API キーはサーバー側だけに保持し、フロントエンドのバンドルやモバイルクライアントには決して含めないでください
- 環境変数(
CARBIUM_RPC_KEY、CARBIUM_API_KEY)を使用します - キーが漏えいした場合は、直ちにローテーションします
- 可能であれば、RPC ダッシュボードでエンドポイントをドメイン/IP によって制限します
レート制限
- HTTP 429 は単なる再試行の合図ではなく、アーキテクチャ上の問題を示すシグナルです
- 開発環境/ステージング環境/本番環境のキーを分けます
- 再試行の処理経路を意思決定ロジックから分離します
getSignatureStatusを確認する前にsendTransactionを再試行しないでください
トランザクションの送信
- Quote の検証後に限り
skipPreflight: trueを使用します。約 200ms 短縮できます - Address Lookup Table(ALT)をサポートするには
VersionedTransaction(V0)を使用します - 確認には WebSocket よりも HTTP ポーリングを優先します(より信頼性が高いため)
- ブロックハッシュは新しい状態に保ってください。約 60 秒で期限切れになります
コミットメントレベル
- ほとんどの操作では
confirmedをデフォルトにします processedは価格フィードや重要度の低い読み取りに限って使用します- 取り消せない確認や高額な操作には
finalizedを使用します
スキルの構成
skills/carbium/
├── SKILL.md # This file
├── resources/
│ ├── endpoints-and-auth.md # All endpoints, auth patterns, pricing
│ ├── swap-api-reference.md # Full Swap API parameter specs
│ ├── grpc-reference.md # gRPC filter fields, response shapes
│ └── websocket-reference.md # All WSS subscription methods and shapes
├── examples/
│ ├── rpc-basic/README.md # Balance check + send transaction
│ ├── swap-quote/README.md # Quote → swap → sign → submit
│ ├── swap-bundle/README.md # MEV-protected Jito bundle
│ ├── grpc-stream/README.md # Program transaction subscription
│ ├── websocket-monitor/README.md # Account + slot monitoring via WSS
│ ├── pump-snipe/README.md # Full pump.fun sniping flow
│ └── gasless-swap/README.md # Gasless swap execution
├── templates/
│ └── carbium-setup.ts # Connection setup + retry helper
└── docs/
├── troubleshooting.md # Error codes, 429 handling
├── migration.md # From Helius, QuickNode, Jupiter
└── trading-bots.md # Bot architecture patterns
参考資料
| リソース | URL |
|---|---|
| エコシステムの概要 | docs.carbium.io/docs/the-carbium-ecosystem |
| RPC クイックスタート | docs.carbium.io/docs/quick-start-rpc |
| Swap API クイックスタート | docs.carbium.io/docs/quick-start-dex-api |
| gRPC/ストリーミング | docs.carbium.io/docs/solana-grpc |
| CQ1 エンジン | docs.carbium.io/docs/cq1-engine-overview |
| RPC 料金 | docs.carbium.io/docs/carbium-rpc-pricing |
| API レシピ | docs.carbium.io/recipes |
| よくある質問 | docs.carbium.io/docs/faq |
| AI コンテキスト全文 | carbium.io/llms-ctx.txt |
| RPC 登録 | rpc.carbium.io/signup |
| Swap API 登録 | api.carbium.io/login |
| Discord | discord.gg/jW7BUkQS5U |
| Twitter/X | x.com/carbium |