Skills carbium

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.

install
source · Clone the upstream repo
git clone https://github.com/sendaifun/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/sendaifun/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/carbium" ~/.claude/skills/sendaifun-skills-carbium && rm -rf "$T"
manifest: skills/carbium/SKILL.md
source content

Carbium — Full-Stack Solana Infrastructure

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

Overview

ProductEndpointPurpose
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...UseKey needed
Read account data / balancesRPCRPC key
Send a transactionRPCRPC key
Monitor a wallet in real timeStandard WebSocketRPC key
Confirm a transaction without pollingStandard WebSocketRPC key
Watch program account changesStandard WebSocketRPC key
Build a wallet appRPC + Swap APIBoth
Get a token swap quoteSwap APIAPI key
Execute a swap programmaticallySwap APIAPI key
Execute a swap with Jito bundlingSwap API (bundle endpoint)API key
Compare quotes across all DEX providersSwap API (quote/all)API key
Swap without users holding SOLSwap API (gasless flag)API key
Snipe pump.fun tokens (pre-graduation)gRPC + direct bonding curve txRPC key (Business+)
React to on-chain events in real timegRPC (streaming)RPC key (Business+)
Index transactions for a programgRPC (streaming)RPC key (Business+)
Build an arbitrage / MEV botgRPC + Swap APIBoth

Quick Start

1. Get API Keys

ProductSignupNotes
RPC + gRPC + WebSocketrpc.carbium.io/signupOne key covers RPC, WebSocket, and gRPC
Swap APIapi.carbium.io/loginSeparate 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

TierPriceCredits/moMax RPSgRPCWebSocket
Free$0500K10NoYes
Developer$32/mo10M50NoYes
Business$320/mo100M200YesYes
Professional$640/mo200M500YesYes

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

LevelSpeedGuaranteeUse for
processed
~400msMay roll backPrice feeds, low-stakes UX
confirmed
~2sSupermajority votedDefault — best balance
finalized
~32sFully finalizedIrreversible 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 WSSgRPC / Yellowstone
ProtocolJSON-RPC over WebSocketBinary protobuf over WebSocket (or HTTP/2)
What you getAccount changes, slot updates, logs, signaturesFull atomic blocks, all transactions
SDK supportAny Solana SDK (
@solana/web3.js
,
solana-py
)
Yellowstone client or raw WS with JSON filter
LatencySub-100ms subscription ack~22ms full block delivery
Tier requiredDeveloper+Business+
Best forWallets, dApps, monitoring specific accountsMEV 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

MethodWhat it streamsTypical use case
slotSubscribe
New slot numbersBlock clock, liveness checks
rootSubscribe
Finalized slotsFinality tracking
accountSubscribe
Account data changesWallet balance updates, PDA state changes
programSubscribe
All accounts owned by a programDEX pool state, staking updates
signatureSubscribe
Transaction confirmation statusConfirm sent transactions in real time
logsSubscribe
Transaction logs matching filterProgram event monitoring
blockSubscribe
Full block dataBlock explorers, indexers
slotsUpdatesSubscribe
Detailed slot lifecycle eventsAdvanced timing, validator monitoring
voteSubscribe
Vote transactionsValidator 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]}
SubscribeUnsubscribe
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

MethodFormatUse 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

MethodDescription
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

FieldTypeDescription
vote
boolInclude vote transactions
failed
boolInclude 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

FieldTypeValues
commitment
string
processed
/
confirmed
/
finalized
encoding
string
base64
/
base58
/
jsonParsed
transactionDetails
string
full
/
signatures
/
none
showRewards
boolInclude 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

MetricValueContext
Solana Slot Resolution~400msThe window in which a block is produced
Competitor "Shreds"~9msFragmented data requiring client-side reassembly
Carbium Full Blocks~22msAtomic, 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

VersionSurfaceStatus
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
ParamRequiredDescription
src_mint
YesInput token mint address
dst_mint
YesOutput token mint address
amount_in
YesInput amount in smallest unit (lamports)
slippage_bps
YesSlippage tolerance in basis points
user_account
NoWallet 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.

EndpointMethodParamsDescription
/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

ProviderID
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 typeRecommended BPSPercentage
Stablecoin swaps5-100.05-0.1%
Major pairs (SOL/USDC)10-500.1-0.5%
Volatile tokens50-1000.5-1%
Arbitrage100.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):

#AccountAccess
0PUMP_GLOBALread
1PUMP_FEE_RECIPIENTwrite
2mintread
3bondingCurvewrite
4bondingCurve ATAwrite
5user ATAwrite
6user/payerwrite, signer
7SystemProgram-
8TokenProgram-
9AssociatedTokenProgram-
10Rent sysvar-
11PUMP_EVENT_AUTHread
12PUMP_PROGRAMread

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

ErrorCauseFix
Blockhash expiredTx took too longFresher blockhash; reduce latency
Insufficient fundsNot enough SOLBalance must cover amount + fees (~0.005 SOL)
Account not foundToken just createdRetry with small delay (50-100ms)
Slippage exceededPrice movedIncrease
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):

JupiterCarbium 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

OperationTimeout
RPC read calls5-10s
Swap quote3-5s
Transaction confirmation30-60s (with polling)

Failure Handling

FailureAction
Quote: no route foundRetry with wider slippage or different provider
Simulation failedDo NOT send — inspect error, log, alert
sendTransaction failedCheck
getSignatureStatus
before retry
Transaction not confirmedPoll with timeout; check blockhash expiry
Stream disconnectedReconnect with exponential backoff
HTTP 429 rate limitBack off immediately; treat as architecture signal

Error Reference

HTTP Status Codes

CodeMeaningAction
401Invalid / missing API keyCheck key and auth format
403Plan restriction (e.g. gRPC on free tier)Upgrade at rpc.carbium.io
429Rate limit exceededBack off + retry; review architecture
400No route found / bad paramsCheck mint addresses, slippage, required params
500Server errorRetry after 1s
503Temporary unavailabilityRetry with exponential backoff

WebSocket Error Codes

CodeMessageCause
-32700
Parse errorMalformed JSON or missing required params
-32601
Method not foundMethod name typo or unsupported method
-32602
Invalid paramsWrong param types or missing fields
-32603
Internal errorServer-side error — retry

Common Token Mints

TokenMint 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

ResourceURL
Ecosystem Overviewdocs.carbium.io/docs/the-carbium-ecosystem
RPC Quick Startdocs.carbium.io/docs/quick-start-rpc
Swap API Quick Startdocs.carbium.io/docs/quick-start-dex-api
gRPC / Streamingdocs.carbium.io/docs/solana-grpc
CQ1 Enginedocs.carbium.io/docs/cq1-engine-overview
RPC Pricingdocs.carbium.io/docs/carbium-rpc-pricing
API Recipesdocs.carbium.io/recipes
FAQdocs.carbium.io/docs/faq
Full AI Contextcarbium.io/llms-ctx.txt
RPC Signuprpc.carbium.io/signup
Swap API Signupapi.carbium.io/login
Discorddiscord.gg/jW7BUkQS5U
Twitter/Xx.com/carbium