> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Slot & Block Monitoring with LaserStream

> Monitor Solana network consensus, block production, and network state changes with LaserStream — slot timing, block metadata, and filtered full blocks.

Slot and block monitoring gives you a window into Solana's network consensus, block production timing, and overall health. With LaserStream you can track slot progression, block finalization, and network performance metrics in real-time using the [`helius-laserstream`](https://www.helius.dev/docs/laserstream/clients) SDK.

> [!NOTE]
>
> **Prerequisites:** This guide assumes you've completed the [LaserStream gRPC Quickstart](https://www.helius.dev/docs/laserstream/grpc.md) and have an API key.

***

## Monitoring Types

> [tab] Slot Updates
>
> **Track network consensus progression**
>
> Monitor slot advancement across commitment levels:
>
> ```typescript theme={"system"}
> import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream';
>
> const subscriptionRequest: SubscribeRequest = {
>   slots: {
>     slotSubscribe: {
>       filterByCommitment: false // Receive all commitment levels
>     }
>   },
>   commitment: CommitmentLevel.CONFIRMED,
>   accounts: {}, transactions: {}, transactionsStatus: {},
>   blocks: {}, blocksMeta: {}, entry: {}, accountsDataSlice: [],
> };
> ```
>
> **Slot data includes:** slot number, parent slot, commitment status (`processed` / `confirmed` / `finalized`), and leader information.
>
> > [!NOTE]
> >
> > **Best for:** Network health monitoring, slot timing analysis, consensus tracking.

> [tab] Block Data
>
> **Monitor complete block information**
>
> Stream full blocks with transactions and account updates:
>
> ```typescript theme={"system"}
> const subscriptionRequest: SubscribeRequest = {
>   blocks: {
>     blockSubscribe: {
>       accountInclude: [], // All accounts
>       includeTransactions: true,
>       includeAccounts: true,
>       includeEntries: false
>     }
>   },
>   commitment: CommitmentLevel.CONFIRMED,
>   accounts: {}, transactions: {}, transactionsStatus: {},
>   slots: {}, blocksMeta: {}, entry: {}, accountsDataSlice: [],
> };
> ```
>
> **Block data includes:** block metadata, transactions, account updates, block timing.
>
> > [!WARNING]
> >
> > **High volume:** Full block streams generate significant data. Use `accountInclude` filters to reduce volume.

> [tab] Block Metadata
>
> **Lightweight block information**
>
> Get block metadata without transaction details:
>
> ```typescript theme={"system"}
> const subscriptionRequest: SubscribeRequest = {
>   blocksMeta: {
>     blockMetaSubscribe: {}
>   },
>   commitment: CommitmentLevel.CONFIRMED,
>   accounts: {}, transactions: {}, transactionsStatus: {},
>   slots: {}, blocks: {}, entry: {}, accountsDataSlice: [],
> };
> ```
>
> **Metadata includes:** block hash, parent hash, slot, height, transaction count, rewards.
>
> > [!TIP]
> >
> > **Efficient:** Lower-bandwidth alternative to full block streaming.

***

## Practical Examples

### Example 1: Network Health Monitor

Track slot progression and identify network issues:

