Skip to main content

Overview

Account subscriptions deliver real-time updates whenever an account’s lamport balance, data, or owner changes. You can monitor specific addresses, all accounts owned by a program, or apply byte-level data filters.

Filter Parameters

ParameterTypeDescription
accountstring[]Specific account public keys to monitor. Matches any in the list (logical OR).
ownerstring[]Monitor all accounts owned by these program IDs (logical OR).
filtersobject[]Additional data filters — dataSize and/or memcmp (logical AND).
nonemptyTxnSignaturebooleanOnly emit updates that are part of a transaction.

dataSize Filter

Only receive updates for accounts whose data length matches exactly:
filters: [{ dataSize: 165 }]

memcmp Filter

Match accounts by a specific byte sequence at a given offset (useful for discriminators):
filters: [
  {
    memcmp: {
      offset: 0,
      bytes: "base58EncodedBytes",
    },
  },
]
When combining multiple filter types, they operate as logical AND. Within account or owner arrays, values operate as logical OR.

Example: Monitor a Specific Wallet

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 PING_INTERVAL_MS = 30_000;

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.account) {
      const { account, slot } = data.account;
      console.log(`Account update at slot ${slot}:`);
      console.log(`  Pubkey:  ${account.pubkey}`);
      console.log(`  Lamports: ${account.lamports}`);
      console.log(`  Owner:   ${account.owner}`);
      console.log(`  Data length: ${account.data.length} bytes`);
    } else if (data.pong) {
      console.log("Pong received");
    }
  });

  const request: SubscribeRequest = {
    accounts: {
      walletMonitor: {
        account: ["YourWalletPublicKeyHere"],
        owner: [],
        filters: [],
      },
    },
    commitment: CommitmentLevel.CONFIRMED,
    accountsDataSlice: [],
    transactions: {},
    transactionsStatus: {},
    slots: {},
    blocks: {},
    blocksMeta: {},
    entry: {},
    ping: { id: 1 },
  };

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

  // Ping to keep alive
  setInterval(() => {
    stream.write({ ping: { id: 1 }, accounts: {}, accountsDataSlice: [], transactions: {}, transactionsStatus: {}, slots: {}, blocks: {}, blocksMeta: {}, entry: {} }, () => {});
  }, PING_INTERVAL_MS);

  await streamClosed;
}

main();

Example: Monitor All Token Accounts by Owner Program

const request: SubscribeRequest = {
  accounts: {
    tokenAccounts: {
      account: [],
      owner: [
        "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // SPL Token program
      ],
      filters: [
        { dataSize: 165 }, // Standard token account size
      ],
    },
  },
  commitment: CommitmentLevel.CONFIRMED,
  accountsDataSlice: [],
  transactions: {},
  transactionsStatus: {},
  slots: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
};

Optimizing with accountsDataSlice

If you only need a portion of the account data (e.g. the first 64 bytes for a discriminator), use accountsDataSlice to reduce bandwidth:
const request: SubscribeRequest = {
  accounts: {
    myFilter: {
      account: ["AccountPubkeyHere"],
      owner: [],
      filters: [],
    },
  },
  accountsDataSlice: [
    { offset: 0, length: 64 }, // Only receive the first 64 bytes
  ],
  commitment: CommitmentLevel.CONFIRMED,
  transactions: {},
  transactionsStatus: {},
  slots: {},
  blocks: {},
  blocksMeta: {},
  entry: {},
};

Common Use Cases

Use CaseApproach
Track wallet balanceFilter by account with specific pubkeys
Monitor all token mintsFilter by owner: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"] + dataSize: 82
Watch a specific program’s stateFilter by owner: ["YourProgramId"]
Detect new AMM pool creationFilter by owner + dataSize matching pool account size