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

# Lọc token mint

> Đăng ký mọi giao dịch tương tác với một token mint trong LaserStream gRPC bằng matchMints. Phát hiện các giao dịch chuyển SPL mà accountInclude bỏ sót vì mint không nằm trong các khóa tài khoản.

Cờ `matchMints` của LaserStream cho phép một đăng ký giao dịch gRPC khớp với **các token mint trong số dư token trước/sau giao dịch**, ngoài các khóa tài khoản của giao dịch.

Đặt một mint vào `accountInclude`, thiết lập `matchMints: true` và bạn sẽ nhận được mọi giao dịch tương tác với token đó: chuyển, hoán đổi, mint-to, đốt và đóng tài khoản.

<Note>
  `matchMints` chỉ khả dụng trên LaserStream gRPC. Tính năng này chưa khả dụng trên LaserStream WebSocket.
</Note>

## Vấn đề: bộ lọc tài khoản thông thường bỏ sót hầu hết các giao dịch chuyển token

Khi theo dõi một token bằng `accountInclude: [mint]`, bạn chỉ khớp với các giao dịch mà pubkey của mint xuất hiện trong các khóa tài khoản của giao dịch.

Một lệnh SPL `Transfer` điển hình không bao giờ tham chiếu đến mint. Lệnh này chỉ định tài khoản token nguồn, tài khoản token đích và chủ sở hữu, vì vậy bộ lọc tài khoản thông thường sẽ bỏ sót thao tác phổ biến nhất trên bất kỳ token nào.

Chỉ những lệnh truyền trực tiếp mint mới khớp, chẳng hạn như `MintTo`, `Burn`, `TransferChecked` và các giao dịch hoán đổi có tài khoản chương trình bao gồm mint. Cách giải quyết duy nhất trước đây là truyền phát tất cả giao dịch và tự kiểm tra số dư token của từng giao dịch.

## Cách `matchMints` hoạt động

Thiết lập `matchMints: true` trên một bộ lọc giao dịch và LaserStream sẽ tạo một tập hợp mint từ `preTokenBalances` và `postTokenBalances` của giao dịch.

Sau đó, các danh sách `accountInclude`, `accountExclude` và `accountRequired` của bạn được khớp với **cả** khóa tài khoản lẫn tập hợp mint đó. Một mint đáp ứng điều kiện nếu bất kỳ tài khoản token nào của mint xuất hiện trong một trong hai danh sách số dư, bất kể số dư có thay đổi hay không.

Cờ này cần được bật rõ ràng. Các bộ lọc không có cờ này vẫn hoạt động chính xác như trước, vì vậy bạn có thể thêm cờ vào một đăng ký hiện có mà không làm thay đổi dữ liệu đăng ký đó đang nhận. Các mint SPL và Token-2022 đều hoạt động vì cả hai chương trình đều điền số dư token trước/sau.

## Ngữ nghĩa

| Điều kiện         | Không có `matchMints`                                                    | Có `matchMints: true`                                                                                                                       |
| ----------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `accountInclude`  | Khớp nếu bất kỳ khóa nào trong danh sách nằm trong các khóa tài khoản    | Khớp nếu bất kỳ khóa nào trong danh sách nằm trong các khóa tài khoản **hoặc** trong tập hợp mint                                           |
| `accountExclude`  | Loại bỏ nếu bất kỳ khóa nào trong danh sách nằm trong các khóa tài khoản | Loại bỏ nếu bất kỳ khóa nào trong danh sách nằm trong các khóa tài khoản **hoặc** trong tập hợp mint                                        |
| `accountRequired` | Mọi khóa trong danh sách đều phải nằm trong các khóa tài khoản           | Mọi khóa trong danh sách đều phải nằm trong các khóa tài khoản **hoặc** trong tập hợp mint (mỗi khóa có thể được đáp ứng bởi một trong hai) |

Phần còn lại của logic lọc không thay đổi:

* Các điều kiện trong cùng một bộ lọc có tên vẫn được kết hợp bằng AND (`vote`, `failed`, `signature` và các danh sách tài khoản).
* Nhiều bộ lọc có tên vẫn được kết hợp bằng OR.
* Các giá trị trong một danh sách được kết hợp bằng OR (ngoại trừ `accountRequired`, trong đó tất cả đều phải khớp).
* Giao dịch không có số dư token sẽ quay về chỉ khớp theo khóa. `matchMints` không bao giờ thêm các giao dịch không có hoạt động token.
* Chỉ riêng `matchMints` không giới hạn luồng. Bạn vẫn cần ít nhất một khóa hoặc mint trong danh sách tài khoản (hoặc một điều kiện giới hạn khác) để bộ lọc được chấp nhận.

<Note>
  LaserStream khớp mint theo pubkey chính xác. Không có chế độ "chỉ số dư đã thay đổi" cho mint, khác với `tokenAccounts: "balanceChanged"`.
</Note>

## Sử dụng trong LaserStream gRPC

Thêm `matchMints: true` vào một bộ lọc giao dịch trong `SubscribeRequest` và đặt mint vào `accountInclude`. Ví dụ này truyền phát mọi giao dịch USDC trên mainnet:

