Skip to main content

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?

  • Entry Basics
  • Entry Structure
  • Use Cases
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

  • Performance Analysis
  • Validator Research
  • Network Debugging
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.