‹ 首页

carbium

@sendaifun · 收录于 1 周前

Build on Solana with Carbium infrastructure — bare-metal RPC, Standard WebSocket pubsub, gRPC Full Block streaming (~22ms), DEX aggregation via CQ1 engine (sub-ms quotes), gasless swaps, and MEV-protected execution via Jito bundling. Drop-in replacement for Helius, QuickNode, Triton, or Jupiter Swap API.

适合你,如果你在 Solana 上开发需要低延迟 RPC 和 MEV 保护的 dApp

/ 下载安装
carbium.skill双击,或拖进 Claude 桌面版 / Cowork,即完成安装↓ .skill↓ .zip
用别的 agent?下载 .zip 解压,把文件夹放进它的技能目录
Claude Code~/.claude/skills/(项目级 .claude/skills/)
Codex CLI~/.codex/skills/
Cursor自动读取上面两处目录
其他工具见其文档的「skills」目录;两个下载是同一份文件,只是名字不同
/ 通过 npx 安装 校验哈希
npx oh-my-skill add sendaifun/skills/carbium
/ 通过 bash 安装
curl -fsSL https://oh-my-skill.com/install.sh | bash -s -- sendaifun/skills/carbium
/ 已经装过?验证本机副本,不用重装
npx oh-my-skill verify sendaifun/skills/carbium
安装目标可用 --agent / --scope 或 --to 明确指定;省略时只会在唯一已存在的 agent 目录上自动选择,零命中或多命中会停止并提示。content_hash 缺失或不一致均拒装。
116GitHub stars
~7K最小装载
~10.8K含声明引用
~17.1K文本包总量
镜像托管

怎么用

技能原文 SKILL.md作者撰写 · Apache-2.0 · 064d4de

Carbium — Full-Stack Solana Infrastructure

Carbium is bare-metal Solana infrastructure — Swiss-engineered, no cloud middlemen. One platform covering the full transaction lifecycle.

Overview

| Product | Endpoint | Purpose | |---|---|---| | RPC | https://rpc.carbium.io | Standard JSON-RPC for reads, writes, subscriptions | | Standard WebSocket | wss://wss-rpc.carbium.io | Native Solana pubsub (account changes, slots, logs, signatures) | | gRPC / Stream | wss://grpc.carbium.io | Yellowstone Full Block streaming (~22ms latency) | | Swap API | https://api.carbium.io | DEX aggregation and execution powered by CQ1 engine | | DEX App | https://app.carbium.io | Consumer-facing trading interface | | Docs | https://docs.carbium.io | Full documentation |

Key differentiators:

  • Sub-millisecond DEX quotes via CQ1 routing engine with binary-native state
  • ~22ms Full Block gRPC — atomic, complete blocks (no shred reassembly)
  • Gasless swaps — users trade without holding SOL
  • MEV protection — Jito bundling built into Swap API
  • Swiss bare-metal servers — sub-50ms RPC latency, 99.99% uptime

When to Use This Skill

| I want to... | Use | Key needed | |---|---|---| | Read account data / balances | RPC | RPC key | | Send a transaction | RPC | RPC key | | Monitor a wallet in real time | Standard WebSocket | RPC key | | Confirm a transaction without polling | Standard WebSocket | RPC key | | Watch program account changes | Standard WebSocket | RPC key | | Build a wallet app | RPC + Swap API | Both | | Get a token swap quote | Swap API | API key | | Execute a swap programmatically | Swap API | API key | | Execute a swap with Jito bundling | Swap API (bundle endpoint) | API key | | Compare quotes across all DEX providers | Swap API (quote/all) | API key | | Swap without users holding SOL | Swap API (gasless flag) | API key | | Snipe pump.fun tokens (pre-graduation) | gRPC + direct bonding curve tx | RPC key (Business+) | | React to on-chain events in real time | gRPC (streaming) | RPC key (Business+) | | Index transactions for a program | gRPC (streaming) | RPC key (Business+) | | Build an arbitrage / MEV bot | gRPC + Swap API | Both |


Quick Start
1. Get API Keys

