Skip to main content
The TypeScript client provides a high-performance interface to Yellowstone gRPC with native Rust bindings via NAPI-RS.

Installation

Install the client from npm:
npm install @triton-one/yellowstone-grpc

Requirements

  • Node.js >= 20.18.0
  • Supported platforms:
    • Linux x64 (GNU and musl)
    • macOS x64 and ARM64 (Apple Silicon)

Quick Start

Basic Connection

Connect to a Yellowstone gRPC server:
import Client from "@triton-one/yellowstone-grpc";

async function main() {
  const client = new Client(
    "https://api.rpcpool.com:443",
    "your-token-here",
    {
      grpcMaxDecodingMessageSize: 64 * 1024 * 1024, // 64 MiB
    }
  );

  await client.connect();

  const version = await client.getVersion();
  console.log("Server version:", version);
}

main();

Client Constructor

const client = new Client(
  endpoint: string,
  xToken: string | undefined,
  channelOptions: JsChannelOptions | undefined
);
Parameters:
  • endpoint - gRPC server URL (e.g., "http://localhost:10000")
  • xToken - Optional authentication token
  • channelOptions - Optional gRPC channel configuration:
    • grpcMaxDecodingMessageSize - Max message size in bytes (default: 4 MiB)

Streaming Subscriptions

Subscribe to Slots

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

const client = new Client("http://localhost:10000", undefined, undefined);
await client.connect();

const stream = await client.subscribe();

// Handle stream events
stream.on("data", (data) => {
  if (data.slot) {
    console.log("Slot update:", data.slot.slot);
  }
});

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

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

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

// Create subscription request
const request: SubscribeRequest = {
  slots: {
    client: {
      filterByCommitment: true,
    },
  },
  commitment: CommitmentLevel.PROCESSED,
  accounts: {},
  transactions: {},
  transactionsStatus: {},
  entry: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  ping: undefined,
};

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

Subscribe to Accounts

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

const request: SubscribeRequest = {
  accounts: {
    client: {
      account: [
        "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
      ],
      owner: [
        "11111111111111111111111111111111",
      ],
      filters: [
        {
          datasize: 165,
        },
      ],
      nonemptyTxnSignature: true,
    },
  },
  commitment: CommitmentLevel.CONFIRMED,
  slots: {},
  transactions: {},
  transactionsStatus: {},
  entry: {},
  blocks: {},
  blocksMeta: {},
  accountsDataSlice: [],
  ping: undefined,
};

const stream = await client.subscribe();

stream.on("data", (data) => {
  if (data.account) {
    console.log("Account update:");
    console.log("  Slot:", data.account.slot);
    console.log("  Account:", data.account.account);
  }
});

stream.write(request);

Subscribe to Transactions

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

const stream = await client.subscribe();

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

stream.write(request);

Subscribe to Blocks

const request: SubscribeRequest = {
  blocks: {
    client: {
      accountInclude: [],
      includeTransactions: true,
      includeAccounts: false,
      includeEntries: false,
    },
  },
  commitment: CommitmentLevel.CONFIRMED,
  slots: {},
  accounts: {},
  transactions: {},
  transactionsStatus: {},
  entry: {},
  blocksMeta: {},
  accountsDataSlice: [],
  ping: undefined,
};

const stream = await client.subscribe();

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

stream.write(request);

Transaction Encoding

The client provides utilities for encoding transaction data to different formats:
import { txEncode, SubscribeUpdateTransactionInfo } from "@triton-one/yellowstone-grpc";

stream.on("data", (data) => {
  if (data.transaction) {
    const message: SubscribeUpdateTransactionInfo = data.transaction.transaction;

    // Encode to JSON
    const tx = txEncode.encode(
      message,
      txEncode.encoding.Json,
      255, // max_supported_transaction_version
      true // show_rewards
    );

    console.log("Transaction JSON:", JSON.stringify(tx, null, 2));
  }
});

Available Encodings

// Access encoding types
import { txEncode } from "@triton-one/yellowstone-grpc";

const encodingTypes = txEncode.encoding;
// Available: Json, Base58, Base64, JsonParsed, etc.

Transaction Error Decoding

Decode transaction errors from raw bytes:
import { txErrDecode } from "@triton-one/yellowstone-grpc";

stream.on("data", (data) => {
  if (data.transaction?.transaction?.meta?.err) {
    const errBytes = data.transaction.transaction.meta.err.err;
    const decodedError = txErrDecode.decode(errBytes);
    console.log("Transaction error:", decodedError);
  }
});

Unary RPC Methods

Ping

const count = await client.ping(1);
console.log("Pong count:", count);

Get Version

const version = await client.getVersion();
console.log("Server version:", version);

Get Slot

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

const slot = await client.getSlot(CommitmentLevel.FINALIZED);
console.log("Current slot:", slot);

Get Block Height

const blockHeight = await client.getBlockHeight(CommitmentLevel.FINALIZED);
console.log("Block height:", blockHeight);

