GRPC
Carbium is the high-performance Layer 2 streaming service for Solana, providing the fastest Full Block gRPC data in the industry.
Built upon the open-source Yellowstone protocol (Layer 1), Carbium optimizes the delivery pipeline to serve comprehensive, atomic block data with industry-leading latency (~22ms). While other providers prioritize raw "shreds" for marginal speed gains, Carbium focuses on data fidelity and parsing efficiency, offering a gold standard stream for sophisticated trading, indexing, and analytics.
The Carbium Difference
In the Solana ecosystem, gRPC providers generally fall into two categories: those who stream Shreds (raw data fragments) and those who stream Full Blocks (complete ledger units).
1. The "Latency Trap"
A common marketing tactic is to advertise "Shred" latency (8–11ms) as superior to "Full Block" latency (22ms). However, this metric is often misleading when viewed against the actual Solana network speed.
| Metric | Latency | Context |
|---|---|---|
| Solana Slot Resolution | ~400ms | The window in which a block is produced |
| Competitor "Shreds" | ~9ms | Fragmented data requiring reassembly |
| Carbium Full Blocks | ~22ms | Atomic, complete data ready for use |
The Reality: Because Solana slots occur every ~400ms, the 13ms difference between receiving a shred and a full block effectively changes nothing regarding transaction inclusion or execution. You cannot "beat" the slot significantly faster with shreds.
2. Why We Choose Full Blocks (The Gold Standard)
Carbium prioritizes Full Block delivery to provide a robust engineering solution:
- Atomic Integrity: Receive the complete state update in one go. No partial failures or missing fragments.
- Parsing Efficiency: Ideal for complex database indexing (Postgres/RocksDB) where data completeness is critical.
- Simplicity: Reduces the overhead of reassembling shreds on the client side.
Note: We understand some legacy systems prefer shreds. Carbium will be adding a Shreds (Layer 2 Complete) tier soon for users who require that specific ingestion method.
Architecture: From L1 to L2
Carbium is not just a host; it is an optimization layer.
- Layer 1 (Yellowstone): We utilize the standard, open-source Rust implementation used to interface with Solana's RocksDB.
- Layer 2 (Carbium): We apply a proprietary optimization pipeline that aggregates shreds into atomic blocks server-side, ensuring maximum fidelity before the data ever reaches your application.
Connection Details
Carbium exposes a WebSocket endpoint that uses JSON-RPC 2.0 protocol with Yellowstone-compatible subscription methods.
Endpoint
wss://grpc.carbium.io
Authentication
| Method | Format | Use Case |
|---|---|---|
| Query Parameter | wss://grpc.carbium.io/?apiKey=YOUR_API_KEY | Recommended for WebSocket clients |
| Header | x-token: YOUR_API_KEY | For HTTP-based connections |
Protocol
Carbium uses JSON-RPC 2.0 over WebSocket. Messages are sent as JSON text frames.
Available Methods
| Method | Description |
|---|---|
transactionSubscribe | Subscribe to real-time transactions with filters |
transactionUnsubscribe | Unsubscribe from transaction stream |
Code Examples
TypeScript / Node.js
import WebSocket from "ws";
const API_KEY = "YOUR_API_KEY";
const PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"; // Example: Pump.fun
async function main() {
const ws = new WebSocket(`wss://grpc.carbium.io/?apiKey=${API_KEY}`);
ws.on("open", () => {
console.log("Connected to Carbium");
// Subscribe to transactions for a specific program
const request = {
jsonrpc: "2.0",
id: 1,
method: "transactionSubscribe",
params: [
{
// Filter configuration
vote: false, // Exclude vote transactions
failed: false, // Exclude failed transactions
accountInclude: [PROGRAM_ID], // Programs to include
accountExclude: [], // Programs to exclude
accountRequired: [], // All listed accounts must be present
},
{
// Subscription options
commitment: "confirmed", // confirmed | finalized | processed
encoding: "base64", // base64 | base58 | jsonParsed
transactionDetails: "full", // full | signatures | none
showRewards: false,
maxSupportedTransactionVersion: 0,
},
],
};
ws.send(JSON.stringify(request));
});
ws.on("message", (data) => {
const message = JSON.parse(data.toString());
// Subscription confirmation
if (message.result !== undefined) {
console.log(`Subscribed with ID: ${message.result}`);
return;
}
// Transaction notification
if (message.method === "transactionNotification") {
const { signature, slot, transaction } = message.params.result;
console.log(`Transaction: ${signature} (slot ${slot})`);
// transaction.transaction[0] contains base64-encoded transaction data
// transaction.meta contains execution metadata
}
});
ws.on("error", (error) => {
console.error("WebSocket error:", error.message);
});
ws.on("close", (code, reason) => {
console.log(`Disconnected: ${code} - ${reason}`);
});
}
main();Transaction Filter Options
The first parameter of transactionSubscribe accepts these filter options:
| Field | Type | Description |
|---|---|---|
vote | boolean | Include vote transactions |
failed | boolean | Include failed transactions |
accountInclude | string[] | Include transactions involving ANY of these accounts |
accountExclude | string[] | Exclude transactions involving these accounts |
accountRequired | string[] | Only include transactions involving ALL of these accounts |
Important: At least one of accountInclude or accountRequired must contain values.
Subscription Options
The second parameter configures the response format:
| Field | Type | Description |
|---|---|---|
commitment | string | processed, confirmed, or finalized |
encoding | string | base64, base58, or jsonParsed |
transactionDetails | string | full, signatures, or none |
showRewards | boolean | Include reward information |
maxSupportedTransactionVersion | number | Max transaction version (0 for legacy + v0) |
Response Format
Subscription Confirmation
{
"jsonrpc": "2.0",
"result": 1234567890,
"id": 1
}The result is your subscription ID, used for unsubscribing.
Transaction Notification
{
"jsonrpc": "2.0",
"method": "transactionNotification",
"params": {
"result": {
"signature": "5VERv8NMvzbJM...",
"slot": 123456789,
"transaction": {
"transaction": ["base64_encoded_data", "base64"],
"meta": {
"err": null,
"fee": 5000,
"preBalances": [...],
"postBalances": [...],
"logMessages": [...]
}
}
},
"subscription": 1234567890
}
}Rust
Using the standard yellowstone-grpc-client crate with HTTP/2 gRPC:
use yellowstone_grpc_client::GeyserGrpcClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let endpoint = "https://grpc.carbium.io";
let x_token = "YOUR_API_KEY";
let mut client = GeyserGrpcClient::connect(endpoint, x_token, None)?;
let (mut subscribe_tx, mut stream) = client.subscribe().await?;
// Define your subscription filters...
Ok(())
}Python
import asyncio
import websockets
import json
API_KEY = "YOUR_API_KEY"
PROGRAM_ID = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
async def subscribe():
uri = f"wss://grpc.carbium.io/?apiKey={API_KEY}"
async with websockets.connect(uri) as ws:
# Subscribe to transactions
request = {
"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,
},
],
}
await ws.send(json.dumps(request))
async for message in ws:
data = json.loads(message)
if "result" in data:
print(f"Subscribed: {data['result']}")
elif data.get("method") == "transactionNotification":
sig = data["params"]["result"]["signature"]
print(f"Transaction: {sig[:20]}...")
asyncio.run(subscribe())Unsubscribing
To unsubscribe, send:
{
"jsonrpc": "2.0",
"id": 2,
"method": "transactionUnsubscribe",
"params": [SUBSCRIPTION_ID]
}Pricing
Carbium gRPC is included in plans $320 and above.
FAQ
Q: Is Carbium compatible with standard Yellowstone clients?
A: Yes for Rust clients using HTTP/2 gRPC. For TypeScript/JavaScript/Python, use the WebSocket JSON-RPC interface as shown in the examples above. The subscription filters and data format follow Yellowstone conventions.
Q: Why is your "Full Block" stream 22ms when others claim 10ms?
A: Those claims usually refer to "shreds" (partial data). Carbium delivers the entire block in 22ms. We are the fastest Full Block provider in the industry.
Q: Does the extra 12ms latency matter for trading?
A: Generally, no. With Solana's slot times averaging 400ms, a 12ms delta is negligible for execution. However, the data quality difference is massive. Full Blocks allow for robust, error-free parsing that shreds cannot match.
Q: What's the difference between accountInclude and accountRequired?
accountInclude and accountRequired?A:
accountInclude: Transaction must involve at least one of the listed accountsaccountRequired: Transaction must involve all of the listed accounts
For example, to get only token creation transactions for Pump.fun, you might use:
{
"accountRequired": ["6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P", "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM"]
}Q: Why do I get "Invalid params" errors?
A: Ensure at least one of accountInclude or accountRequired contains values. Empty arrays for both will return an error.
Support
- Discord: Carbium Discord Server
Updated about 1 month ago