```typescript [expandable] theme={"system"}
import { subscribe, CommitmentLevel, LaserstreamConfig, SubscribeRequest } from 'helius-laserstream';

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

// CommitmentLevel only ships the forward (name → number) mapping, so we keep
// a small reverse lookup for the numeric status the SDK returns on slot updates.
const STATUS_NAMES = ['PROCESSED', 'CONFIRMED', 'FINALIZED'] as const;

async function monitorNetworkHealth() {
  const subscriptionRequest: SubscribeRequest = {
    slots: {
      slotSubscribe: {
        filterByCommitment: true // Track processed commitment levels
      }
    },
    commitment: CommitmentLevel.PROCESSED,
    accounts: {}, transactions: {}, transactionsStatus: {},
    blocks: {}, blocksMeta: {}, entry: {}, accountsDataSlice: [],
  };

  const config: LaserstreamConfig = {
    apiKey: 'YOUR_API_KEY',
    endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com',
  };

  await subscribe(config, subscriptionRequest, async (data) => {
    if (!data.slot) return;
    const slot = data.slot;
    // The SDK returns u64 fields as strings to preserve precision.
    const currentSlot = Number(slot.slot);
    const currentTime = Date.now();

    console.log(`\n📊 Slot Update:`);
    console.log(`  Slot: ${currentSlot}`);
    console.log(`  Parent: ${slot.parent}`);
    // slot.status is a numeric enum (0=processed, 1=confirmed, 2=finalized).
    console.log(`  Status: ${STATUS_NAMES[slot.status] ?? slot.status}`);

    if (lastSlot > 0) {
      const slotDiff = currentSlot - lastSlot;
      const timeDiff = currentTime - lastTimestamp;

      if (slotDiff === 1) {
        slotTimes.push(timeDiff);
        if (slotTimes.length > 100) slotTimes.shift();

        const avg = slotTimes.reduce((a, b) => a + b, 0) / slotTimes.length;
        console.log(`  Slot Time: ${timeDiff}ms`);
        console.log(`  Avg Slot Time: ${avg.toFixed(1)}ms`);

        if (timeDiff > 800) {
          console.log(`  ⚠️  SLOW SLOT: ${timeDiff}ms (normal ~400ms)`);
        }
      } else if (slotDiff > 1) {
        console.log(`  ⚠️  SKIPPED ${slotDiff - 1} SLOTS`);
      }
    }

    lastSlot = currentSlot;
    lastTimestamp = currentTime;
  }, async (error) => {
    console.error('Stream error:', error);
  });
}

monitorNetworkHealth().catch(console.error);
```

### Example 2: Block Production Monitor

Track block production and transaction volume:

```typescript [expandable] theme={"system"}
async function monitorBlockProduction() {
  const subscriptionRequest: SubscribeRequest = {
    blocksMeta: {
      blockMetaSubscribe: {}
    },
    commitment: CommitmentLevel.CONFIRMED,
    accounts: {}, transactions: {}, transactionsStatus: {},
    slots: {}, blocks: {}, entry: {}, accountsDataSlice: [],
  };

  const config: LaserstreamConfig = {
    apiKey: 'YOUR_API_KEY',
    endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com',
  };

  await subscribe(config, subscriptionRequest, async (data) => {
    if (!data.blockMeta) return;
    const blockMeta = data.blockMeta;

    console.log(`\n🧱 Block Produced:`);
    console.log(`  Slot: ${blockMeta.slot}`);
    // blockHeight is a wrapper object: { blockHeight: '397657352' }
    console.log(`  Block Height: ${blockMeta.blockHeight?.blockHeight}`);
    console.log(`  Block Hash: ${blockMeta.blockhash}`);
    console.log(`  Parent Slot: ${blockMeta.parentSlot}`);
    console.log(`  Parent Hash: ${blockMeta.parentBlockhash}`);
    console.log(`  Transactions: ${blockMeta.executedTransactionCount}`);
    console.log(`  Entries: ${blockMeta.entriesCount}`);
    if (blockMeta.blockTime?.timestamp) {
      // blockTime.timestamp is a u64 as a string (Unix seconds).
      console.log(`  Block Time: ${new Date(Number(blockMeta.blockTime.timestamp) * 1000).toISOString()}`);
    }

    // rewards is a wrapper object: { rewards: [...], numPartitions: number | null }
    if (blockMeta.rewards?.rewards?.length > 0) {
      console.log(`  Rewards:`);
      blockMeta.rewards.rewards.forEach((r: any) => {
        console.log(`    ${r.pubkey}: ${r.lamports} lamports (${r.rewardType})`);
      });
    }

    if (Number(blockMeta.executedTransactionCount) > 3000) {
      console.log(`  🔥 HIGH ACTIVITY: ${blockMeta.executedTransactionCount} transactions`);
    }
  }, async (error) => {
    console.error('Stream error:', error);
  });
}
```

### Example 3: Filtered Block Monitor

Monitor blocks containing specific program activity:

