Documentation

gRPC examples

Copy-paste Yellowstone gRPC subscription code with token auth for accounts, transactions, and slots in TypeScript, Rust, Python, and grpcurl.

// updated 2026-08-26

Working code to connect to Supanode gRPC and subscribe to streams.

Prerequisites

  • A Supanode account on a plan with gRPC (FOCUS, BUILD, GROW, or PROFESSIONAL).
  • Your token, issued on provisioning. Send it as x-token (or Authorization: Bearer) on every connection - see Authentication.
  • Your gRPC endpoint - default Frankfurt: fra.sol.supanode.xyz:10010.
  • Yellowstone gRPC client library for your language, plus geyser.proto and solana-storage.proto from the Yellowstone repo. Server reflection is disabled, so the proto files are required.
NOTE

Before you write filters, read Limits. One filter holds at most 2 000 addresses and one subscription at most 10 filters. Sending your whole address budget in a single filter is the most common first mistake.

Don't have an account yet? Get a 24-hour free trial - contact us on Telegram: @supanode_tgs.

Test connection

Before writing code, verify your endpoint is reachable using grpcurl:

grpcurl -plaintext -import-path ./proto -proto geyser.proto \
  -H 'x-token: sk_your_token_here' \
  -d '{}' \
  fra.sol.supanode.xyz:10010 geyser.Geyser/GetVersion

If you see a version number in the response, your token and connection both work. A missing or wrong token returns PermissionDenied.

Basic subscribe example

Subscribes to all successful transactions involving a specific program. The Python example generates its stubs from the Yellowstone gRPC geyser.proto.

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

// Second argument is your token — the client sends it as x-token.
const client = new Client(
  "http://fra.sol.supanode.xyz:10010",
  process.env.SUPANODE_TOKEN,
  { "grpc.max_receive_message_length": 64 * 1024 * 1024 }
);

const stream = await client.subscribe();

const request: SubscribeRequest = {
  commitment: CommitmentLevel.CONFIRMED,
  accounts: {},
  slots: {},
  transactions: {
    myFilter: {
      vote: false,
      failed: false,
      accountInclude: ["YOUR_PROGRAM_ID"],
      accountExclude: [],
      accountRequired: [],
    },
  },
  transactionsStatus: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
  accountsDataSlice: [],
};

stream.write(request);

stream.on("data", (data) => {
  if (data.transaction) {
    console.log(`Transaction: ${data.transaction.signature}`);
  }
});

Production tips

  1. Reconnection with exponential backoff. Network blips happen. Implement retry logic that starts at 1 second and backs off to 30 seconds. On 429 or 503 errors, always back off before retrying.

  2. Ping/pong for keepalive. Yellowstone server sends ping every 15 seconds. Most client libraries handle this automatically.

  3. Use accountsDataSlice to reduce bandwidth. If you only need part of an account's data, specify accountsDataSlice: [{offset: 0, length: 40}].

  4. Choose commitment level wisely. processed is fastest but can revert. confirmed is the practical default for trading. finalized adds ~13 seconds of latency.

  5. Handle stream restart gracefully. When your stream restarts, you'll miss events during downtime. Design your application to recover from this.

  6. Do not read the first message as an acceptance. The server sends a ping immediately, and a rejection arrives after it. Wait for a real data message or an error before you consider the subscription live - see Limits.

  7. Close streams you stop using. Your address budget is counted across everything open at once, and closing a subscription frees it immediately.

Where to go next

Limits
Subscription caps and how to lay out addresses.
Restrictions
What's not supported on shared.
Free Trials
24-hour gRPC trial.
Yellowstone examples
More examples on GitHub.