> ## 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 gRPC 中使用 matchMints 订阅涉及某个代币铸币地址的每笔交易。它可以捕获 accountInclude 因铸币地址不在账户键中而遗漏的 SPL 转账。

LaserStream 的 `matchMints` 标志让 gRPC 交易订阅除了匹配账户键外，还能匹配**交易前后代币余额中的代币铸币地址**。

将铸币地址放入 `accountInclude`，并设置 `matchMints: true`，即可接收涉及该代币的每笔交易：转账、兑换、铸造、销毁和账户关闭。

<Note>
  `matchMints` 仅适用于 LaserStream gRPC。目前尚不适用于 LaserStream WebSocket。
</Note>

## 问题：普通账户过滤器会遗漏大多数代币转账

使用 `accountInclude: [mint]` 监控代币时，只能匹配铸币地址公钥出现在交易账户键中的交易。

经典的 SPL `Transfer` 指令从不引用铸币地址。它只指定源代币账户、目标代币账户和所有者，因此普通账户过滤器会遗漏任何代币最常见的操作。

只有直接传入铸币地址的指令才能匹配，例如 `MintTo`、`Burn`、`TransferChecked`，以及程序账户中包含铸币地址的兑换交易。此前唯一的解决方法是流式传输所有交易，并自行检查每笔交易的代币余额。

## `matchMints` 的工作原理

在交易过滤器上设置 `matchMints: true` 后，LaserStream 会根据交易的 `preTokenBalances` 和 `postTokenBalances` 构建一组铸币地址。

随后，你的 `accountInclude`、`accountExclude` 和 `accountRequired` 列表会同时匹配账户键和该铸币地址集合。如果某个铸币地址对应的任意代币账户出现在任一余额列表中，该铸币地址就符合条件，无论余额是否发生变化。

该标志需要显式启用，未设置此标志的过滤器行为与之前完全相同。因此，你可以将它添加到现有订阅中，而不会改变该订阅原本接收的内容。SPL 和 Token-2022 铸币地址均受支持，因为这两个程序都会填充交易前后的代币余额。

## 语义

| 谓词                | 不使用 `matchMints`   | 使用 `matchMints: true`                     |
| ----------------- | ------------------ | ----------------------------------------- |
| `accountInclude`  | 如果列出的任意键位于账户键中，则匹配 | 如果列出的任意键位于账户键**或**铸币地址集合中，则匹配             |
| `accountExclude`  | 如果列出的任意键位于账户键中，则拒绝 | 如果列出的任意键位于账户键**或**铸币地址集合中，则拒绝             |
| `accountRequired` | 列出的每个键都必须位于账户键中    | 列出的每个键都必须位于账户键**或**铸币地址集合中（每个键可由其中任意一项满足） |

其余过滤逻辑保持不变：

* 同一个命名过滤器中的谓词仍通过 AND 组合（`vote`、`failed`、`signature` 和账户列表）。
* 多个命名过滤器仍通过 OR 组合。
* 列表中的值使用 OR 关系（`accountRequired` 除外，其中所有值都必须匹配）。
* 对于没有代币余额的交易，会回退到仅匹配账户键。`matchMints` 绝不会添加没有代币活动的交易。
* 单独使用 `matchMints` 不会限制流。要使过滤器被接受，仍需在账户列表中至少添加一个键或铸币地址（或使用其他限制性谓词）。

<Note>
  LaserStream 通过精确公钥匹配铸币地址。与 `tokenAccounts: "balanceChanged"` 不同，铸币地址没有“仅余额发生变化”模式。
</Note>

## 在 LaserStream gRPC 中使用

在 `SubscribeRequest` 的交易过滤器中添加 `matchMints: true`，并将铸币地址放入 `accountInclude`。以下示例会流式传输主网上的每笔 USDC 交易：