```typescript [expandable] theme={"system"}
async function monitorDEXBlocks() {
  const subscriptionRequest: SubscribeRequest = {
    blocks: {
      blockSubscribe: {
        accountInclude: [
          "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", // Raydium
          "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK", // Raydium CLMM
          "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"   // Jupiter
        ],
        includeTransactions: true,
        includeAccounts: false,
        includeEntries: false
      }
    },
    commitment: CommitmentLevel.CONFIRMED,
    accounts: {}, transactions: {}, transactionsStatus: {},
    slots: {}, blocksMeta: {}, entry: {}, accountsDataSlice: [],
  };

  const config: LaserstreamConfig = {
    apiKey: 'YOUR_API_KEY',
    endpoint: 'https://laserstream-mainnet-ewr.helius-rpc.com',
  };

  await subscribe(config, subscriptionRequest, async (data) => {
    if (!data.block) return;
    const block = data.block;

    let successfulDexTx = 0;
    let totalFees = 0; // lamports
    block.transactions?.forEach((tx: any) => {
      if (tx.meta && !tx.meta.err) {
        successfulDexTx++;
        // tx.meta.fee is a u64 string — coerce before adding.
        totalFees += Number(tx.meta.fee ?? 0);
      }
    });

    console.log(`\n🔄 DEX Activity Block:`);
    console.log(`  Slot: ${block.slot}`);
    console.log(`  Block Height: ${block.blockHeight?.blockHeight}`);
    console.log(`  Block Hash: ${block.blockhash}`);
    console.log(`  Total transactions in block: ${block.executedTransactionCount}`);
    console.log(`  Matched DEX transactions: ${block.transactions?.length ?? 0}`);
    console.log(`  Successful DEX transactions: ${successfulDexTx}`);
    if (successfulDexTx > 0) {
      console.log(`  Total Fees: ${(totalFees / 1e9).toFixed(4)} SOL`);
      console.log(`  Avg Fee: ${(totalFees / successfulDexTx / 1e9).toFixed(6)} SOL`);
    }
  }, async (error) => {
    console.error('Stream error:', error);
  });
}
```

***

## Data Structures

> [accordion] Slot Data Structure
>
> ```typescript theme={"system"}
> {
>   slot: string;     // Current slot number (u64 as string)
>   parent: string;   // Parent slot number (u64 as string)
>   status: number;   // CommitmentLevel enum: 0 = processed, 1 = confirmed, 2 = finalized
> }
> ```
>
> Each slot represents \~400ms of network time. The three commitment levels reflect progressively stronger guarantees: `processed` (initial), `confirmed` (supermajority voted), `finalized` (irreversible).
>
> > [!TIP]
> >
> > u64 fields (slot, parent) arrive as strings to preserve precision beyond `Number.MAX_SAFE_INTEGER`. Convert with `Number(slot.slot)` when you need arithmetic. `status` is a numeric enum — use `CommitmentLevel[slot.status]` for the human-readable name.

> [accordion] Block Metadata Structure
>
> ```typescript theme={"system"}
> {
>   slot: string;                                  // u64 as string
>   blockhash: string;
>   rewards: {
>     rewards: Array<{
>       pubkey: string;
>       lamports: string;                          // u64 as string
>       rewardType: string;                        // "fee" | "rent" | "voting" | "staking"
>     }>;
>     numPartitions: number | null;
>   };
>   blockTime: { timestamp: string };              // Unix seconds as a u64 string
>   blockHeight: { blockHeight: string };          // u64 as string, wrapped
>   parentSlot: string;                            // u64 as string
>   parentBlockhash: string;
>   executedTransactionCount: string;              // u64 as string
>   entriesCount: string;                          // u64 as string
> }
> ```
>
> > [!TIP]
> >
> > Numeric fields (slot, parentSlot, executedTransactionCount, entriesCount, the values inside `blockHeight` and `blockTime`) are emitted as strings because they are u64 in the underlying proto. Wrap them in `Number(...)` for arithmetic or comparisons.

> [accordion] Full Block Structure
>
> ```typescript theme={"system"}
> {
>   slot: string;                                  // u64 as string
>   blockhash: string;
>   rewards: {
>     rewards: Array<{
>       pubkey: string;
>       lamports: string;                          // u64 as string
>       rewardType: string;
>     }>;
>     numPartitions: number | null;
>   };
>   blockTime: { timestamp: string };              // Unix seconds (u64 string)
>   blockHeight: { blockHeight: string };          // u64 as string, wrapped
>   parentSlot: string;                            // u64 as string
>   parentBlockhash: string;
>   executedTransactionCount: string;              // total executed tx in the block (u64 as string)
>   updatedAccountCount: string;                   // total account updates in the block (u64 as string)
>   entriesCount: string;                          // u64 as string
>   transactions: Array<{
>     signature: Buffer;                           // base58-encode for display
>     isVote: boolean;
>     transaction: TransactionMessage;             // full transaction payload
>     meta: TransactionMeta;                       // execution metadata (fee, err, balances, …)
>     index: string;                               // u64 as string
>   }>;
>   accounts: AccountUpdate[];                     // populated when includeAccounts: true
>   entries: Entry[];                              // populated when includeEntries: true
> }
> ```
>
> Full blocks can be several MB with all transactions and accounts. The same u64-as-string convention applies — wrap numeric fields with `Number(...)` for arithmetic. Inside each transaction, `meta.fee`, `meta.preBalances`, `meta.postBalances`, etc. are also strings.

