Solana - gRPC

Solana Yellowstone gRPC enables real-time streaming of transactions, accounts, slots, and blocks without polling.

Solana Yellowstone gRPC establishes a persistent stream and pushes data to your application as events occur on-chain. It is a strong fit for systems that need fresh Solana data immediately, such as trading infrastructure, indexers, real-time analytics, wallets, and monitoring services.

With Tatum’s Yellowstone gRPC endpoint, you can retrieve:

Solana Mainnet gRPC endpoint

Yellowstone gRPC (Mainnet)

↳ gRPC (Mainnet)
https://solana-mainnet-grpc.gateway.tatum.io

For JSON-RPC, Devnet, and the full network list, see Solana RPC.

Test Solana in Postman

Use the collections below to try gRPC streaming against Tatum’s Solana gateway.

Solana Mainnet gRPC Postman collection

  1. Get your API key: Same Tatum API key as REST/JSON-RPC; gRPC uses the x-token header (see Authentication below)
  2. Import the collection: Open Postman using the button below
  3. Configure variables: Set host and API key per the collection’s instructions
  4. Start testing: Call Yellowstone-style methods (for example GetVersion) and subscriptions as provided in the collection

Endpoint validation toolkit

If you need to verify behavior across reconnects, keepalive, resubscribe, and concurrency scenarios, use the open-source test suite:

Getting Started

Set Up Your Environment

This guide uses Node.js with TypeScript and the official Yellowstone gRPC client on macOS. Before writing code, install Node.js and (optionally) grpcurl for endpoint smoke testing.

  1. Install Node.js (version 18+)

    brew install node
    node -v
  2. Install grpcurl (optional)
    grpcurl helps verify your endpoint and API key before you run app code.

    brew install grpcurl
  3. Create your project and install dependencies:

    mkdir tatum-grpc-test
    cd tatum-grpc-test
    npm init -y
    npm install @triton-one/yellowstone-grpc
    npm install -D tsx typescript @types/node
    📘

    Note

    Use tsx instead of ts-node to run TypeScript files directly. It's faster and requires no additional tsconfig.json setup.

  4. Download the Yellowstone proto files (required for grpcurl smoke tests):

    curl -o geyser.proto https://raw.githubusercontent.com/rpcpool/yellowstone-grpc/master/yellowstone-grpc-proto/proto/geyser.proto
    curl -o solana-storage.proto https://raw.githubusercontent.com/rpcpool/yellowstone-grpc/master/yellowstone-grpc-proto/proto/solana-storage.proto
    
    # Your project folder should now look like this:
    tatum-grpc-test/
    ├── geyser.proto
    ├── solana-storage.proto
    ├── node_modules/
    ├── package.json
    └── get-block.ts      // ← your script goes here
  5. Verify your connection with grpcurl before writing app code.

    • Tatum-specific: The gRPC endpoint is solana-mainnet-grpc.gateway.tatum.io:443 (Mainnet).
    • Authentication uses the x-token header. This is your Tatum API key (x-api-key) sent under Yellowstone's expected header name.
    grpcurl \
      -proto geyser.proto \
      -import-path . \
      -H "x-token: YOUR_API_KEY" \
      solana-mainnet-grpc.gateway.tatum.io:443 \
      geyser.Geyser/GetVersion

    Expected response format:

    {
      "version": "{\"version\":{\"package\":\"yellowstone-grpc-geyser\",\"version\":\"12.1.0+solana.3.1.10\",\"proto\":\"12.1.0+solana.3.1.10\",\"solana\":\"3.1.10\",\"git\":\"f0ae884\",\"rustc\":\"1.86.0\",\"buildts\":\"2026-03-12T09:16:09.772120954Z\"},\"extra\":{\"hostname\":\"relevant-marten\"}}"
    }
    🚧

    Attention

    • If you see a version response, your endpoint and API key are working.
    • If this step fails, no amount of Node.js code will fix it. Confirm your environment setup and credentials

Quick start checklist

Before opening a stream, confirm:

  • You can call GetVersion successfully with grpcurl
  • Your API key has access to the endpoint
  • Your service can keep long-lived outbound connections
  • You have a reconnect strategy for network interruptions
  • You selected the correct network endpoint for your environment (Mainnet vs Devnet JSON-RPC)