<Tabs>
  <Tab title="TypeScript">
    Yêu cầu `helius-laserstream` phiên bản 0.8.5 trở lên. Trường này cũng được chấp nhận dưới tên `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">
    Yêu cầu `helius-laserstream` phiên bản 0.6.4 trở lên (sẽ lấy `laserstream-core-proto` 11.3.0). Trường này được lấy trực tiếp từ 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">
    Yêu cầu mô-đun Go ở thẻ `go/v0.3.0` trở lên.

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

Nếu sử dụng một máy khách gRPC thô hoặc Yellowstone thay vì SDK, hãy tạo lại từ proto của Helius (`laserstream-core-proto` 11.3.0 trở lên hoặc `.proto` đi kèm trong kho lưu trữ SDK).

`match_mints` là trường 32 của `SubscribeRequestFilterTransactions`. Các máy khách được tạo từ proto Triton thượng nguồn sẽ âm thầm loại bỏ trường không xác định, vì vậy cờ này không có hiệu lực cho đến khi bạn tạo lại máy khách.

Xem [tài liệu tham khảo về yêu cầu đăng ký](/docs/vi/laserstream/grpc#yêu-cầu-đăng-ký) để biết mọi trường của bộ lọc giao dịch.

## Kết hợp với `tokenAccounts` để theo dõi một token cho một ví

`matchMints` có thể kết hợp với [tính năng mở rộng `tokenAccounts`](/docs/vi/laserstream/token-account-filtering), nhờ đó một bộ lọc có thể khớp đồng thời theo chủ sở hữu ví và mint.

Ví dụ này truyền phát mọi thay đổi đối với số dư USDC của một ví:

```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` kết hợp với `tokenAccounts` sẽ tìm các giao dịch làm thay đổi số dư token của ví. `accountRequired` kết hợp với `matchMints` sẽ thu hẹp kết quả xuống những giao dịch liên quan đến USDC.

## Đọc thông tin đã khớp

Khi một giao dịch khớp thông qua mint, hãy tìm mint trong `meta.preTokenBalances[].mint` và `meta.postTokenBalances[].mint`. Đối với các giao dịch chuyển thông thường, mint thường không có trong các khóa tài khoản, vì vậy đừng tìm mint ở đó.

So sánh sự khác biệt giữa `preTokenBalances` và `postTokenBalances` trên cùng một `accountIndex` để biết lượng token đã di chuyển và giữa những chủ sở hữu nào.

[Hướng dẫn giám sát giao dịch](/docs/vi/laserstream/guides/transaction-monitoring#cấu-trúc-dữ-liệu-giao-dịch) trình bày chi tiết về cấu trúc giao dịch.

## Giới hạn và lưu ý

* Các mint nằm trong cùng những danh sách `accountInclude`, `accountExclude` và `accountRequired` với các khóa tài khoản, vì vậy chúng được tính vào cùng giới hạn của gói cho mỗi danh sách. Không có giới hạn mint riêng.
* Chi phí khớp không tăng theo số lượng mint trong danh sách. Hiệu năng của 100 mint và 100.000 mint là như nhau, còn những người đăng ký không thiết lập cờ sẽ không chịu thêm chi phí nào.
* [Phát lại dữ liệu lịch sử](/docs/vi/laserstream/historical-replay) tuân theo `matchMints`, vì vậy đăng ký phát lại sẽ trả về cùng các giao dịch mà luồng trực tiếp sẽ trả về.
* Nếu bạn đính kèm một [bộ lọc nén (cuckoo)](/docs/vi/laserstream/cuckoo-filters) vào đăng ký giao dịch, `matchMints` cũng kiểm tra tập hợp mint với bộ lọc đó, bên cạnh các khóa tài khoản.
* `matchMints` đang hoạt động trên tất cả khu vực LaserStream gRPC, cả mainnet và devnet. Hiện tại, tính năng này chưa khả dụng trên LaserStream WebSocket.
* Phiên bản SDK tối thiểu: JavaScript/TypeScript `helius-laserstream` 0.8.5, Rust `helius-laserstream` 0.6.4, Go `go/v0.3.0`.

## Nội dung liên quan

<CardGroup cols={2}>
  <Card title="Token Account (ATA) Filtering" icon="coins" href="/docs/vi/laserstream/token-account-filtering">
    Khớp các giao dịch tương tác với những tài khoản token do một ví sở hữu
  </Card>

  <Card title="Transaction Monitoring" icon="receipt" href="/docs/vi/laserstream/guides/transaction-monitoring">
    Các chiến lược lọc đầy đủ và ví dụ có thể chạy qua gRPC
  </Card>

  <Card title="Subscribe Request Reference" icon="filter" href="/docs/vi/laserstream/grpc">
    Mọi trường của bộ lọc giao dịch, bao gồm `matchMints`
  </Card>

  <Card title="Historical Replay" icon="clock-rotate-left" href="/docs/vi/laserstream/historical-replay">
    Bổ sung dữ liệu hoạt động token trong tối đa 48 giờ bằng cùng một bộ lọc
  </Card>
</CardGroup>