***

## Performance Considerations

> [card] Slot Monitoring
>
> Lightweight: very low bandwidth, minimal processing overhead. Good for monitoring dashboards.

> [card] Block Metadata
>
> Balanced: moderate bandwidth, block-level insights without full data. Suitable for analytics.

> [card] Full Blocks
>
> High volume: complete transaction data, requires robust processing. Always pair with filters.

> [card] Filtered Blocks
>
> Optimized: use `accountInclude`, disable `includeAccounts`/`includeEntries` you don't need.

***

## Use Cases

> [tab] Network Monitoring
>
> Track network health and performance — slot timing, congestion, consensus.
>
> ```typescript theme={"system"}
> const targetSlotTime = 400; // ms
> const tolerance = 200; // ms
> if (Math.abs(slotTime - targetSlotTime) > tolerance) {
>   console.log(`Network performance issue detected`);
> }
> ```

> [tab] Analytics & Metrics
>
> Collect blockchain analytics data — transaction volume, fee analysis, block size, activity patterns.
>
> ```typescript theme={"system"}
> const dailyStats = {
>   date: new Date().toDateString(),
>   totalTransactions: 0,
>   totalFees: 0,
>   blockCount: 0
> };
> ```

> [tab] Application Synchronization
>
> Keep applications in sync with the network — slot-based updates, block confirmations.
>
> ```typescript theme={"system"}
> if (data.slot && data.slot.status === 'finalized') {
>   updateApplicationState(data.slot.slot);
> }
> ```

***

## Error Handling

> [accordion] Missing Slots
>
> **Symptom:** Gaps in slot progression.
>
> **Causes:** Network connectivity issues, validator downtime, client processing delays.
>
> **Solutions:** Track slot gaps and alert; implement catch-up logic via [historical replay](https://www.helius.dev/docs/laserstream/historical-replay.md); monitor connection health.

> [accordion] High Volume
>
> **Symptom:** Too much block data.
>
> **Solutions:** Use block metadata instead of full blocks; apply account filters; disable unnecessary inclusions (entries, accounts); process asynchronously.

> [accordion] Timing Issues
>
> **Symptom:** Inconsistent slot timing.
>
> **Analysis:** Calculate moving averages; track deviations; monitor network health metrics; correlate with validator performance.

***

## Best Practices

> [!NOTE]
>
> **Production Guidelines:**
>
> * **Start with metadata** — use block metadata before subscribing to full blocks
> * **Apply filters** — use `accountInclude` to drop irrelevant data
> * **Monitor timing** — track slot progression as a network-health canary
> * **Handle gaps** — combine with [historical replay](https://www.helius.dev/docs/laserstream/historical-replay.md) so missing slots are auto-backfilled on reconnect
> * **Process async** — don't block stream processing with heavy computations
> * **Match commitment to need** — `processed` for low-latency UIs, `confirmed`/`finalized` for state writes

***

## Next Steps

> [card] [Transaction Monitoring](https://www.helius.dev/docs/laserstream/guides/transaction-monitoring.md)
>
> Filter transactions by program, account, vote, or failure status.

> [card] [Stream Pump AMM Data](https://www.helius.dev/docs/laserstream/guides/stream-pump-amm-data.md)
>
> Real-world example: monitor Pump AMM transactions.

> [card] [Decoding Transaction Data](https://www.helius.dev/docs/laserstream/guides/decoding-transaction-data.md)
>
> Parse the binary `transactionUpdate` payloads into readable Solana transactions.

> [card] [Yellowstone protocol reference](https://www.helius.dev/docs/grpc/slot-and-block-monitoring)
>
> The same workflow against the raw Yellowstone gRPC protocol.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.