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

# Giám sát giao dịch với LaserStream

> Truyền phát giao dịch Solana theo thời gian thực với LaserStream — lọc chương trình, chi tiết thực thi, thay đổi số dư token và phát lại an toàn khi kết nối lại.

Tính năng giám sát giao dịch cho phép bạn theo dõi quá trình thực thi giao dịch, trạng thái thành công/thất bại, tương tác với chương trình và thay đổi số dư token trên Solana theo thời gian thực. Hướng dẫn này trình bày các chiến lược lọc và cách triển khai thực tế bằng SDK [`helius-laserstream`](/docs/vi/laserstream/clients).

<Info>
  **Điều kiện tiên quyết:** Hướng dẫn này giả định rằng bạn đã hoàn thành phần [Bắt đầu nhanh với LaserStream gRPC](/docs/vi/laserstream/grpc) và có khóa API.
</Info>

***

## Các tùy chọn lọc giao dịch

LaserStream sử dụng cùng cấu trúc bộ lọc như Yellowstone gRPC, bao gồm bộ lọc `tokenAccounts` (mở rộng ATA). Các trường bạn sẽ đặt bên trong `transactions.<label>`:

* **`accountInclude`** — khớp nếu có bất kỳ tài khoản nào trong số này xuất hiện (OR logic)
* **`accountRequired`** — chỉ khớp nếu tất cả các tài khoản này đều xuất hiện (AND logic)
* **`accountExclude`** — loại bỏ nếu có bất kỳ tài khoản nào trong số này xuất hiện
* **`vote` / `failed`** — cờ boolean cho giao dịch bỏ phiếu và giao dịch thất bại
* **`tokenAccounts`** — tùy chọn bật tính năng mở rộng tài khoản token liên kết (ATA) (`"balanceChanged"`, `"all"` hoặc `"none"`), để ví trong `accountInclude` cũng khớp với các giao dịch có số dư token SPL thuộc quyền sở hữu của ví đó. Xem [Lọc tài khoản token (ATA)](/docs/vi/laserstream/token-account-filtering) và tab **Theo dõi ví** bên dưới.
* **`matchMints`** — cờ tùy chọn giúp đối chiếu thêm danh sách tài khoản với các mint trong số dư token trước/sau của giao dịch, nhờ đó một mint trong `accountInclude` sẽ bắt được mọi thao tác chuyển, hoán đổi, tạo và đốt token đó. Xem [Lọc mint token](/docs/vi/laserstream/mint-filtering) và tab **Theo dõi token** bên dưới.

