概述

账户监控让您可以实时跟踪 Solana 上的余额变化、数据修改、所有权转移以及账户创建/删除事件。本指南涵盖了不同用例的过滤策略和实现模式。
先决条件: 本指南假设您已完成 Yellowstone gRPC 快速入门 并已设置好工作流。

账户过滤选项

通过公钥监控单个账户当您确切知道要监控哪些账户时使用:
const subscribeRequest: SubscribeRequest = {
  accounts: {
    accountSubscribe: {
      account: [
        "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC mint
        "So11111111111111111111111111111111111111112"   // Wrapped SOL
      ],
      owner: [],
      filters: []
    }
  },
  commitment: CommitmentLevel.CONFIRMED
};
最佳用途: 监控特定代币铸造、已知钱包或关键程序账户

数据切片

通过请求账户数据的特定字节范围来优化带宽:
// Only get the balance portion of token accounts (bytes 64-72)
const subscribeRequest: SubscribeRequest = {
  accounts: {
    accountSubscribe: {
      owner: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
      filters: [{ dataSize: 165 }]
    }
  },
  accountsDataSlice: [
    { offset: 64, length: 8 } // Token balance (u64)
  ],
  commitment: CommitmentLevel.CONFIRMED
};

实用示例

示例 1:监控大额代币持有者

跟踪具有大量余额的 USDC 账户:
import { StreamManager } from './stream-manager'; // From quickstart guide

async function monitorLargeUSDCHolders() {
  const streamManager = new StreamManager(
    "your-grpc-endpoint",
    "your-api-key",
    handleLargeHolderUpdate
  );

  const subscribeRequest: SubscribeRequest = {
    accounts: {
      accountSubscribe: {
        owner: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
        filters: [
          { dataSize: 165 }, // Token account size
          { 
            memcmp: { 
              offset: 0, 
              bytes: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" // USDC mint
            } 
          }
        ]
      }
    },
    accountsDataSlice: [
      { offset: 32, length: 32 }, // Owner
      { offset: 64, length: 8 }   // Balance
    ],
    commitment: CommitmentLevel.CONFIRMED
  };

  await streamManager.connect(subscribeRequest);
}

function handleLargeHolderUpdate(data: any): void {
  if (data.account) {
    const account = data.account.account;
    
    // Parse token account data
    if (account.data && account.data.length >= 8) {
      const balanceBuffer = Buffer.from(account.data.slice(64, 72), 'base64');
      const balance = balanceBuffer.readBigUInt64LE();
      const balanceInUSDC = Number(balance) / 1e6; // USDC has 6 decimals
      
      // Only log accounts with > 100,000 USDC
      if (balanceInUSDC > 100000) {
        console.log(`🐋 Large USDC Holder Update:`);
        console.log(`  Account: ${account.pubkey}`);
        console.log(`  Balance: ${balanceInUSDC.toLocaleString()} USDC`);
        console.log(`  Slot: ${data.account.slot}`);
      }
    }
  }
}

示例 2:跟踪程序账户变化

监控由特定程序拥有的所有账户:
async function monitorProgramAccounts() {
  const PROGRAM_ID = "YourProgramId"; // Replace with actual program ID
  
  const streamManager = new StreamManager(
    "your-grpc-endpoint",
    "your-api-key",
    handleProgramAccountUpdate
  );

  const subscribeRequest: SubscribeRequest = {
    accounts: {
      accountSubscribe: {
        owner: [PROGRAM_ID],
        filters: []
      }
    },
    commitment: CommitmentLevel.CONFIRMED
  };

  await streamManager.connect(subscribeRequest);
}

function handleProgramAccountUpdate(data: any): void {
  if (data.account) {
    const account = data.account.account;
    console.log(`📋 Program Account Update:`);
    console.log(`  Account: ${account.pubkey}`);
    console.log(`  Owner: ${account.owner}`);
    console.log(`  Lamports: ${account.lamports}`);
    console.log(`  Data Length: ${account.data?.length || 0} bytes`);
    console.log(`  Executable: ${account.executable}`);
    console.log(`  Rent Epoch: ${account.rentEpoch}`);
  }
}

示例 3:新账户创建监控

跟踪新账户创建的时间:
async function monitorNewAccounts() {
  const streamManager = new StreamManager(
    "your-grpc-endpoint",
    "your-api-key",
    handleNewAccountCreation
  );

  const subscribeRequest: SubscribeRequest = {
    accounts: {
      accountSubscribe: {
        owner: ["11111111111111111111111111111111"], // System Program
        filters: []
      }
    },
    commitment: CommitmentLevel.CONFIRMED
  };

  await streamManager.connect(subscribeRequest);
}

function handleNewAccountCreation(data: any): void {
  if (data.account && data.account.account.lamports === 0) {
    // New account creation typically starts with 0 lamports
    const account = data.account.account;
    console.log(`🆕 New Account Created:`);
    console.log(`  Account: ${account.pubkey}`);
    console.log(`  Owner: ${account.owner}`);
    console.log(`  Slot: ${data.account.slot}`);
  }
}

过滤逻辑参考

了解过滤器如何组合:

性能注意事项

带宽优化

使用数据切片 仅请求所需字节应用严格过滤器 以减少不必要的更新选择适当的承诺 水平以适应您的用例

规模管理

从特定账户开始 然后使用所有者过滤器监控订阅量 并根据需要调整过滤器实现背压处理 以应对高流量流

错误处理

常见账户监控错误及解决方案:

下一步