| Product | Signup | Notes | |---|---|---| | RPC + gRPC + WebSocket | rpc.carbium.io/signup | One key covers RPC, WebSocket, and gRPC | | Swap API | api.carbium.io/login | Separate key, free account, instant |

Programmatic key provisioning is not yet available. Keys must be created via the dashboards.

2. Set Environment Variables
export CARBIUM_RPC_KEY="your-rpc-key"
export CARBIUM_API_KEY="your-swap-api-key"
3. Security Rules (Non-Negotiable)
  • Never embed keys in frontend/client-side code
  • Never commit keys to version control
  • Use environment variables: CARBIUM_RPC_KEY, CARBIUM_API_KEY
  • Rotate immediately if exposed
  • Keep keys server-side only

Pricing Tiers

| Tier | Price | Credits/mo | Max RPS | gRPC | WebSocket | |---|---|---|---|---|---| | Free | $0 | 500K | 10 | No | Yes | | Developer | $32/mo | 10M | 50 | No | Yes | | Business | $320/mo | 100M | 200 | Yes | Yes | | Professional | $640/mo | 200M | 500 | Yes | Yes |

gRPC streaming requires Business tier or above.


RPC

Standard Solana JSON-RPC. Any Solana SDK works: @solana/web3.js, solana-py, solana Rust crate.

Endpoint:

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);
Commitment Levels

| Level | Speed | Guarantee | Use for | |---|---|---|---| | processed | ~400ms | May roll back | Price feeds, low-stakes UX | | confirmed | ~2s | Supermajority voted | Default — best balance | | finalized | ~32s | Fully finalized | Irreversible confirmations, high-value ops |


Standard WebSocket (Solana Pubsub)

Native Solana WebSocket pubsub — any SDK built for Solana WebSocket works with zero modifications.

Endpoint:

wss://wss-rpc.carbium.io/?apiKey=YOUR_RPC_KEY

Auth: same RPC key as query parameter. Available on all tiers (Developer and above recommended for production).

WSS vs gRPC — When to Use Which

| | Standard WSS | gRPC / Yellowstone | |---|---|---| | Protocol | JSON-RPC over WebSocket | Binary protobuf over WebSocket (or HTTP/2) | | What you get | Account changes, slot updates, logs, signatures | Full atomic blocks, all transactions | | SDK support | Any Solana SDK (@solana/web3.js, solana-py) | Yellowstone client or raw WS with JSON filter | | Latency | Sub-100ms subscription ack | ~22ms full block delivery | | Tier required | Developer+ | Business+ | | Best for | Wallets, dApps, monitoring specific accounts | MEV bots, indexers, full-block processing |

Rule of thumb: watching specific accounts or signatures → WSS. Processing all transactions or need full block data → gRPC.

Subscription Methods

| Method | What it streams | Typical use case | |---|---|---| | slotSubscribe | New slot numbers | Block clock, liveness checks | | rootSubscribe | Finalized slots | Finality tracking | | accountSubscribe | Account data changes | Wallet balance updates, PDA state changes | | programSubscribe | All accounts owned by a program | DEX pool state, staking updates | | signatureSubscribe | Transaction confirmation status | Confirm sent transactions in real time | | logsSubscribe | Transaction logs matching filter | Program event monitoring | | blockSubscribe | Full block data | Block explorers, indexers | | slotsUpdatesSubscribe | Detailed slot lifecycle events | Advanced timing, validator monitoring | | voteSubscribe | Vote transactions | Validator monitoring |

TypeScript — Watch a Wallet
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 — Confirm Transaction via 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 — Stream Program Logs
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 1,
  method: "logsSubscribe",
  params: [
    { mentions: ["PROGRAM_ID"] },
    { commitment: "confirmed" },
  ],
}));
Using @solana/web3.js (Recommended)

The Connection class handles subscriptions natively:

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 — Watch Account
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())
Unsubscribe

Every subscription method has a matching unsubscribe. Use the subscription ID from the ack:

{"jsonrpc": "2.0", "id": 2, "method": "accountUnsubscribe", "params": [SUBSCRIPTION_ID]}