<Tabs>
  <Tab title="Program Filtering">
    **Giám sát các giao dịch liên quan đến những chương trình cụ thể**

    Theo dõi tất cả giao dịch có tương tác với các chương trình mà bạn quan tâm:

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

    const subscriptionRequest: SubscribeRequest = {
      transactions: {
        "program-filter": {
          accountInclude: [
            "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Token Program
            "11111111111111111111111111111111",              // System Program
            "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"  // Your program
          ],
          accountExclude: [],
          accountRequired: [],
          vote: false,
          failed: false
        }
      },
      commitment: CommitmentLevel.CONFIRMED,
      accounts: {},
      slots: {},
      transactionsStatus: {},
      blocks: {},
      blocksMeta: {},
      entry: {},
      accountsDataSlice: [],
    };
    ```

    **Phù hợp nhất cho:** Giám sát theo chương trình, theo dõi giao thức DeFi, tương tác với hợp đồng thông minh.
  </Tab>

  <Tab title="Account-Specific">
    **Giám sát các giao dịch ảnh hưởng đến những tài khoản cụ thể**

    ```typescript theme={"system"}
    const subscriptionRequest: SubscribeRequest = {
      transactions: {
        "wallet-filter": {
          accountInclude: [
            "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC mint
            "YourWalletAddress"                                // Your wallet
          ],
          accountExclude: [],
          accountRequired: [],
          vote: false,
          failed: true // Include failures to track errors
        }
      },
      commitment: CommitmentLevel.CONFIRMED,
      accounts: {}, slots: {}, transactionsStatus: {},
      blocks: {}, blocksMeta: {}, entry: {}, accountsDataSlice: [],
    };
    ```

    **Trường hợp sử dụng:** Giám sát ví, theo dõi mint token, bảng điều khiển hoạt động tài khoản.
  </Tab>

  <Tab title="Advanced Filtering">
    **Kết hợp nhiều tiêu chí lọc**

    ```typescript theme={"system"}
    const subscriptionRequest: SubscribeRequest = {
      transactions: {
        "advanced-filter": {
          accountInclude: ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"],
          accountRequired: ["YourProgramId"], // Must include this program
          accountExclude: ["VoteProgram"],     // Exclude vote-related txs
          vote: false,
          failed: false
        }
      },
      commitment: CommitmentLevel.CONFIRMED,
      accounts: {}, slots: {}, transactionsStatus: {},
      blocks: {}, blocksMeta: {}, entry: {}, accountsDataSlice: [],
    };
    ```

    **Logic lọc:** `accountInclude` (OR) **AND** `accountRequired` (AND) **AND NOT** `accountExclude`.
  </Tab>

  <Tab title="Watching a Wallet">
    **Bắt các giao dịch chuyển token đến, không chỉ hoạt động trực tiếp**

    `accountInclude` chỉ khớp với các giao dịch mà ví xuất hiện trực tiếp trong khóa tài khoản. Khi ai đó gửi token SPL đến ví, giao dịch chuyển sẽ tương tác với **tài khoản token liên kết (ATA)** của ví chứ không phải khóa công khai của ví — vì vậy `accountInclude: [wallet]` thông thường sẽ không bao giờ phát hiện được giao dịch đó.

    Đặt `tokenAccounts` để mở rộng phạm vi khớp đến các giao dịch có số dư token **thuộc sở hữu** của ví. Trường này nhận một chuỗi:

    * **`"balanceChanged"`** — khớp khi số dư token thuộc sở hữu thay đổi (hoặc tài khoản token của nó bị đóng). Phù hợp nhất với yêu cầu "thông báo khi tiền thực sự được chuyển" — phạm vi hẹp hơn, lưu lượng thấp hơn và là lựa chọn mặc định được đề xuất.
    * **`"all"`** — khớp với mọi giao dịch tham chiếu đến số dư token thuộc sở hữu, ngay cả khi số dư không thay đổi. Lưu lượng cao hơn đáng kể.
    * **`"none"`** — không mở rộng (giống như bỏ qua trường này).

    ```typescript theme={"system"}
    const subscriptionRequest: SubscribeRequest = {
      transactions: {
        "wallet-with-tokens": {
          accountInclude: ["YourWalletAddress"],
          accountExclude: [],
          accountRequired: [],
          vote: false,
          failed: false,
          tokenAccounts: "balanceChanged" // also match the wallet's ATAs
        }
      },
      commitment: CommitmentLevel.CONFIRMED,
      accounts: {}, slots: {}, transactionsStatus: {},
      blocks: {}, blocksMeta: {}, entry: {}, accountsDataSlice: [],
    };
    ```

    <Note>
      Việc đối chiếu dựa trên chủ sở hữu — tính năng này bắt mọi tài khoản token thuộc sở hữu của ví (bao gồm cả các tài khoản không chính tắc), không chỉ địa chỉ ATA được dẫn xuất. SDK tự động chuyển đổi chuỗi thành enum `TokenAccountExpansionControlFlag` ở cấp giao thức cho bạn.
    </Note>
  </Tab>

  <Tab title="Watching a Token">
    **Bắt mọi giao dịch của một mint, không chỉ các giao dịch nêu trực tiếp mint đó**

    `accountInclude: [mint]` thông thường chỉ khớp với các giao dịch có khóa tài khoản chứa mint, chẳng hạn như `MintTo`, `Burn` hoặc `TransferChecked`. `Transfer` SPL kiểu truyền thống không bao giờ tham chiếu đến mint, vì vậy phần lớn giao dịch chuyển token sẽ bị bỏ sót.

    Đặt `matchMints: true` để danh sách tài khoản cũng được đối chiếu với các mint trong `preTokenBalances` và `postTokenBalances` của giao dịch:

    ```typescript theme={"system"}
    const USDC = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

    const subscriptionRequest: SubscribeRequest = {
      transactions: {
        "usdc-activity": {
          accountInclude: [USDC],
          accountExclude: [],
          accountRequired: [],
          vote: false,
          failed: false,
          matchMints: true // also match via pre/post token-balance mints
        }
      },
      commitment: CommitmentLevel.CONFIRMED,
      accounts: {}, slots: {}, transactionsStatus: {},
      blocks: {}, blocksMeta: {}, entry: {}, accountsDataSlice: [],
    };
    ```

    Kết hợp với `tokenAccounts` để theo dõi một token cho một ví: đặt ví vào `accountInclude` cùng `tokenAccounts: "balanceChanged"` và đặt mint vào `accountRequired` cùng `matchMints: true`. Yêu cầu `helius-laserstream` 0.8.5+ (JS), 0.6.4+ (Rust) hoặc `go/v0.3.0`+ (Go). Xem [Lọc mint token](/docs/vi/laserstream/mint-filtering) để biết toàn bộ ngữ nghĩa.
  </Tab>
</Tabs>

***

## Ví dụ thực tế

### Ví dụ 1: Giám sát giao dịch DEX

Theo dõi các giao dịch tương tác với những chương trình DEX phổ biến:

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

async function monitorDEXTransactions() {
  const subscriptionRequest: SubscribeRequest = {
    transactions: {
      "dex-filter": {
        accountInclude: [
          "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", // Raydium
          "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK", // Raydium CLMM
          "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"   // Jupiter
        ],
        accountExclude: [],
        accountRequired: [],
        vote: false,
        failed: false
      }
    },
    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', // Choose your closest region
  };

  await subscribe(config, subscriptionRequest, async (data) => {
    if (!data.transaction?.transaction) return;
    const tx = data.transaction.transaction;
    console.log(`\n🔄 DEX Transaction:`);
    console.log(`  Signature: ${bs58.encode(tx.signature)}`);
    console.log(`  Slot: ${data.transaction.slot}`);
    console.log(`  Status: ${tx.meta?.err ? 'Failed' : 'Success'}`);
    console.log(`  Fee: ${tx.meta?.fee || 0} lamports`);
    console.log(`  Compute Units: ${tx.meta?.computeUnitsConsumed || 0}`);

    // Token balance changes
    if (tx.meta?.preTokenBalances?.length > 0) {
      console.log(`  Token Balance Changes:`);
      tx.meta.preTokenBalances.forEach((preBalance: any, index: number) => {
        const postBalance = tx.meta.postTokenBalances[index];
        if (preBalance && postBalance) {
          const change = postBalance.uiTokenAmount.uiAmount - preBalance.uiTokenAmount.uiAmount;
          if (change !== 0) {
            console.log(`    ${preBalance.mint}: ${change > 0 ? '+' : ''}${change}`);
          }
        }
      });
    }
  }, async (error) => {
    console.error('Stream error:', error);
  });
}

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

### Ví dụ 2: Giám sát giao dịch thất bại

Theo dõi các giao dịch thất bại để phát hiện vấn đề của ứng dụng:

```typescript [expandable] theme={"system"}
async function monitorFailedTransactions() {
  const subscriptionRequest: SubscribeRequest = {
    transactions: {
      "failures": {
        accountInclude: ["YourProgramId"],
        accountExclude: [],
        accountRequired: [],
        vote: false,
        failed: true // Only failed transactions
      }
    },
    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) => {
    if (!data.transaction?.transaction?.meta?.err) return;
    const tx = data.transaction.transaction;
    console.log(`\n❌ Failed Transaction:`);
    console.log(`  Signature: ${bs58.encode(tx.signature)}`);
    console.log(`  Slot: ${data.transaction.slot}`);
    console.log(`  Error: ${JSON.stringify(tx.meta.err)}`);
    console.log(`  Fee: ${tx.meta.fee} lamports`);
    console.log(`  Compute Units: ${tx.meta.computeUnitsConsumed || 0}`);
  }, async (error) => {
    console.error('Stream error:', error);
  });
}
```

### Ví dụ 3: Giám sát giao dịch giá trị cao

Theo dõi các giao dịch chuyển SOL có giá trị lớn:

```typescript [expandable] theme={"system"}
async function monitorHighValueTransactions() {
  const subscriptionRequest: SubscribeRequest = {
    transactions: {
      "system-program": {
        accountInclude: ["11111111111111111111111111111111"],
        accountExclude: [],
        accountRequired: [],
        vote: false,
        failed: false
      }
    },
    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) => {
    if (!data.transaction?.transaction?.meta) return;
    const tx = data.transaction.transaction;
    const preBalances = tx.meta.preBalances || [];
    const postBalances = tx.meta.postBalances || [];

    let maxChange = 0;
    preBalances.forEach((preBalance: number, index: number) => {
      const postBalance = postBalances[index] || 0;
      maxChange = Math.max(maxChange, Math.abs(postBalance - preBalance));
    });

    const changeInSOL = maxChange / 1e9;
    if (changeInSOL > 10) {
      console.log(`\n💰 High-Value Transaction:`);
      console.log(`  Signature: ${bs58.encode(tx.signature)}`);
      console.log(`  Slot: ${data.transaction.slot}`);
      console.log(`  Max SOL Transfer: ${changeInSOL.toFixed(2)} SOL`);
      console.log(`  Fee: ${tx.meta.fee / 1e9} SOL`);
    }
  }, async (error) => {
    console.error('Stream error:', error);
  });
}
```

### Ví dụ 4: Theo dõi ví (bao gồm giao dịch chuyển token)

Giám sát mọi hoạt động làm dịch chuyển tiền của một ví — bao gồm các giao dịch chuyển token SPL đến có tương tác với ATA của ví — bằng cách thêm `tokenAccounts` vào bộ lọc `accountInclude` thông thường:

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

async function watchWallet(wallet: string) {
  const subscriptionRequest: SubscribeRequest = {
    transactions: {
      "wallet-activity": {
        accountInclude: [wallet],
        accountExclude: [],
        accountRequired: [],
        vote: false,
        failed: false,
        // Also match txs touching token accounts this wallet owns.
        // "balanceChanged" = only when an owned token balance actually moved.
        tokenAccounts: "balanceChanged"
      }
    },
    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) => {
    if (!data.transaction?.transaction) return;
    const tx = data.transaction.transaction;
    console.log(`\n👛 Wallet activity:`);
    console.log(`  Signature: ${bs58.encode(tx.signature)}`);
    console.log(`  Slot: ${data.transaction.slot}`);

    // Surface token balances this wallet owns that changed in the tx
    const owned = (tx.meta?.postTokenBalances || []).filter((b: any) => b.owner === wallet);
    owned.forEach((post: any) => {
      const pre = (tx.meta.preTokenBalances || []).find(
        (b: any) => b.accountIndex === post.accountIndex
      );
      const before = pre?.uiTokenAmount?.uiAmount || 0;
      const after = post.uiTokenAmount?.uiAmount || 0;
      if (after !== before) {
        console.log(`  ${post.mint}: ${after - before > 0 ? '+' : ''}${after - before}`);
      }
    });
  }, async (error) => {
    console.error('Stream error:', error);
  });
}
```