Authentication in Yellowstone gRPC client

  1. Get the Solana gRPC URL.
  2. Create an API Key in your Tatum Dashboard.
  3. Configure your client with the endpoint and token:
import Client, {
  CommitmentLevel,
} from "@triton-one/yellowstone-grpc";

const ENDPOINT = "https://solana-mainnet-grpc.gateway.tatum.io";
const X_TOKEN = "YOUR_API_KEY";

Example Requests

🚧

Attention

These are minimal examples. For production systems, implement reconnection handling, checkpointing, and idempotent downstream processing.

End-to-end stream example (transactions)

The following script opens a stream and subscribes to all finalized, non-vote, non-failed transactions.

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

const ENDPOINT = "https://solana-mainnet-grpc.gateway.tatum.io";
const X_TOKEN = "YOUR_API_KEY";

async function main() {
  const client = new Client(ENDPOINT, X_TOKEN);
  const stream = await client.subscribe();

  stream.on("data", (message) => {
    if (message.transaction) {
      const slot = message.transaction.slot;
      const signature = Buffer.from(
        message.transaction.transaction.signature,
      ).toString("base64");
      console.log(`tx received: slot=${slot} signature=${signature}`);
    }
  });

  stream.on("error", (error) => {
    console.error("stream error:", error);
  });

  stream.on("end", () => {
    console.log("stream closed");
  });

  const request: SubscribeRequest = {
    slots: {},
    accounts: {},
    transactions: {
      alltxs: {
        vote: false,
        failed: false,
      },
    },
    blocks: {},
    blocksMeta: {},
    accountsDataSlice: [],
    commitment: CommitmentLevel.FINALIZED,
    entry: {},
    transactionsStatus: {},
  };

  stream.write(request);
  console.log("subscription started");
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});

Run it with:

npx tsx get-transactions.ts

Troubleshooting

If streaming does not start, check:

  • Auth failures: ensure x-token contains a valid Tatum API key
  • Wrong interface/network: verify you are using Mainnet gRPC endpoint (not Devnet JSON-RPC endpoint)
  • No data received: verify your subscription filter is broad enough
  • Frequent disconnects: add retries with exponential backoff and jitter
  • Consumer overload: add buffering/queueing and process messages asynchronously

Retrieve an account

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

const request = {
  "slots": {
    "slots": {}
  },
  "accounts": {
    "wsol/usdc": {
      "account": ["8BnEgHoWFysVcuFFX7QztDmzuH8r5ZFvyP3sYwn1XTh6"]
    }
  },
  "transactions": {},
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.CONFIRMED,
  "entry": {},
  "transactionsStatus": {}
};

Use this request when you need account-level state changes for a known address.

Retrieve all finalized non-vote and non-failed transactions

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

const request = {
  "slots": {
    "slots": {}
  },
  "accounts": {},
  "transactions": {
    "alltxs": {
      "vote": false,
      "failed": false
    }
  },
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "commitment": CommitmentLevel.FINALIZED,
  "entry": {},
  "transactionsStatus": {}
};

Use this request to monitor finalized transaction flow while excluding vote and failed transactions.

Retrieve slots

const request = {
  "slots": {
    "incoming_slots": {}
  },
  "accounts": {},
  "transactions": {},
  "blocks": {},
  "blocksMeta": {},
  "accountsDataSlice": [],
  "entry": {},
  "transactionsStatus": {}
};

Use this request for slot-level progression and liveness monitoring.

Retrieve blocks

const request = {
  "slots": {},
  "accounts": {},
  "transactions": {},
  "blocks": {
    "blocks": {}
  },
  "blocksMeta": {},
  "accountsDataSlice": [],
  "entry": {},
  "transactionsStatus": {}
};

Use this request for block-by-block ingestion pipelines.

Retrieve block metadata

const request = {
  "slots": {},
  "accounts": {},
  "transactions": {},
  "blocks": {},
  "blocksMeta": {
    "blockmetadata": {}
  },
  "accountsDataSlice": [],
  "entry": {},
  "transactionsStatus": {}
};

Use this request when you only need block headers and metadata, not full block payloads.