Yellowstone gRPC Overview

cubestech provides access to the Yellowstone Dragon's Mouth gRPC interface - a high-performance streaming API built on Solana's Geyser plugin architecture.

Yellowstone gRPC enables real-time streaming of accounts, transactions, slots, blocks, and entries with advanced filtering, significantly outperforming traditional WebSocket and polling-based approaches.

Endpoint

text
geyser.sol.cubestech.online:443:443

Authenticate with the x-api-key header on every request.

Key Advantages

  • Low latency - direct Geyser plugin access, data arrives before RPC processing
  • Rich filtering - filter by account, owner, program, transaction participants, and more
  • Bidirectional streaming - update subscription filters without reconnecting
  • Typed data - Protocol Buffers provide strict typing and efficient serialization

Service Definition

The Geyser service exposes two bidirectional streaming RPCs and several unary methods:

protobuf
service Geyser {
  // Bidirectional streaming subscriptions
  rpc Subscribe(stream SubscribeRequest) returns (stream SubscribeUpdate) {}
  rpc SubscribeDeshred(stream SubscribeDeshredRequest) returns (stream SubscribeUpdateDeshred) {}

  // Unary methods
  rpc SubscribeReplayInfo(SubscribeReplayInfoRequest) returns (SubscribeReplayInfoResponse) {}
  rpc Ping(PingRequest) returns (PongResponse) {}
  rpc GetLatestBlockhash(GetLatestBlockhashRequest) returns (GetLatestBlockhashResponse) {}
  rpc GetBlockHeight(GetBlockHeightRequest) returns (GetBlockHeightResponse) {}
  rpc GetSlot(GetSlotRequest) returns (GetSlotResponse) {}
  rpc IsBlockhashValid(IsBlockhashValidRequest) returns (IsBlockhashValidResponse) {}
  rpc GetVersion(GetVersionRequest) returns (GetVersionResponse) {}
}

Commitment Levels

protobuf
enum CommitmentLevel {
  PROCESSED = 0;
  CONFIRMED = 1;
  FINALIZED = 2;
}
LevelValueDescription
PROCESSED0Processed by the connected node (fastest, may be reverted)
CONFIRMED1Confirmed by supermajority vote
FINALIZED2Finalized by supermajority (most reliable)

Connection Keep-Alive

Some load balancers terminate gRPC connections if the client is idle. The server sends Ping messages every 15 seconds - reply with a SubscribeRequest containing a ping message with an id field (any int32 value) to keep the connection alive.

Subscribe

The Subscribe RPC is a bidirectional stream. The client sends SubscribeRequest messages to set or update filters, and the server responds with a continuous stream of SubscribeUpdate messages.

protobuf
rpc Subscribe(stream SubscribeRequest) returns (stream SubscribeUpdate) {}

SubscribeRequest

map<string, SubscribeRequestFilterAccounts>

Named account subscription filters. See Account Filters.

map<string, SubscribeRequestFilterSlots>

Named slot subscription filters. See Slot Filters.

map<string, SubscribeRequestFilterTransactions>

Named transaction subscription filters. See Transaction Filters.

map<string, SubscribeRequestFilterTransactions>

Same filters as transactions, but only returns status (no full transaction data).

map<string, SubscribeRequestFilterBlocks>

Named block subscription filters. See Block Filters.

map<string, SubscribeRequestFilterBlocksMeta>

Block metadata filters. See Block Metadata Filters.

map<string, SubscribeRequestFilterEntry>

Entry subscription filters. See Entry Filters.

CommitmentLevel

Commitment level: PROCESSED (0), CONFIRMED (1), FINALIZED (2).

array

Array of { offset: uint64, length: uint64 } objects to receive only specific slices of account data.

SubscribeRequestPing

Send a ping to keep the connection alive. Contains a single field: id (int32) - set to any integer value. The server responds with a Pong echoing the same id.

uint64

Start streaming from this slot (replay support).

SubscribeUpdate

Each update contains the matched filter names and exactly one update type:

filtersarray

Names of the filters that matched this update.

update_oneofoneof
Update types
accountSubscribeUpdateAccount
Account data change.
slotSubscribeUpdateSlot
Slot status change.
transactionSubscribeUpdateTransaction
Full transaction data.
transaction_statusSubscribeUpdateTransactionStatus
Transaction status only.
blockSubscribeUpdateBlock
Full block data.
block_metaSubscribeUpdateBlockMeta
Block metadata only.
entrySubscribeUpdateEntry
Ledger entry.
pingSubscribeUpdatePing
Server ping.
pongSubscribeUpdatePong
Pong response to client ping.
created_atTimestamp

Server-side timestamp when the update was created.

Example: Subscribe to All Slots

typescript
import Client, { CommitmentLevel } from "@triton-one/yellowstone-grpc";

// The SDK sends its token argument through x-token metadata
const client = new Client("geyser.sol.cubestech.online:443:443", "YOUR_API_KEY", {
  grpcMaxDecodingMessageSize: 64 * 1024 * 1024,
});

await client.connect();
const stream = await client.subscribe();

stream.on("data", (data) => {
  if (data.slot) {
    console.log(`Slot: ${data.slot.slot}, Status: ${data.slot.status}`);
  }
});

// Send subscription request
const request = {
  slots: {
    mySlots: { filterByCommitment: true },
  },
  commitment: CommitmentLevel.CONFIRMED,
  accounts: {},
  transactions: {},
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
};

stream.write(request);
python
import grpc
import geyser_pb2
import geyser_pb2_grpc

# Auth plugin - sends x-api-key as gRPC metadata
class KeyAuth(grpc.AuthMetadataPlugin):
    def __init__(self, api_key):
        self.api_key = api_key
    def __call__(self, context, callback):
        callback([("x-api-key", self.api_key)], None)

ssl_creds = grpc.ssl_channel_credentials()
call_creds = grpc.metadata_call_credentials(KeyAuth("YOUR_API_KEY"))
combined_creds = grpc.composite_channel_credentials(ssl_creds, call_creds)

channel = grpc.secure_channel("geyser.sol.cubestech.online:443:443", credentials=combined_creds)
stub = geyser_pb2_grpc.GeyserStub(channel)

# Create subscription request
request = geyser_pb2.SubscribeRequest(
    slots={"mySlots": geyser_pb2.SubscribeRequestFilterSlots(
        filter_by_commitment=True
    )},
    commitment=geyser_pb2.CONFIRMED,
)

# Subscribe and process updates
for update in stub.Subscribe(iter([request])):
    if update.HasField("slot"):
        print(f"Slot: {update.slot.slot}, Status: {update.slot.status}")

Updating Filters

Since Subscribe is bidirectional, you can send a new SubscribeRequest at any time to update your filters without reconnecting:

typescript
// Initial subscription for slots
stream.write({
  slots: { mySlots: {} },
  accounts: {},
  transactions: {},
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.CONFIRMED,
});

// Later: add account subscription without reconnecting
stream.write({
  slots: { mySlots: {} },
  accounts: {
    myAccounts: {
      account: ["vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg"],
    },
  },
  transactions: {},
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
  commitment: CommitmentLevel.CONFIRMED,
});

Each new SubscribeRequest completely replaces the previous filters. Include all desired filters in every request.