Overview

Entry monitoring provides access to the fundamental execution units of the Solana blockchain. Entries contain batches of transactions and their execution results, offering the lowest-level view of blockchain activity.
Prerequisites: This guide assumes you’ve completed the Yellowstone gRPC Quickstart and have a working stream setup.
Advanced topic: Entry monitoring is primarily useful for deep blockchain analysis, debugging, and specialized use cases. Most applications should use transaction or account monitoring instead.

What are Entries?

Fundamental blockchain unitsEntries are the basic building blocks that validators use to construct blocks:
  • Transaction batches: Groups of transactions executed together
  • Execution order: Deterministic transaction ordering within entries
  • Hash chains: Cryptographic linking between entries
  • Timing information: When entries were created and processed
const subscribeRequest: SubscribeRequest = {
  entry: {
    entrySubscribe: {} // Subscribe to all entries
  },
  commitment: CommitmentLevel.CONFIRMED
};

Implementation Example

Basic Entry Monitoring

import { StreamManager } from './stream-manager'; // From quickstart guide

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

  const subscribeRequest: SubscribeRequest = {
    entry: {
      entrySubscribe: {} // Subscribe to all entries
    },
    commitment: CommitmentLevel.CONFIRMED
  };

  console.log('Starting entry monitoring...');
  await streamManager.connect(subscribeRequest);
}

function handleEntryUpdate(data: any): void {
  if (data.entry) {
    const entry = data.entry;
    
    console.log('\n📋 Entry Details:');
    console.log(`  Slot: ${entry.slot}`);
    console.log(`  Index: ${entry.index || 'N/A'}`);
    console.log(`  Hash: ${entry.hash || 'N/A'}`);
    console.log(`  Num Hashes: ${entry.numHashes || 'N/A'}`);
    
    if (entry.transactions?.length > 0) {
      console.log(`\n  📦 Entry Transactions (${entry.transactions.length}):`);
      
      entry.transactions.forEach((tx: any, index: number) => {
        console.log(`    ${index + 1}. ${tx.signature || 'No signature'}`);
        console.log(`       Vote: ${tx.isVote ? 'Yes' : 'No'}`);
        
        // Show transaction status if available
        if (tx.meta) {
          const status = tx.meta.err ? 'Failed' : 'Success';
          console.log(`       Status: ${status}`);
          if (tx.meta.fee) {
            console.log(`       Fee: ${tx.meta.fee} lamports`);
          }
        }
      });
    } else {
      console.log(`  📦 No transactions in this entry`);
    }
    
    // Check if this is a tick entry (no transactions)
    if (entry.tick !== undefined) {
      console.log(`  ⏱️  Tick Entry: ${entry.tick ? 'Yes' : 'No'}`);
    }
  }
}

// Start monitoring
monitorEntries().catch(console.error);

Entry Analysis Example

Advanced analysis of entry patterns:
let entryStats = {
  totalEntries: 0,
  totalTransactions: 0,
  tickEntries: 0,
  largestEntry: 0,
  slotsProcessed: new Set<number>()
};

function analyzeEntry(data: any): void {
  if (data.entry) {
    const entry = data.entry;
    entryStats.totalEntries++;
    entryStats.slotsProcessed.add(entry.slot);
    
    const txCount = entry.transactions?.length || 0;
    entryStats.totalTransactions += txCount;
    
    if (txCount === 0 || entry.tick) {
      entryStats.tickEntries++;
    }
    
    if (txCount > entryStats.largestEntry) {
      entryStats.largestEntry = txCount;
      console.log(`\n🔥 New largest entry: ${txCount} transactions in slot ${entry.slot}`);
    }
    
    // Log stats every 100 entries
    if (entryStats.totalEntries % 100 === 0) {
      console.log('\n📊 Entry Statistics:');
      console.log(`  Total Entries: ${entryStats.totalEntries}`);
      console.log(`  Total Transactions: ${entryStats.totalTransactions}`);
      console.log(`  Tick Entries: ${entryStats.tickEntries}`);
      console.log(`  Slots Processed: ${entryStats.slotsProcessed.size}`);
      console.log(`  Avg Tx/Entry: ${(entryStats.totalTransactions / entryStats.totalEntries).toFixed(2)}`);
      console.log(`  Largest Entry: ${entryStats.largestEntry} transactions`);
    }
  }
}

