Carbium for Trading Bots

Build Solana trading bots on Carbium with the right split between RPC, Swap API, CQ1-backed quote flows, gRPC streaming, and production-safe key handling.

Carbium for Trading Bots

Trading bots usually fail for boring reasons before they fail for strategy reasons. The common breakpoints are stale reads, bursty retries, exposed keys, and execution paths that mix quote, sign, and submit concerns in one fragile process.

Carbium's public docs already cover the main surfaces a Solana bot needs:

  • RPC for reads, writes, and transaction submission over https://rpc.carbium.io/?apiKey=...
  • Swap API for quote and executable transaction flows over https://api.carbium.io/api/v2/quote
  • CQ1-backed routing when your strategy needs the Swap API's routing engine instead of a single DEX path
  • gRPC at grpc.carbium.io for transaction-centric real-time feeds when polling is too slow or too expensive

Part of the Carbium Solana infrastructure stack.

Use the right Carbium surface for each bot job

Bot jobBest Carbium surfaceWhy
Read slots, balances, recent blockhashes, and signature statusRPCStandard Solana JSON-RPC with normal SDK support
Request an executable route for a swapSwap APIThe published quote flow can return a serialized transaction when user_account is included
Submit the signed transactionRPCKeeps execution on the standard Solana submission path
Watch transaction-heavy flows with less pollinggRPCBetter fit once bot traffic or latency pressure makes constant RPC reads wasteful
Compare and execute routed swaps across supported DEX liquiditySwap API / CQ1Carbium documents CQ1 as the routing layer behind its API execution path

This page owns the build pattern for bot teams. For detailed throttling behavior, use Solana RPC Rate Limits Explained. For key handling, use API Key Security Best Practices.

Recommended architecture for most bots

The cleanest production split is:

  1. A reader that pulls RPC state or listens on gRPC.
  2. A decision layer that decides whether the signal is actionable.
  3. An execution service that requests a quote, signs, submits, and confirms.

Keep the keys and signing boundary inside backend services you control. Do not let one loop both discover opportunities and blindly hammer submission retries without checking chain state.

flowchart LR
    A["Market state"] --> B["Bot reader"]
    B --> C["Decision layer"]
    C --> D["Quote request<br/>api.carbium.io/api/v2/quote"]
    D --> E["Signed transaction"]
    E --> F["RPC submit<br/>rpc.carbium.io"]
    F --> G["Status + confirmation"]
    B --> H["gRPC listener<br/>grpc.carbium.io"]
    H --> C

Start simple: quote on API, execute on RPC

If your strategy is route-aware and execution-focused, a minimal Carbium bot usually needs only two live paths:

  • request a quote from the Swap API
  • submit the resulting signed transaction through RPC

That keeps the first version of the bot operational without forcing a streaming stack on day one.

Minimal TypeScript flow

import { Connection, Keypair, VersionedTransaction } from "@solana/web3.js";
import bs58 from "bs58";

const RPC_URL = `https://rpc.carbium.io/?apiKey=${process.env.CARBIUM_RPC_KEY}`;
const QUOTE_URL = "https://api.carbium.io/api/v2/quote";

const connection = new Connection(RPC_URL, "confirmed");
const signer = Keypair.fromSecretKey(bs58.decode(process.env.BOT_PRIVATE_KEY!));

async function fetchExecutableQuote(params: {
  srcMint: string;
  dstMint: string;
  amountIn: string;
}) {
  const url = new URL(QUOTE_URL);
  url.searchParams.set("src_mint", params.srcMint);
  url.searchParams.set("dst_mint", params.dstMint);
  url.searchParams.set("amount_in", params.amountIn);
  url.searchParams.set("slippage_bps", "50");
  url.searchParams.set("user_account", signer.publicKey.toBase58());

  const res = await fetch(url, {
    headers: {
      "X-API-KEY": process.env.CARBIUM_API_KEY!,
      "Accept": "application/json",
    },
  });

  if (!res.ok) {
    throw new Error(`Quote failed with ${res.status}`);
  }

  const quote = await res.json();

  if (!quote.txn) {
    throw new Error("Quote response did not include an executable transaction");
  }

  return quote;
}