***

## Cấu trúc dữ liệu giao dịch

<Accordion title="Transaction Message Structure">
  ```typescript theme={"system"}
  {
    signature: string;
    isVote: boolean;
    transaction: {
      message: {
        accountKeys: string[];        // All accounts involved
        instructions: Instruction[];  // Program instructions
        recentBlockhash: string;
      };
      signatures: string[];
    };
    meta: {
      err: any;                      // Error details if failed
      fee: number;                   // Transaction fee in lamports
      computeUnitsConsumed: number;
      preBalances: number[];
      postBalances: number[];
      preTokenBalances: TokenBalance[];
      postTokenBalances: TokenBalance[];
      logMessages: string[];
    };
  }
  ```
</Accordion>

<Accordion title="Token Balance Changes">
  ```typescript theme={"system"}
  {
    accountIndex: number;
    mint: string;
    owner: string;
    uiTokenAmount: {
      amount: string;
      decimals: number;
      uiAmount: number;
      uiAmountString: string;
    };
  }
  ```
</Accordion>

<Accordion title="Instruction Details">
  ```typescript theme={"system"}
  {
    programIdIndex: number; // Index in accountKeys array
    accounts: number[];
    data: string;           // Instruction data (base58)
  }
  ```
</Accordion>

***

## Tham chiếu logic bộ lọc