Get Latest Blockhash

const response = await client.getLatestBlockhash(CommitmentLevel.FINALIZED);
console.log("Blockhash:", response.blockhash);
console.log("Last valid block height:", response.lastValidBlockHeight);

Is Blockhash Valid

const blockhash = "EkSnNWid2cvwEVnVx9aBqawnmiCNiDgp3gUdkDPTKN1N";
const response = await client.isBlockhashValid(
  blockhash,
  CommitmentLevel.FINALIZED
);
console.log("Is valid:", response.valid);

Subscribe Replay Info

const replayInfo = await client.subscribeReplayInfo();
console.log("Replay info:", replayInfo);

Account Filters

Filter by Data Size

const request: SubscribeRequest = {
  accounts: {
    client: {
      account: [],
      owner: [],
      filters: [
        {
          datasize: 165, // Token account size
        },
      ],
    },
  },
  // ... other fields
};

Filter by Memcmp

const request: SubscribeRequest = {
  accounts: {
    client: {
      account: [],
      owner: [],
      filters: [
        {
          memcmp: {
            offset: 32,
            base58: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
          },
        },
      ],
    },
  },
  // ... other fields
};

Filter by Lamports

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

const request: SubscribeRequest = {
  accounts: {
    client: {
      account: [],
      owner: [],
      filters: [
        {
          lamports: {
            gt: "1000000000", // Greater than 1 SOL
          } as SubscribeRequestFilterAccountsFilterLamports,
        },
      ],
    },
  },
  // ... other fields
};

Token Account State Filter

const request: SubscribeRequest = {
  accounts: {
    client: {
      account: [],
      owner: [],
      filters: [
        {
          tokenAccountState: true,
        },
      ],
    },
  },
  // ... other fields
};

Complete Example

Here’s a complete example that subscribes to multiple data types:
import Client, {
  CommitmentLevel,
  SubscribeRequest,
} from "@triton-one/yellowstone-grpc";

async function main() {
  const client = new Client(
    "http://localhost:10000",
    undefined,
    {
      grpcMaxDecodingMessageSize: 64 * 1024 * 1024,
    }
  );

  await client.connect();
  console.log("Connected to gRPC server");

  const stream = await client.subscribe();

  // Handle stream lifecycle
  const streamClosed = new Promise<void>((resolve, reject) => {
    stream.on("error", (error) => {
      console.error("Stream error:", error);
      reject(error);
      stream.end();
    });

    stream.on("end", () => {
      console.log("Stream ended");
      resolve();
    });

    stream.on("close", () => {
      console.log("Stream closed");
      resolve();
    });
  });

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

    if (data.account) {
      console.log(`Account update at slot ${data.account.slot}`);
    }

    if (data.transaction) {
      console.log(`Transaction at slot ${data.transaction.slot}`);
    }
  });

  // Subscribe to slots, accounts, and transactions
  const request: SubscribeRequest = {
    slots: {
      client: {
        filterByCommitment: true,
      },
    },
    accounts: {
      client: {
        account: [],
        owner: ["11111111111111111111111111111111"],
        filters: [],
      },
    },
    transactions: {
      client: {
        vote: false,
        failed: false,
        accountInclude: ["11111111111111111111111111111111"],
      },
    },
    commitment: CommitmentLevel.CONFIRMED,
    transactionsStatus: {},
    entry: {},
    blocks: {},
    blocksMeta: {},
    accountsDataSlice: [],
    ping: undefined,
  };

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

  console.log("Subscription active");

  // Wait for stream to close
  await streamClosed;
}

main().catch(console.error);

Commitment Levels

Available commitment levels:
import { CommitmentLevel } from "@triton-one/yellowstone-grpc";

CommitmentLevel.PROCESSED  // Latest block, may be rolled back
CommitmentLevel.CONFIRMED  // Block confirmed by cluster
CommitmentLevel.FINALIZED  // Block finalized by cluster

Error Handling

try {
  await client.connect();
  const version = await client.getVersion();
  console.log("Version:", version);
} catch (error) {
  if (error.code) {
    console.error(`gRPC error [${error.code}]: ${error.message}`);
  } else {
    console.error("Connection error:", error);
  }
}

TypeScript Types

The package includes full TypeScript definitions for all request and response types:
import type {
  SubscribeRequest,
  SubscribeUpdate,
  SubscribeUpdateAccount,
  SubscribeUpdateAccountInfo,
  SubscribeUpdateSlot,
  SubscribeUpdateTransaction,
  SubscribeUpdateTransactionInfo,
  SubscribeRequestFilterAccounts,
  SubscribeRequestFilterTransactions,
  SubscribeRequestFilterSlots,
  CommitmentLevel,
} from "@triton-one/yellowstone-grpc";

Next Steps

Subscribe Filters

Learn more about subscription filters

Plugin Setup

Set up your own Yellowstone gRPC plugin

Build docs developers (and LLMs) love