Solana Geyser gRPC - Filters

Solana Stream SDK
The Solana Stream SDK is provided as open-source software. For more details, please visit the GitHub repository below.

Overview of gRPC Filters

Solana Geyser gRPC uses filters to efficiently fetch only the data you are interested in, such as specific accounts, programs, transactions, slots, and blocks.
Below, we provide TypeScript examples using the Solana Stream SDK, clearly explaining the specific roles of each filter. The structure and meaning of the filters are identical when using Rust.

Roles and Examples of Each Filter

Subscribe to an account

Subscribe to real-time updates for a specific account. The following example subscribes to the SOL-USDC OpenBook account at the Confirmed commitment level:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: { slots: {} }, accounts: { 'wsol/usdc': { account: ['8BnEgHoWFysVcuFFX7QztDmzuH8r5ZFvyP3sYwn1XTh6'], }, }, transactions: {}, blocks: {}, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.CONFIRMED, }
  • "wsol/usdc" is a client-defined label.
  • Multiple filters for accounts, programs, blocks, and slots can be combined in a single JSON request.

Subscribe to an account with account_data_slice

This example demonstrates retrieving only a specific portion of account data. Instead of fetching the entire data (165 bytes) of a USDC token account, it retrieves 40 bytes starting from offset 32. This range includes information such as the owner and lamports balance.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: {}, accounts: { usdc: { owner: ['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'], filters: [ { tokenAccountState: true, }, { memcmp: { offset: 0, data: { base58: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', }, }, }, ], }, }, transactions: {}, blocks: {}, blocksMeta: {}, entry: {}, commitment: CommitmentLevel.CONFIRMED, accountsDataSlice: [{ offset: 32, length: 40 }], }

Subscribe to a program

This example demonstrates subscribing to account updates associated with a specific program.
Below, we subscribe to account updates for accounts owned by the Solend program at the Processed commitment level.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: { slots: {}, }, accounts: { solend: { owner: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'], }, }, transactions: {}, blocks: {}, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }
  • "solend" is a custom label that can be freely set by the client.
  • To subscribe to multiple programs, please refer to the next section titled "Subscribe to multiple programs."

Subscribe to multiple programs

This example demonstrates how to subscribe to account updates associated with multiple programs at once.
The example below subscribes to updates for accounts owned by both Solend and Serum programs.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: { slots: {}, }, accounts: { programs: { owner: [ 'So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo', '9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin', ], }, }, transactions: {}, blocks: {}, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }
If you prefer assigning individual labels to each program, use the following approach:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: { slots: {}, }, accounts: { solend: { owner: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'], }, serum: { owner: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'], }, }, transactions: {}, blocks: {}, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }

Subscribe to all finalized non-vote and non-failed transactions

This example demonstrates subscribing to all transactions at the Finalized commitment level, excluding vote transactions and failed transactions.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: { slots: {}, }, accounts: {}, transactions: { alltxs: { vote: false, failed: false, }, }, blocks: {}, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.FINALIZED, }
  • vote: false excludes vote transactions.
  • failed: false excludes failed transactions.
  • If fields are left empty, all transactions are retrieved.
  • When multiple fields are specified, they operate with an AND condition.

Subscribe to non-vote transactions mentioning an account

This example demonstrates subscribing to transactions involving a specific account but excluding vote transactions.
The example below subscribes to non-vote transactions mentioning accounts associated with the Serum program.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: { slots: {}, }, accounts: {}, transactions: { serum: { vote: false, accountInclude: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'], }, }, blocks: {}, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }

Subscribe to transactions excluding accounts

This example demonstrates subscribing to transactions excluding those involving specific accounts.
The example below retrieves transactions excluding any accounts owned by the Serum and Tokenkeg programs.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: { slots: {}, }, accounts: {}, transactions: { serum: { accountExclude: [ '9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin', 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', ], }, }, blocks: {}, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }

Subscribe to transactions mentioning accounts & excluding certain accounts

This example demonstrates subscribing to transactions involving certain accounts, while explicitly excluding other specified accounts.
The example below subscribes to transactions mentioning Serum's account but excludes a specified account:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: { slots: {}, }, accounts: {}, transactions: { serum: { accountInclude: ['9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin'], accountExclude: ['9wFFyRfZBsuAha4YcuxcXLKwMxJR43S7fPfQLusDBzvT'], }, }, blocks: {}, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }

Subscribe to a transaction signature

This example demonstrates subscribing to real-time updates for a specific transaction signature, until it reaches the Confirmed or Finalized state.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: {}, accounts: {}, transactions: { sign: { signature: '5rp2hL9b6kexex11Mugfs3vfU9GhieKruj4CkFFSnu52WLxiGn4VcLLwsB62XURhMmT1j4CZiXT6FFtYbXsLq2Zs', }, }, blocks: {}, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }

Subscribe to slots

This example demonstrates subscribing to notifications of incoming slots. No additional details are required beyond assigning a custom tag name:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: { incoming_slots: {}, }, accounts: {}, transactions: {}, blocks: {}, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }

Subscribe to blocks

Subscribe to real-time updates of all generated blocks. By default, all transactions within a block will be retrieved:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: {}, accounts: {}, transactions: {}, blocks: { blocks: {}, }, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }

To exclude transactions and only retrieve updated account information:

typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: {}, accounts: {}, transactions: {}, blocks: { blocks: { includeTransactions: false, includeAccounts: true, }, }, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }

To only retrieve transactions/accounts involving specific accounts:

typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: {}, accounts: {}, transactions: {}, blocks: { blocks: { accountInclude: ['So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo'], }, }, blocksMeta: {}, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }

Subscribe to block metadata

Subscribe only to block metadata notifications when blocks are processed. Detailed transaction data is not included.
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' const request = { slots: {}, accounts: {}, transactions: {}, blocks: {}, blocksMeta: { blockmetadata: {}, }, accountsDataSlice: [], commitment: CommitmentLevel.PROCESSED, }

Managing commitment levels

The Solana Geyser gRPC stream defaults to the Processed commitment level.
You can specify higher commitment levels such as Confirmed or Finalized. In these cases, Geyser buffers the data and sends notifications once the specified commitment level is reached.
For maximum performance, it is recommended to handle commitment-level management on the client side.
Here's how to specify commitment levels:
typescript
import { CommitmentLevel } from '@validators-dao/solana-stream-sdk' enum CommitmentLevel { PROCESSED = 0, CONFIRMED = 1, FINALIZED = 2, }
  • PROCESSED: Immediate data after processing. Fast retrieval, but not yet confirmed.
  • CONFIRMED: Data confirmed by the cluster, providing increased certainty.
  • FINALIZED: Fully finalized data with no risk of reorganization.

Benefits of working at Processed

The main advantage of the Processed commitment level is immediate transaction retrieval, enabling rapid client-side processing. Clients can subsequently detect transitions to Confirmed or Finalized, offering quick responsiveness.

How to manage Confirmed and Finalized

When using Confirmed or Finalized levels, events (transactions or account updates) should be buffered per slot.
Buffer events slot by slot, subscribe to slot notifications, and release events from the buffer once a specific slot reaches the desired commitment (Confirmed or Finalized).
Events will initially be received before a slot reaches Confirmed or Finalized.

The special thing about Finalized

Due to Solana Geyser specifications, not all slots receive explicit finalized notifications. Therefore, when you receive a finalized notification for a slot, you must treat all ancestor slots as finalized, even if no notifications were received explicitly.
Specifically, upon receiving a finalized notification, retroactively treat all ancestor slots as finalized.