<CardGroup cols={2}>
  <Card title="Include Logic (OR)" icon="plus">
    **`accountInclude`:** Giao dịch phải liên quan đến BẤT KỲ tài khoản nào trong số này.

    `["A", "B"]` khớp với các giao dịch liên quan đến tài khoản A OR tài khoản B.
  </Card>

  <Card title="Required Logic (AND)" icon="check">
    **`accountRequired`:** Giao dịch phải liên quan đến TẤT CẢ các tài khoản này.

    `["A", "B"]` khớp với các giao dịch liên quan đến tài khoản A AND tài khoản B.
  </Card>

  <Card title="Exclude Logic (NOT)" icon="minus">
    **`accountExclude`:** Giao dịch KHÔNG được liên quan đến bất kỳ tài khoản nào trong số này.
  </Card>

  <Card title="Combined Logic" icon="code">
    Bộ lọc cuối cùng: `(accountInclude OR empty) AND (accountRequired AND all) AND NOT (accountExclude OR any)`.
  </Card>
</CardGroup>

***

## Các yếu tố cần cân nhắc về hiệu năng

<Tabs>
  <Tab title="Volume Management">
    Luồng giao dịch có thể có lưu lượng cao. Để theo kịp:

    * Bắt đầu với các bộ lọc chương trình cụ thể (không đăng ký "tất cả giao dịch")
    * Dùng `confirmed` thay cho `processed` nếu có thể chấp nhận độ trễ bổ sung khoảng 1,5 giây
    * Giám sát năng lực xử lý bằng bộ đếm
    * Cân nhắc chạy song song nhiều trình tiêu thụ phía sau một hàng đợi

    ```typescript theme={"system"}
    let count = 0;
    const startTime = Date.now();
    // inside your subscribe handler:
    count++;
    if (count % 100 === 0) {
      const elapsed = (Date.now() - startTime) / 1000;
      console.log(`Processing ${(count / elapsed).toFixed(1)} tx/sec`);
    }
    ```
  </Tab>

  <Tab title="Data Processing">
    Chỉ trích xuất dữ liệu cần thiết để giảm mức sử dụng bộ nhớ:

    ```typescript theme={"system"}
    import bs58 from 'bs58';

    function extractTransactionData(tx: any) {
      return {
        signature: bs58.encode(tx.signature),
        slot: tx.slot,
        success: !tx.meta?.err,
        fee: tx.meta?.fee || 0,
        computeUnits: tx.meta?.computeUnitsConsumed || 0,
      };
    }
    ```
  </Tab>