async function executeQuotedSwap() {
  const quote = await fetchExecutableQuote({
    srcMint: "So11111111111111111111111111111111111111112",
    dstMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    amountIn: "10000000",
  });

  const transaction = VersionedTransaction.deserialize(
    Buffer.from(quote.txn, "base64")
  );

  transaction.sign([signer]);

  const signature = await connection.sendTransaction(transaction, {
    skipPreflight: false,
    maxRetries: 3,
  });

  const status = await connection.confirmTransaction(signature, "confirmed");
  return { signature, status, routePlan: quote.routePlan };
}

This pattern matches Carbium's published docs:

  • user_account on the quote request returns an executable transaction payload
  • the signed transaction is submitted through standard Solana RPC
  • confirmation should be checked before the bot decides the trade failed

When to add gRPC

Do not add streaming because it sounds more advanced. Add it when your current bot shape proves that polling is the wrong tool.

Good reasons to add gRPC:

  • you monitor many programs or transaction flows continuously
  • your bot reacts to transaction-level events and polling misses timing windows
  • repeated RPC reads are creating rate-limit pressure
  • you need one backend listener to feed several strategy workers

Carbium's public docs position grpc.carbium.io as the real-time path and document that gRPC starts at the Business tier. Use that as a design checkpoint: if streaming is mandatory for the bot to work, validate the plan and endpoint before you scale the strategy.

Minimal listener shape

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: ["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"],
          accountExclude: [],
          accountRequired: [],
        },
        {
          commitment: "confirmed",
          encoding: "base64",
          transactionDetails: "full",
          showRewards: false,
          maxSupportedTransactionVersion: 0,
        },
      ],
    })
  );
});

Use streaming to feed the decision layer. Keep execution and retry policy separate so one noisy feed does not turn into duplicate submissions.

Production notes that matter more than strategy tweaks

Separate secrets and workloads

Use separate environment variables for:

  • CARBIUM_RPC_KEY
  • CARBIUM_API_KEY
  • signing material such as BOT_PRIVATE_KEY

If you run multiple bots or environments, split keys per service where practical. That limits blast radius and makes rate anomalies easier to isolate.

Treat 429s as architecture feedback

If a bot gets 429 responses, do not just raise retry counts. The usual fixes are:

  • reduce duplicated reads
  • add jitter and backoff
  • centralize request budgeting
  • move hot monitoring paths to gRPC when that actually reduces polling pressure

The detailed throttling guidance belongs on the rate-limits page, not here.

Confirm before replaying

The most expensive bot bug is often duplicate execution. Before retrying sendTransaction, check signature status first and decide whether the original submission already landed.

Keep quote and submit logs correlated

Store enough information to answer:

  • which signal triggered the trade
  • which quote parameters were used
  • which route plan came back
  • which signature was submitted
  • whether the final status was confirmed, failed, or abandoned

That makes post-trade debugging much faster than trying to reconstruct intent from RPC logs alone.

Bot launch checklist

Before you run real capital through the bot, verify:

  • the bot can complete a quote -> sign -> submit -> confirm loop in your target environment
  • RPC and API keys live only in backend env vars or a secret manager
  • sendTransaction retries always check signature status first
  • rate-limit handling uses backoff instead of parallel blind retries
  • gRPC is only required if your strategy truly needs streaming
  • the expected workload fits the Carbium plan you selected
📘This page is the implementation guide for bot architecture. Keep rate-limit rules, plan selection, and key-hardening details in their dedicated canonical pages rather than duplicating them inside strategy docs.
🔶Building a Solana trading bot on Carbium? Start with a controlled backend flow and validate plan fit at carbium.io.