| Subscribe | Unsubscribe | |---|---| | slotSubscribe | slotUnsubscribe | | accountSubscribe | accountUnsubscribe | | programSubscribe | programUnsubscribe | | signatureSubscribe | signatureUnsubscribe (auto after first notification) | | logsSubscribe | logsUnsubscribe | | blockSubscribe | blockUnsubscribe | | rootSubscribe | rootUnsubscribe |

For full notification shapes and advanced patterns, see resources/websocket-reference.md.


gRPC / Full Block Streaming

Real-time Yellowstone-compatible Full Block stream. ~22ms latency. Atomic complete blocks — no shred reassembly needed.

Endpoints & Auth

| Method | Format | Use case | |---|---|---| | WebSocket query param | wss://grpc.carbium.io/?apiKey=YOUR_RPC_KEY | Recommended for TS/Python | | HTTP/2 header | x-token: YOUR_RPC_KEY | For Rust yellowstone-grpc-client |

Requires Business tier or above.

Available Methods

| Method | Description | |---|---| | transactionSubscribe | Subscribe to real-time transactions with filters | | transactionUnsubscribe | Unsubscribe from transaction stream |

TypeScript — Subscribe to Program Transactions
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...`);
});
Filter Fields

| Field | Type | Description | |---|---|---| | vote | bool | Include vote transactions | | failed | bool | Include failed transactions | | accountInclude | string[] | Include txs involving ANY of these accounts | | accountExclude | string[] | Exclude txs involving these accounts | | accountRequired | string[] | Only include txs involving ALL of these accounts |

At least one of accountInclude or accountRequired must contain values.

Subscription Options

| Field | Type | Values | |---|---|---| | commitment | string | processed / confirmed / finalized | | encoding | string | base64 / base58 / jsonParsed | | transactionDetails | string | full / signatures / none | | showRewards | bool | Include reward information | | maxSupportedTransactionVersion | number | 0 for legacy + v0 |

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(())
}
Full Blocks vs Shreds

| Metric | Value | Context | |---|---|---| | Solana Slot Resolution | ~400ms | The window in which a block is produced | | Competitor "Shreds" | ~9ms | Fragmented data requiring client-side reassembly | | Carbium Full Blocks | ~22ms | Atomic, complete data ready for use |

The 13ms difference is negligible within a 400ms slot. Full Blocks provide atomic integrity, zero-logic ingestion, and parsing efficiency.

Unsubscribe
{"jsonrpc": "2.0", "id": 2, "method": "transactionUnsubscribe", "params": [SUBSCRIPTION_ID]}

For complete gRPC reference with response shapes, see resources/grpc-reference.md.


Swap API

Aggregated DEX quotes and execution powered by the CQ1 engine — sub-millisecond quotes, ~10ms chain-to-queryable latency, binary-native state.

Base URL: https://api.carbium.io Auth: X-API-KEY: YOUR_API_KEY header on all requests Get your key: api.carbium.io/login (free account)

API Versions

| Version | Surface | Status | |---|---|---| | v2 (Q1) | GET /api/v2/quote | Current — use this for new integrations | | v1 (legacy) | GET /api/v1/quote, /api/v1/swap, /api/v1/quote/all, /api/v1/swap/bundle | Legacy — still operational |

Important: v2 and v1 use different parameter names. Do not mix them. v2 (Q1) uses src_mint/dst_mint/amount_in/slippage_bps. v1 uses fromMint/toMint/amount/slippage.
v2 / Q1 — Quote + Executable Transaction (Recommended)

The Q1 engine returns both the quote and an executable transaction in a single call when user_account is included. No separate swap endpoint needed.

GET /api/v2/quote

| Param | Required | Description | |---|---|---| | src_mint | Yes | Input token mint address | | dst_mint | Yes | Output token mint address | | amount_in | Yes | Input amount in smallest unit (lamports) | | slippage_bps | Yes | Slippage tolerance in basis points | | user_account | No | Wallet address — if included, response includes executable txn field |

Quote only (no transaction):

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 }

Quote + executable transaction (include 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 Legacy Endpoints

These endpoints are still operational but use the older parameter family. Do not mix v1 params with v2 URLs.

| Endpoint | Method | Params | Description | |---|---|---|---| | /api/v1/quote | GET | fromMint, toMint, amount, slippage, provider | Provider-specific quote | | /api/v1/quote/all | GET | fromMint, toMint, amount, slippage | Compare quotes across all providers | | /api/v1/swap | GET | owner, fromMint, toMint, amount, slippage, provider + optional flags | Get serialized swap transaction | | /api/v1/swap/bundle | GET | signedTransaction | Submit via Jito bundle (MEV protection) | | /api/v1/fee/custom | GET | payer, receiver, lamports | Generate custom fee transfer transaction |

v1 /swap supports additional execution flags: gasless, mevSafe, priorityMicroLamports, feeLamports, feeReceiver, pool.

Full Swap Execute Flow (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);
Supported DEX Providers

| Provider | 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 |

Slippage Recommendations

| Pair type | Recommended BPS | Percentage | |---|---|---| | Stablecoin swaps | 5-10 | 0.05-0.1% | | Major pairs (SOL/USDC) | 10-50 | 0.1-0.5% | | Volatile tokens | 50-100 | 0.5-1% | | Arbitrage | 10 | 0.1% (tight) |

For complete OpenAPI parameter specifications, see resources/swap-api-reference.md.


Gasless Swaps

Gasless swaps let users execute on-chain transactions without holding SOL to pay fees.

How It Works
  1. User initiates a swap
  2. Carbium advances the SOL fee from an internal fee pool
  3. Transaction settles on-chain normally
  4. A micro-adjustment on the swap output rebalances the fee pool
Constraint

Gasless swaps require the output token to be SOL. Currently available on the v1 swap endpoint.

When to Use
  • First-time users who received tokens but no SOL
  • Embedded wallet experiences with low-friction onboarding
  • Swap-first UX where gas funding hurts conversion
Integration

Add gasless=true to a v1 swap request:

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 Pre-Graduation Token Sniping

Carbium Swap API cannot route pump.fun tokens before graduation (returns 0 routes). Use: gRPC to detect launches → build raw bonding curve transactions → submit via RPC.

Requires Business tier RPC key (gRPC access).

Key Constants
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],
};
Step 1 — Subscribe to Launches via 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);
    }
  }
});
Step 2 — Derive Bonding Curve 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;
}
Step 3 — Fetch & Parse Bonding Curve State
// 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,
  };
}
Step 4 — Quote (Constant Product 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;
}
Step 5 — Build & Submit Buy Transaction

Buy instruction accounts (order matters, 13 total):

| # | Account | Access | |---|---|---| | 0 | PUMP_GLOBAL | read | | 1 | PUMP_FEE_RECIPIENT | write | | 2 | mint | read | | 3 | bondingCurve | write | | 4 | bondingCurve ATA | write | | 5 | user ATA | write | | 6 | user/payer | write, signer | | 7 | SystemProgram | - | | 8 | TokenProgram | - | | 9 | AssociatedTokenProgram | - | | 10 | Rent sysvar | - | | 11 | PUMP_EVENT_AUTH | read | | 12 | PUMP_PROGRAM | read |

Submit with skipPreflight: true to save ~200ms:

const sig = await connection.sendRawTransaction(signedTx.serialize(), {
  skipPreflight: true,
  preflightCommitment: "confirmed",
  maxRetries: 3,
});
Sniping Flow Summary
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 Error Handling

| Error | Cause | Fix | |---|---|---| | Blockhash expired | Tx took too long | Fresher blockhash; reduce latency | | Insufficient funds | Not enough SOL | Balance must cover amount + fees (~0.005 SOL) | | Account not found | Token just created | Retry with small delay (50-100ms) | | Slippage exceeded | Price moved | Increase maxSolCost or reduce size |

For the full sniping example, see examples/pump-snipe/example.ts.


Migration
From Other RPC Providers (Helius, QuickNode, Triton, Alchemy)

Simple URL swap — all use standard 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}`
);
From Jupiter Swap API

