> ## 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.

# 使用 LaserStream 进行插槽和区块监控

> 通过 LaserStream 监控 Solana 网络共识、区块生产和网络状态变化 —— 插槽计时、区块元数据和过滤后的完整区块。

插槽和区块监控为您提供了 Solana 网络共识、区块生产计时和整体健康状况的窗口。通过 LaserStream，您可以使用 [`helius-laserstream`](/docs/zh/laserstream/clients) SDK 实时跟踪插槽进展、区块最终化和网络性能指标。

<Info>
  **先决条件：** 本指南假设您已完成 [LaserStream gRPC 快速入门](/docs/zh/laserstream/grpc) 并拥有 API 密钥。
</Info>

***

## 监控类型

<Tabs>
  <Tab title="插槽更新">
    **跟踪网络共识进展**

    监控不同承诺级别的插槽进展：

    ```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: [],
    };
    ```

    **插槽数据包括：** 插槽编号、父插槽、承诺状态 (`processed` / `confirmed` / `finalized`) 以及领导者信息。

    <Note>
      **最佳用途：** 网络健康监控、插槽计时分析、共识跟踪。
    </Note>
  </Tab>

  <Tab title="区块数据">
    **监控完整区块信息**

    流播含事务和账户更新的完整区块：

    ```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: [],
    };
    ```

    **区块数据包括：** 区块元数据、事务、账户更新、区块计时。

    <Warning>
      **高流量：** 完整区块流会生成大量数据。使用 `accountInclude` 过滤器减少流量。
    </Warning>
  </Tab>

  <Tab title="区块元数据">
    **轻量级区块信息**

    获取不含事务细节的区块元数据：

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

    **元数据包括：** 区块哈希、父哈希、插槽、高度、事务数、奖励。

    <Tip>
      **高效：** 相比整个区块流量更低的带宽。
    </Tip>
  </Tab>
</Tabs>

***

## 实用示例

### 示例 1：网络健康监控器

跟踪插槽进展并识别网络问题：

```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);
```

### 示例 2：区块生产监控器

跟踪区块生产和交易量：

```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);
  });
}
```

### 示例 3：过滤区块监控器

监控包含特定程序活动的区块：

```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);
  });
}
```

***

## 数据结构

<Accordion title="插槽数据结构">
  ```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
  }
  ```

  每个插槽代表大约400毫秒的网络时间。三个承诺级别反映了逐步增强的保证：`processed` (初始)、`confirmed` (超多数投票)、`finalized` (不可逆)。

  <Tip>
    u64 字段（插槽、父级）以字符串形式传送，以在 `Number.MAX_SAFE_INTEGER` 之后保持精度。需要进行算术运算时请使用 `Number(slot.slot)` 进行转换。`status` 是一个数字枚举 — 使用 `CommitmentLevel[slot.status]` 获取可读名称。
  </Tip>
</Accordion>

<Accordion title="区块元数据结构">
  ```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>
    数字字段（slot, parentSlot, executedTransactionCount, entriesCount, `blockHeight` 和 `blockTime` 内的值）都以字符串形式输出，因为它们在底层 proto 中是 u64。对于算术或比较，请将它们包装在 `Number(...)` 中。
  </Tip>
</Accordion>

<Accordion title="完整区块结构">
  ```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
  }
  ```

  完整区块可能包含数 MB 的所有事务和账户。相同的 u64-as-string 约定适用 —— 将数字字段包装在 `Number(...)` 以进行算术。每个事务中，`meta.fee`、`meta.preBalances`、`meta.postBalances` 等也是字符串。
</Accordion>

***

## 性能考虑

<CardGroup cols={2}>
  <Card title="插槽监控" icon="clock">
    轻量级：带宽极低，处理开销最小。适用于监控仪表板。
  </Card>

  <Card title="区块元数据" icon="info">
    平衡：中等带宽，区块级洞察，无完整数据。适合分析。
  </Card>

  <Card title="完整区块" icon="database">
    高流量：完整交易数据，需要强大的处理能力。始终与过滤器配对使用。
  </Card>

  <Card title="过滤区块" icon="filter">
    优化：使用 `accountInclude`，禁用不需要的 `includeAccounts`/`includeEntries`。
  </Card>
</CardGroup>

***

## 使用案例

<Tabs>
  <Tab title="网络监控">
    跟踪网络健康和性能 —— 插槽计时、拥堵、共识。

    ```typescript theme={"system"}
    const targetSlotTime = 400; // ms
    const tolerance = 200; // ms
    if (Math.abs(slotTime - targetSlotTime) > tolerance) {
      console.log(`Network performance issue detected`);
    }
    ```
  </Tab>

  <Tab title="分析与指标">
    收集区块链分析数据 —— 交易量、费用分析、区块大小、活动模式。

    ```typescript theme={"system"}
    const dailyStats = {
      date: new Date().toDateString(),
      totalTransactions: 0,
      totalFees: 0,
      blockCount: 0
    };
    ```
  </Tab>

  <Tab title="应用同步">
    使应用与网络保持同步 —— 以插槽为基础的更新、区块确认。

    ```typescript theme={"system"}
    if (data.slot && data.slot.status === 'finalized') {
      updateApplicationState(data.slot.slot);
    }
    ```
  </Tab>
</Tabs>

***

## 错误处理

<Accordion title="缺失插槽">
  **症状：** 插槽进展出现空缺。

  **原因：** 网络连接问题、验证器宕机、客户端处理延迟。

  **解决方案：** 跟踪插槽空缺并发出警报；通过 [历史重播](/docs/zh/laserstream/historical-replay) 实现捕获逻辑；监控连接健康。
</Accordion>

<Accordion title="高流量">
  **症状：** 区块数据过多。

  **解决方案：** 使用区块元数据代替完整区块；应用账户过滤器；禁用不必要的包含项（条目、账户）；异步处理。
</Accordion>

<Accordion title="计时问题">
  **症状：** 插槽计时不一致。

  **分析：** 计算移动平均值；跟踪偏差；监控网络健康指标；与验证器性能相关联。
</Accordion>

***

## 最佳实践

<Note>
  **生产指南：**

  * **从元数据开始** — 在订阅完整区块之前使用区块元数据
  * **应用过滤器** — 使用 `accountInclude` 删除不相关数据
  * **监控计时** — 将插槽进展作为网络健康指示灯
  * **处理空缺** — 结合 [历史重播](/docs/zh/laserstream/historical-replay)，使在重新连接时自动回填缺失插槽
  * **异步处理** — 不要通过繁重的计算阻塞流处理
  * **匹配承诺与需求** — `processed` 用于低延迟接口，`confirmed`/`finalized` 用于状态写入
</Note>
