Skip to main content

Overview

Slot and block monitoring provides insights into Solana’s network consensus, block production timing, and network health. Track slot progression, block finalization, and network performance metrics in real-time.
Prerequisites: This guide assumes you’ve completed the Yellowstone gRPC Quickstart and have a working stream setup.

Monitoring Types

  • Slot Updates
  • Block Data
  • Block Metadata
Track network consensus progressionMonitor slot advancement across different commitment levels:
const subscribeRequest: SubscribeRequest = {
  slots: {
    slotSubscribe: {
      filterByCommitment: false // Receive all commitment levels
    }
  },
  commitment: CommitmentLevel.CONFIRMED
};
Slot data includes:
  • Slot number
  • Parent slot
  • Commitment status (processed, confirmed, finalized)
  • Leader information
Best for: Network health monitoring, slot timing analysis, consensus tracking

Practical Examples

Example 1: Network Health Monitor

Track slot progression and identify network issues:
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;
  }
}

Example 2: Block Production Monitor

Track block production and transaction volume:
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`);
    }
  }
}

Example 3: Filtered Block Monitor

Monitor blocks containing specific program activity:
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`);
    }
  }
}

Data Structures

Understanding slot and block data formats:
{
  slot: number;           // Current slot number
  parentSlot: number;     // Parent slot number  
  status: string;         // "processed", "confirmed", "finalized"
}
Slot progression: Each slot represents ~400ms of network timeCommitment levels:
  • Processed: Initial slot processing
  • Confirmed: Supermajority confirmation
  • Finalized: Irreversible finalization
{
  slot: number;
  blockHeight: number;
  blockhash: string;
  parentBlockhash: string;
  blockTime: number;      // Unix timestamp
  transactionCount: number;
  rewards: Array<{
    pubkey: string;
    lamports: number;
    rewardType: string;   // "fee", "rent", "voting", "staking"
  }>;
}
Block time: Estimated time when the block was producedRewards: Validator rewards for block production
{
  slot: number;
  parentSlot: number;
  blockhash: string;
  previousBlockhash: string;
  transactions: Transaction[];  // Full transaction data
  accounts: AccountUpdate[];    // Account state changes
  entries: Entry[];            // Block entries (if included)
}
Size warning: Full blocks can be several MB with all transactions and accounts

Performance Considerations

Slot Monitoring

Lightweight and efficient
  • Very low bandwidth usage
  • Real-time network health insights
  • Minimal processing overhead
  • Good for monitoring dashboards

Block Metadata

Balanced approach
  • Moderate bandwidth usage
  • Block-level insights without full data
  • Transaction counts and timing
  • Suitable for analytics

Full Blocks

High volume data
  • High bandwidth requirements
  • Complete transaction data
  • Requires robust processing
  • Use filters to reduce volume

Filtered Blocks

Optimized streaming
  • Use accountInclude filters
  • Disable unnecessary data (entries, accounts)
  • Focus on specific programs
  • Balance detail with performance

Use Cases

  • Network Monitoring
  • Analytics & Metrics
  • Application Synchronization
Track network health and performance
  • Slot timing analysis
  • Network congestion detection
  • Consensus monitoring
  • Validator performance
// Monitor slot timing deviations
const targetSlotTime = 400; // ms
const tolerance = 200; // ms

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

Error Handling

Common issues and solutions:
Issue: Gaps in slot progressionCauses:
  • Network connectivity issues
  • Validator downtime
  • Client processing delays
Solutions:
  • Track slot gaps and alert
  • Implement catch-up logic
  • Monitor connection health
Issue: Too much block dataSolutions:
  • Use block metadata instead of full blocks
  • Apply account filters to reduce data
  • Disable unnecessary inclusions (entries, accounts)
  • Process data asynchronously
Issue: Inconsistent slot timingAnalysis:
  • Calculate moving averages
  • Track timing deviations
  • Monitor network health metrics
  • Correlate with validator performance

Best Practices

Production Guidelines:
  • Start with metadata - Use block metadata before full blocks
  • Apply filters - Use accountInclude to reduce irrelevant data
  • Monitor timing - Track slot progression for network health
  • Handle gaps - Implement logic for missing slots/blocks
  • Process async - Don’t block stream processing with heavy computations
  • Use appropriate commitment - Match commitment level to your needs

Next Steps