概述

Slot 和 block 监控提供了对 Solana 网络共识、区块生成时间和网络健康状况的洞察。实时跟踪 slot 进展、区块最终化和网络性能指标。
先决条件: 本指南假设您已完成 Yellowstone gRPC 快速入门 并已设置好工作流。

监控类型

跟踪网络共识进展监控不同承诺级别的 slot 进展:
const subscribeRequest: SubscribeRequest = {
  slots: {
    slotSubscribe: {
      filterByCommitment: false // Receive all commitment levels
    }
  },
  commitment: CommitmentLevel.CONFIRMED
};
Slot 数据包括:
  • Slot 编号
  • 父 slot
  • 承诺状态(已处理、已确认、已最终化)
  • 领导者信息
最佳用途: 网络健康监控、slot 时间分析、共识跟踪

实用示例

示例 1:网络健康监控

跟踪 slot 进展并识别网络问题:
import { StreamManager } from './stream-manager'; // From quickstart guide

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

  const subscribeRequest: SubscribeRequest = {
    slots: {
      slotSubscribe: {
        filterByCommitment: false // Track all commitment levels
      }
    },
    commitment: CommitmentLevel.PROCESSED
  };

  await streamManager.connect(subscribeRequest);
}

let lastSlot = 0;
let lastTimestamp = Date.now();
const slotTimes: number[] = [];

function handleNetworkHealth(data: any): void {
  if (data.slot) {
    const slot = data.slot;
    const currentTime = Date.now();
    
    console.log(`\n📊 Slot Update:`);
    console.log(`  Slot: ${slot.slot}`);
    console.log(`  Parent: ${slot.parentSlot}`);
    console.log(`  Status: ${slot.status}`);
    
    // Calculate slot timing
    if (lastSlot > 0) {
      const slotDiff = slot.slot - lastSlot;
      const timeDiff = currentTime - lastTimestamp;
      
      if (slotDiff === 1) {
        // Normal slot progression
        const slotTime = timeDiff;
        slotTimes.push(slotTime);
        
        // Keep last 100 slot times for analysis
        if (slotTimes.length > 100) {
          slotTimes.shift();
        }
        
        const avgSlotTime = slotTimes.reduce((a, b) => a + b, 0) / slotTimes.length;
        
        console.log(`  Slot Time: ${slotTime}ms`);
        console.log(`  Avg Slot Time: ${avgSlotTime.toFixed(1)}ms`);
        
        // Alert on slow slots
        if (slotTime > 800) {
          console.log(`  ⚠️  SLOW SLOT: ${slotTime}ms (normal ~400ms)`);
        }
      } else if (slotDiff > 1) {
        console.log(`  ⚠️  SKIPPED ${slotDiff - 1} SLOTS`);
      }
    }
    
    lastSlot = slot.slot;
    lastTimestamp = currentTime;
  }
}

示例 2:区块生成监控

跟踪区块生成和交易量:
async function monitorBlockProduction() {
  const streamManager = new StreamManager(
    "your-grpc-endpoint",
    "your-api-key",
    handleBlockProduction
  );

  const subscribeRequest: SubscribeRequest = {
    blocksMeta: {
      blockMetaSubscribe: {}
    },
    commitment: CommitmentLevel.CONFIRMED
  };

  await streamManager.connect(subscribeRequest);
}

function handleBlockProduction(data: any): void {
  if (data.blockMeta) {
    const blockMeta = data.blockMeta;
    
    console.log(`\n🧱 Block Produced:`);
    console.log(`  Slot: ${blockMeta.slot}`);
    console.log(`  Block Height: ${blockMeta.blockHeight}`);
    console.log(`  Block Hash: ${blockMeta.blockhash}`);
    console.log(`  Parent Hash: ${blockMeta.parentBlockhash}`);
    console.log(`  Transactions: ${blockMeta.transactionCount}`);
    console.log(`  Block Time: ${new Date(blockMeta.blockTime * 1000).toISOString()}`);
    
    if (blockMeta.rewards?.length > 0) {
      console.log(`  Rewards:`);
      blockMeta.rewards.forEach((reward: any) => {
        console.log(`    ${reward.pubkey}: ${reward.lamports} lamports (${reward.rewardType})`);
      });
    }
    
    // Alert on high transaction count
    if (blockMeta.transactionCount > 3000) {
      console.log(`  🔥 HIGH ACTIVITY: ${blockMeta.transactionCount} transactions`);
    }
  }
}

示例 3:过滤区块监控

监控包含特定程序活动的区块:
async function monitorDEXBlocks() {
  const streamManager = new StreamManager(
    "your-grpc-endpoint",
    "your-api-key",
    handleDEXBlock
  );

  const subscribeRequest: SubscribeRequest = {
    blocks: {
      blockSubscribe: {
        accountInclude: [
          "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM", // Raydium V4
          "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"   // Jupiter
        ],
        includeTransactions: true,
        includeAccounts: false,
        includeEntries: false
      }
    },
    commitment: CommitmentLevel.CONFIRMED
  };

  await streamManager.connect(subscribeRequest);
}

function handleDEXBlock(data: any): void {
  if (data.block) {
    const block = data.block;
    
    console.log(`\n🔄 DEX Activity Block:`);
    console.log(`  Slot: ${block.slot}`);
    console.log(`  Block Hash: ${block.blockhash}`);
    console.log(`  Total Transactions: ${block.transactions?.length || 0}`);
    
    if (block.transactions) {
      let dexTxCount = 0;
      let totalFees = 0;
      
      block.transactions.forEach((tx: any) => {
        if (tx.meta && !tx.meta.err) {
          dexTxCount++;
          totalFees += tx.meta.fee || 0;
        }
      });
      
      console.log(`  DEX Transactions: ${dexTxCount}`);
      console.log(`  Total Fees: ${(totalFees / 1e9).toFixed(4)} SOL`);
      console.log(`  Avg Fee: ${(totalFees / dexTxCount / 1e9).toFixed(6)} SOL`);
    }
  }
}

数据结构

理解插槽和区块数据格式:

性能考虑

插槽监控

轻量且高效
  • 非常低的带宽使用
  • 实时网络健康洞察
  • 最小的处理开销
  • 适合监控仪表板

区块元数据

平衡的方法
  • 中等带宽使用
  • 区块级洞察而非完整数据
  • 交易计数和时间
  • 适合分析

完整区块

高容量数据
  • 高带宽要求
  • 完整的交易数据
  • 需要强大的处理能力
  • 使用过滤器减少数据量

过滤区块

优化的流媒体
  • 使用 accountInclude 过滤器
  • 禁用不必要的数据(条目,账户)
  • 专注于特定程序
  • 在细节和性能之间取得平衡

用例

跟踪网络健康和性能
  • 插槽时间分析
  • 网络拥塞检测
  • 共识监控
  • 验证者性能
// Monitor slot timing deviations
const targetSlotTime = 400; // ms
const tolerance = 200; // ms

if (Math.abs(slotTime - targetSlotTime) > tolerance) {
  console.log(`Network performance issue detected`);
}

错误处理

常见问题和解决方案:

最佳实践

生产指南:
  • 从元数据开始 - 在完整区块之前使用区块元数据
  • 应用过滤器 - 使用 accountInclude 减少无关数据
  • 监控时间 - 跟踪插槽进程以了解网络健康状况
  • 处理间隙 - 实施缺失插槽/区块的逻辑
  • 异步处理 - 不要用繁重的计算阻塞流处理
  • 使用适当的承诺 - 根据需要匹配承诺级别

下一步