Skip to main content

Overview

Yellowstone gRPC provides two related but distinct subscription types for tracking network progress:
  • Slots — lightweight updates indicating when a slot reaches processed, confirmed, or finalized commitment. Low bandwidth, useful for consensus monitoring.
  • Blocks — full block data including transactions, account updates, and entries. Higher bandwidth, useful for indexers and analytics.

Slot Subscriptions

Filter Parameters

ParameterTypeDescription
filterByCommitmentbooleanWhen true, only emit slot updates that match the subscription’s commitment level. When false (default), emit updates for all commitment levels.
interslotUpdatesbooleanWhen true, emit intra-slot state changes, not just slot boundaries. Useful for granular real-time monitoring.

Example: Track Confirmed Slots

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

const GRPC_URL = "https://your-endpoint.grpc.orbitflare.com";
const X_TOKEN = "YOUR_GRPC_TOKEN";

const client = new Client(GRPC_URL, X_TOKEN, {
  "grpc.max_receive_message_length": 64 * 1024 * 1024,
});

async function main() {
  const stream = await client.subscribe();

  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => { reject(error); stream.end(); });
    stream.on("end", () => resolve());
    stream.on("close", () => resolve());
  });

  stream.on("data", (data) => {
    if (data.slot) {
      const { slot, parent, status } = data.slot;
      console.log(`Slot ${slot} (parent: ${parent}) — status: ${status}`);
    } else if (data.pong) {
      console.log("Pong received");
    }
  });

  const request: SubscribeRequest = {
    slots: {
      slotUpdates: {
        filterByCommitment: true,
      },
    },
    commitment: CommitmentLevel.CONFIRMED,
    accounts: {},
    accountsDataSlice: [],
    transactions: {},
    transactionsStatus: {},
    blocks: {},
    blocksMeta: {},
    entry: {},
    ping: { id: 1 },
  };

  await new Promise<void>((resolve, reject) => {
    stream.write(request, (err) => {
      if (err == null) resolve(); else reject(err);
    });
  });

  setInterval(() => {
    stream.write({ ping: { id: 1 }, accounts: {}, accountsDataSlice: [], transactions: {}, transactionsStatus: {}, slots: {}, blocks: {}, blocksMeta: {}, entry: {} }, () => {});
  }, 30_000);

  await streamClosed;
}

main();

Block Subscriptions

Filter Parameters

ParameterTypeDescription
accountIncludestring[]Filter transactions and account updates within blocks to only include these accounts.
includeTransactionsbooleanInclude full transaction data in each block update.
includeAccountsbooleanInclude account state updates in each block update.
includeEntriesbooleanInclude entries (execution units) in each block update.
Block subscriptions with includeTransactions: true and no account filter produce very high data volumes. Use accountInclude to narrow the stream to accounts you care about, or combine with a dedicated node for sustained throughput.

Example: Stream Blocks with Transactions

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

const client = new Client(
  "https://your-endpoint.grpc.orbitflare.com",
  "YOUR_GRPC_TOKEN",
  { "grpc.max_receive_message_length": 1024 * 1024 * 1024 }
);

async function main() {
  const stream = await client.subscribe();

  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => { reject(error); stream.end(); });
    stream.on("end", () => resolve());
    stream.on("close", () => resolve());
  });

  stream.on("data", (data) => {
    if (data.block) {
      const { block } = data;
      console.log(`Block slot: ${block.slot}`);
      console.log(`  Blockhash: ${block.blockhash}`);
      console.log(`  Transactions: ${block.transactions?.length ?? 0}`);
    }
  });

  const request: SubscribeRequest = {
    blocks: {
      blockStream: {
        accountInclude: [
          "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", // Raydium AMM
        ],
        includeTransactions: true,
        includeAccounts: false,
        includeEntries: false,
      },
    },
    commitment: CommitmentLevel.CONFIRMED,
    accounts: {},
    accountsDataSlice: [],
    transactions: {},
    transactionsStatus: {},
    slots: {},
    blocksMeta: {},
    entry: {},
    ping: { id: 1 },
  };

  await new Promise<void>((resolve, reject) => {
    stream.write(request, (err) => {
      if (err == null) resolve(); else reject(err);
    });
  });

  setInterval(() => {
    stream.write({ ping: { id: 1 }, accounts: {}, accountsDataSlice: [], transactions: {}, transactionsStatus: {}, slots: {}, blocks: {}, blocksMeta: {}, entry: {} }, () => {});
  }, 30_000);

  await streamClosed;
}

main();

Example: Block Metadata Only

Use blocksMeta to receive lightweight block headers (slot, blockhash, block time) without transaction payloads:
const request: SubscribeRequest = {
  blocksMeta: {
    blockMeta: {},
  },
  commitment: CommitmentLevel.FINALIZED,
  accounts: {},
  accountsDataSlice: [],
  transactions: {},
  transactionsStatus: {},
  slots: {},
  blocks: {},
  entry: {},
};

Choosing Between Slots and Blocks

NeedUse
Detect when a slot finalizesSlot subscription (filterByCommitment: true)
Track block height progressSlot subscription
Index all transactions in a blockBlock subscription (includeTransactions: true)
Monitor account state changes per blockBlock subscription (includeAccounts: true)
Minimal latency consensus signalSlot subscription at processed
Full archive-quality block dataBlock subscription at finalized