Parameter mapping (v2/Q1):

| Jupiter | Carbium v2/Q1 (/api/v2/quote) | |---|---| | inputMint | src_mint | | outputMint | dst_mint | | amount | amount_in | | slippageBps | slippage_bps |

Key difference: Carbium Q1 returns the executable transaction in the quote response when user_account is included. No separate swap call needed.

From Triton gRPC

Same Yellowstone protocol. Update endpoint only:

wss://grpc.carbium.io/?apiKey=YOUR_RPC_KEY

For detailed migration guides, see docs/migration.md.


Production Patterns
Retry with Exponential Backoff
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");
}
Do NOT blindly retry sendTransaction — check getSignatureStatus first to confirm the tx did not already land.
WebSocket / gRPC Reconnect
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
    }
  }
}

Send ping every 30 seconds to prevent silent disconnects.

Timeout Recommendations

| Operation | Timeout | |---|---| | RPC read calls | 5-10s | | Swap quote | 3-5s | | Transaction confirmation | 30-60s (with polling) |

Failure Handling

| Failure | Action | |---|---| | Quote: no route found | Retry with wider slippage or different provider | | Simulation failed | Do NOT send — inspect error, log, alert | | sendTransaction failed | Check getSignatureStatus before retry | | Transaction not confirmed | Poll with timeout; check blockhash expiry | | Stream disconnected | Reconnect with exponential backoff | | HTTP 429 rate limit | Back off immediately; treat as architecture signal |