<Tabs>
  <Tab title="TypeScript">
    需要 `helius-laserstream` 0.8.5 或更高版本。该字段也可写作 `match_mints`。

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

    const USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

    const subscriptionRequest: SubscribeRequest = {
      transactions: {
        'usdc-txs': {
          accountInclude: [USDC],
          accountExclude: [],
          accountRequired: [],
          vote: false,
          failed: false,
          matchMints: true, // match USDC via pre/post token-balance mints
        },
      },
      commitment: CommitmentLevel.CONFIRMED,
      accounts: {}, slots: {}, 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) => {
      const tx = data.transaction?.transaction;
      if (!tx) return;
      // USDC balances touched by this transaction
      const usdcBalances = (tx.meta?.postTokenBalances || []).filter((b: any) => b.mint === USDC);
      console.log(bs58.encode(tx.signature), usdcBalances);
    }, async (error) => {
      console.error('Stream error:', error);
    });
    ```
  </Tab>

  <Tab title="Rust">
    需要 `helius-laserstream` 0.6.4 或更高版本（它会引入 `laserstream-core-proto` 11.3.0）。该字段直接来自 proto crate。

    ```rust theme={"system"}
    use std::collections::HashMap;
    use helius_laserstream::grpc::{SubscribeRequest, SubscribeRequestFilterTransactions};

    let request = SubscribeRequest {
        transactions: HashMap::from([(
            "usdc-txs".to_string(),
            SubscribeRequestFilterTransactions {
                account_include: vec!["EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v".to_string()],
                vote: Some(false),
                failed: Some(false),
                match_mints: true,
                ..Default::default()
            },
        )]),
        ..Default::default()
    };
    ```
  </Tab>

  <Tab title="Go">
    需要标签为 `go/v0.3.0` 或更高版本的 Go 模块。

    ```go theme={"system"}
    vote := false
    failed := false
    req := &laserstream.SubscribeRequest{
        Transactions: map[string]*laserstream.SubscribeRequestFilterTransactions{
            "usdc-txs": {
                AccountInclude: []string{"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"},
                Vote:           &vote,
                Failed:         &failed,
                MatchMints:     true,
            },
        },
        Commitment: &commitmentLevel,
    }
    ```
  </Tab>
</Tabs>

如果你使用原始 gRPC 或 Yellowstone 客户端而不是 SDK，请基于 Helius proto 重新生成代码（`laserstream-core-proto` 11.3.0 或更高版本，或者使用 SDK 仓库中附带的 `.proto`）。

`match_mints` 是 `SubscribeRequestFilterTransactions` 的第 32 个字段。使用上游 Triton proto 生成的客户端会静默丢弃未知字段，因此在重新生成代码之前，该标志不会生效。

有关所有交易过滤器字段，请参阅[订阅请求参考](/docs/zh/laserstream/grpc#订阅请求)。

## 与 `tokenAccounts` 结合使用，监控一个钱包中的一种代币

`matchMints` 可与 [`tokenAccounts` 扩展](/docs/zh/laserstream/token-account-filtering)组合使用，因此一个过滤器可以同时匹配钱包所有者和铸币地址。

以下示例会流式传输某个钱包 USDC 余额的每次变化：

```typescript theme={"system"}
transactions: {
  'wallet-usdc': {
    accountInclude: [WALLET],
    accountRequired: [USDC],
    accountExclude: [],
    tokenAccounts: 'balanceChanged', // wallet matched via its token accounts
    matchMints: true,                // USDC matched via balance mints
    vote: false,
    failed: false,
  },
},
```

`accountInclude` 与 `tokenAccounts` 结合使用，可以找出该钱包代币余额发生变化的交易。`accountRequired` 与 `matchMints` 结合使用，可进一步将结果缩小到涉及 USDC 的交易。

## 查看匹配内容

交易通过铸币地址匹配后，请在 `meta.preTokenBalances[].mint` 和 `meta.postTokenBalances[].mint` 中查找该铸币地址。对于普通转账，铸币地址通常不会出现在账户键中，因此不要在那里查找。

对同一 `accountIndex` 上的 `preTokenBalances` 和 `postTokenBalances` 进行差异比较，即可查看转移了多少代币以及代币在由哪些所有者控制的账户之间转移。

[交易监控指南](/docs/zh/laserstream/guides/transaction-monitoring#交易数据结构)详细介绍了交易结构。

## 限制和注意事项

* 铸币地址与账户键使用相同的 `accountInclude`、`accountExclude` 和 `accountRequired` 列表，因此它们计入相同的每列表套餐限制。没有单独的铸币地址限制。
* 匹配成本不会随列出的铸币地址数量而增加。列出 100 个和 100,000 个铸币地址的性能相同，未设置该标志的订阅者不会产生额外开销。
* [历史重放](/docs/zh/laserstream/historical-replay)支持 `matchMints`，因此重放订阅返回的交易与实时流原本会返回的交易相同。
* 如果你将[压缩（布谷鸟）过滤器](/docs/zh/laserstream/cuckoo-filters)附加到交易订阅，`matchMints` 除了会用账户键探测该过滤器，也会用铸币地址集合进行探测。
* `matchMints` 已在所有 LaserStream gRPC 区域、主网和开发网上线。目前尚不适用于 LaserStream WebSocket。
* SDK 最低版本：JavaScript/TypeScript `helius-laserstream` 0.8.5、Rust `helius-laserstream` 0.6.4、Go `go/v0.3.0`。

## 相关内容

<CardGroup cols={2}>
  <Card title="Token Account (ATA) Filtering" icon="coins" href="/docs/zh/laserstream/token-account-filtering">
    匹配涉及钱包所拥有代币账户的交易
  </Card>

  <Card title="Transaction Monitoring" icon="receipt" href="/docs/zh/laserstream/guides/transaction-monitoring">
    完整的过滤策略和可通过 gRPC 运行的示例
  </Card>

  <Card title="Subscribe Request Reference" icon="filter" href="/docs/zh/laserstream/grpc">
    所有交易过滤器字段，包括 `matchMints`
  </Card>

  <Card title="Historical Replay" icon="clock-rotate-left" href="/docs/zh/laserstream/historical-replay">
    使用相同过滤器回填最多 24 小时的代币活动
  </Card>
</CardGroup>