</Tabs>

***

## Xử lý lỗi

<Accordion title="Too Many Transactions">
  **Triệu chứng:** Lưu lượng giao dịch quá lớn.

  **Giải pháp:** Thêm các bộ lọc nghiêm ngặt hơn (`accountRequired`, `accountExclude`); sử dụng mức cam kết cao hơn; triển khai lấy mẫu hoặc giới hạn tốc độ; xử lý bất đồng bộ.
</Accordion>

<Accordion title="Missing Transactions">
  **Triệu chứng:** Các giao dịch dự kiến không xuất hiện.

  **Giải pháp:** Xác minh địa chỉ chương trình là chính xác; kiểm tra xem giao dịch có thực sự tồn tại hay không; thử `processed` để nhận cập nhật nhanh hơn; nới lỏng các bộ lọc `accountRequired`/`accountExclude` hạn chế.
</Accordion>

<Accordion title="Parse Errors">
  **Triệu chứng:** Không thể phân tích cú pháp dữ liệu giao dịch.

  **Giải pháp:** Xử lý linh hoạt các trường bị thiếu; xác thực cấu trúc trước khi xử lý; bọc thao tác phân tích cú pháp trong try/catch; xem [Giải mã dữ liệu giao dịch](/docs/vi/laserstream/guides/decoding-transaction-data).
</Accordion>

***

## Các bước tiếp theo

<CardGroup cols={2}>
  <Card title="Slot & Block Monitoring" icon="cube" href="/docs/vi/laserstream/guides/slot-and-block-monitoring">
    Theo dõi sự đồng thuận mạng và quá trình tạo khối.
  </Card>

  <Card title="Stream Pump AMM Data" icon="chart-line" href="/docs/vi/laserstream/guides/stream-pump-amm-data">
    Ví dụ thực tế: giám sát các giao dịch AMM của Pump.fun.
  </Card>

  <Card title="Decoding Transaction Data" icon="binary" href="/docs/vi/laserstream/guides/decoding-transaction-data">
    Phân tích các payload giao dịch nhị phân thành giao dịch Solana có thể đọc được.
  </Card>

  <Card title="Yellowstone protocol reference" icon="book" href="/docs/vi/grpc/transaction-monitoring">
    Cùng một quy trình làm việc trực tiếp với giao thức Yellowstone gRPC thô.
  </Card>
</CardGroup>