Error Reference
HTTP Status Codes

| Code | Meaning | Action | |---|---|---| | 401 | Invalid / missing API key | Check key and auth format | | 403 | Plan restriction (e.g. gRPC on free tier) | Upgrade at rpc.carbium.io | | 429 | Rate limit exceeded | Back off + retry; review architecture | | 400 | No route found / bad params | Check mint addresses, slippage, required params | | 500 | Server error | Retry after 1s | | 503 | Temporary unavailability | Retry with exponential backoff |

WebSocket Error Codes

| Code | Message | Cause | |---|---|---| | -32700 | Parse error | Malformed JSON or missing required params | | -32601 | Method not found | Method name typo or unsupported method | | -32602 | Invalid params | Wrong param types or missing fields | | -32603 | Internal error | Server-side error — retry |


Common Token Mints

| Token | Mint Address | |---|---| | SOL (wrapped) | So11111111111111111111111111111111111111112 | | USDC | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v | | USDT | Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB |


Best Practices
Security
  • Keep API keys server-side only — never in frontend bundles or mobile clients
  • Use environment variables (CARBIUM_RPC_KEY, CARBIUM_API_KEY)
  • Rotate keys immediately if exposed
  • Restrict endpoints by domain/IP in the RPC dashboard where practical
Rate Limiting
  • HTTP 429 is an architecture signal, not just a retry cue
  • Separate dev/staging/prod keys
  • Isolate retry paths from decision logic
  • Do NOT retry sendTransaction before checking getSignatureStatus
Transaction Submission
  • Use skipPreflight: true only after validating the quote — saves ~200ms
  • Use VersionedTransaction (V0) for Address Lookup Table (ALT) support
  • Prefer HTTP polling for confirmations over WebSocket (more reliable)
  • Keep blockhashes fresh — they expire after ~60 seconds
Commitment Levels
  • Default to confirmed for most operations
  • Use processed only for price feeds or low-stakes reads
  • Use finalized for irreversible confirmations and high-value operations

Skill Structure
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

References

| Resource | URL | |---|---| | Ecosystem Overview | docs.carbium.io/docs/the-carbium-ecosystem | | RPC Quick Start | docs.carbium.io/docs/quick-start-rpc | | Swap API Quick Start | docs.carbium.io/docs/quick-start-dex-api | | gRPC / Streaming | docs.carbium.io/docs/solana-grpc | | CQ1 Engine | docs.carbium.io/docs/cq1-engine-overview | | RPC Pricing | docs.carbium.io/docs/carbium-rpc-pricing | | API Recipes | docs.carbium.io/recipes | | FAQ | docs.carbium.io/docs/faq | | Full AI Context | carbium.io/llms-ctx.txt | | RPC Signup | rpc.carbium.io/signup | | Swap API Signup | api.carbium.io/login | | Discord | discord.gg/jW7BUkQS5U | | Twitter/X | x.com/carbium |

按 Apache-2.0 许可原样转载,未经改动 · 在 GitHub 查看 →

评论

登录即可评论;带「已验证安装」的,是发布者名下有本店的安装或持有记录。