Entry Data Structure

Understanding the entry data format:
{
  slot: number;              // Slot number containing this entry
  index: number;             // Entry index within the slot
  hash: string;              // Entry hash (proof-of-history)
  numHashes: number;         // Number of hashes in PoH sequence
  transactions: Array<{      // Transactions in this entry
    signature: string;
    isVote: boolean;
    meta: {
      err: any;            // Error if transaction failed
      fee: number;         // Transaction fee
      // ... other transaction metadata
    };
  }>;
  tick: boolean;             // Whether this is a tick entry
}
Entries vs Transactions:
  • Entries group transactions together
  • Show execution order and batching
  • Include PoH (Proof of History) information
Entries vs Blocks:
  • Blocks contain multiple entries
  • Entries are subunits within blocks
  • Blocks add consensus and finality information
Entries vs Slots:
  • Slots are time units (400ms)
  • Multiple entries can exist per slot
  • Entries show what happened within a slot

Performance Considerations

Volume Characteristics

High-frequency data stream
  • Very high message rate
  • Continuous stream during network activity
  • Each entry contains multiple transactions
  • Requires efficient processing

Processing Efficiency

Optimize for performance
  • Process entries asynchronously
  • Batch entry analysis
  • Focus on specific data fields
  • Use sampling for large-scale analysis

Common Use Cases

Analyze transaction batching efficiency
function analyzeBatching(entry: any): void {
  const txCount = entry.transactions?.length || 0;
  
  if (txCount > 50) {
    console.log(`Large batch: ${txCount} transactions in entry ${entry.index}`);
  }
  
  // Track batching patterns
  const batchSizes = new Map<number, number>();
  const currentCount = batchSizes.get(txCount) || 0;
  batchSizes.set(txCount, currentCount + 1);
}

Filtering and Optimization

Entry monitoring currently doesn’t support specific filters, so all entries are streamed. To manage this:
Optimization strategies:
  • Client-side filtering: Process only entries matching your criteria
  • Sampling: Analyze every Nth entry for statistical analysis
  • Time-based analysis: Focus on specific time periods
  • Slot-based filtering: Only process entries from certain slots
  • Transaction type filtering: Focus on entries with specific transaction types
Example client-side filtering:
function handleFilteredEntries(data: any): void {
  if (data.entry) {
    const entry = data.entry;
    
    // Only process entries with transactions
    if (entry.transactions?.length > 0) {
      // Only process entries with non-vote transactions
      const hasNonVoteTransactions = entry.transactions.some((tx: any) => !tx.isVote);
      
      if (hasNonVoteTransactions) {
        processImportantEntry(entry);
      }
    }
  }
}

Best Practices

Appropriate use cases:
  • Deep blockchain analysis and research
  • Validator performance studies
  • Network debugging and forensics
  • Academic blockchain research
  • Understanding PoH mechanics
When NOT to use:
  • Standard application development
  • User-facing features
  • Business logic implementation
  • Real-time trading applications
Handle high-volume data:
  • Implement efficient data processing
  • Use asynchronous processing patterns
  • Consider data sampling for analysis
  • Monitor memory usage and cleanup
  • Implement backpressure handling
Effective entry analysis:
  • Focus on specific metrics
  • Use statistical sampling
  • Implement rolling averages
  • Track patterns over time
  • Correlate with other blockchain data

Troubleshooting

Issue: Overwhelming entry stream volumeSolutions:
  • Implement client-side filtering
  • Use data sampling techniques
  • Process entries asynchronously
  • Monitor system resources
  • Consider alternative monitoring approaches
Issue: Need additional transaction contextSolutions:
  • Combine with transaction monitoring
  • Cross-reference with account updates
  • Use block monitoring for broader context
  • Maintain local state tracking

Next Steps

Remember: Entry monitoring is a specialized tool for advanced blockchain analysis. For most applications, transaction, account, or block monitoring will be more appropriate and efficient.