> ## 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 tài khoản token (ATA) qua WebSocket

> Phát hiện các giao dịch chuyển token SPL đến ví trong luồng WebSocket của LaserStream bằng bộ lọc tokenAccounts trên transactionSubscribe — đối sánh theo chủ sở hữu.

Bộ lọc `tokenAccounts` trên phương thức WebSocket [`transactionSubscribe`](/docs/vi/rpc/websocket/transaction-subscribe) cho phép gói đăng ký đối sánh hoạt động trên **các tài khoản token liên kết (ATA) thuộc sở hữu của ví**, thay vì chỉ các giao dịch có pubkey của ví xuất hiện trực tiếp. Bộ lọc tương tự cũng có trên gRPC — xem [Lọc tài khoản token (ATA)](/docs/vi/laserstream/token-account-filtering) để biết phiên bản gRPC.

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

Khi theo dõi một ví bằng `accountInclude: [wallet]`, bạn chỉ đối sánh các giao dịch mà pubkey của ví đó xuất hiện trong các khóa tài khoản của giao dịch. Một trường hợp phổ biến sẽ bị bỏ sót: khi ai đó gửi token SPL (ví dụ: USDC) đế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í — một địa chỉ riêng biệt được chương trình dẫn xuất — chứ không phải chính pubkey của ví.

Do đó, gói đăng ký `accountInclude: [wallet]` thông thường sẽ không bao giờ phát hiện các giao dịch chuyển token đến. Bạn sẽ phải liệt kê trước mọi ATA thuộc sở hữu của ví và thêm từng tài khoản vào bộ lọc — nhưng ATA được tạo theo nhu cầu (mỗi mint một tài khoản), nên không thể biết trước toàn bộ tập hợp.

## Cách hoạt động của tính năng mở rộng `tokenAccounts`

Đặt `tokenAccounts` trên gói đăng ký để mở rộng phạm vi đối sánh, nhờ đó ví `accountInclude` **cũng** đối sánh với các giao dịch tương tác với tài khoản token thuộc sở hữu của ví. Việc đối sánh **dựa trên chủ sở hữu**: LaserStream phân giải các tài khoản token thuộc sở hữu của địa chỉ `accountInclude` tại thời điểm đối sánh, nên có thể phát hiện mọi tài khoản token thuộc sở hữu của ví — kể cả các tài khoản không chính tắc — chứ không chỉ địa chỉ ATA dẫn xuất. Bạn không bao giờ phải tự liệt kê các ATA.

Các gói đăng ký không có `tokenAccounts` vẫn hoạt động chính xác như trước, vì vậy bạn có thể thêm trường này vào bộ lọc hiện có một cách an toàn.

## Các chế độ mở rộng

`tokenAccounts` nhận một trong ba giá trị chuỗi sau:

| Giá trị            | Đối sánh                                                                                           | Lưu lượng                                    | Dùng cho                                                                                                           |
| ------------------ | -------------------------------------------------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `"balanceChanged"` | Các giao dịch mà số dư token thuộc sở hữu thực sự thay đổi (hoặc tài khoản token bị đóng)          | Thấp hơn — giá trị mặc định được khuyến nghị | "Thông báo cho tôi khi tiền thực sự dịch chuyển" — tiền gửi, tiền rút và giao dịch hoán đổi được quyết toán vào ví |
| `"all"`            | Mọi giao dịch tham chiếu đến tài khoản token thuộc sở hữu của ví, ngay cả khi số dư không thay đổi | Cao hơn                                      | Khả năng quan sát đầy đủ mọi hoạt động dù chỉ tương tác với tài khoản token của ví                                 |
| `"none"`           | Không mở rộng — tương đương với việc bỏ qua trường này                                             | —                                            | Giá trị mặc định                                                                                                   |

Hãy bắt đầu với `"balanceChanged"`. Chế độ này ghi nhận chuyển động thực tế của tiền với lưu lượng chỉ bằng một phần nhỏ so với `"all"`.

## Sử dụng trong `transactionSubscribe`

`tokenAccounts` là phần mở rộng của Helius cho API WebSocket Solana tiêu chuẩn. Giá trị không hợp lệ sẽ trả về lỗi JSON-RPC `-32602`: `Invalid tokenAccounts value '<x>', expected one of: none, balanceChanged, all`.

```javascript theme={"system"}
const ws = new WebSocket('wss://mainnet.helius-rpc.com/?api-key=<API_KEY>');

ws.on('open', () => {
  ws.send(JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'transactionSubscribe',
    params: [
      {
        accountInclude: ['<WALLET_PUBKEY>'],
        tokenAccounts: 'balanceChanged' // also match the wallet's ATAs
      },
      { commitment: 'confirmed', encoding: 'jsonParsed', maxSupportedTransactionVersion: 1 }
    ]
  }));
  setInterval(() => ws.ping(), 30_000);
});

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString());
  const result = msg.params?.result;
  if (!result) return;
  // Token balances this wallet owns that changed in the tx
  const owned = (result.transaction.meta.postTokenBalances || [])
    .filter((b) => b.owner === '<WALLET_PUBKEY>');
  console.log(result.signature, owned);
});
```

## Đọc nội dung đã đối sánh

Sau khi một giao dịch được đối sánh thông qua tính năng mở rộng ATA, chuyển động token của ví nằm trong `meta.postTokenBalances` và `meta.preTokenBalances` của giao dịch. Lọc các mục đó theo `owner` để tách riêng số dư thực sự thuộc sở hữu của ví, sau đó so sánh chênh lệch giữa `preTokenBalances` và `postTokenBalances` trên cùng một `accountIndex` để xem lượng token của từng mint đã dịch chuyển. Ví dụ trên minh họa bước lọc này.

## Liên quan

<CardGroup cols={2}>
  <Card title="transactionSubscribe" icon="bolt" href="/docs/vi/rpc/websocket/transaction-subscribe">
    Mọi bộ lọc và tùy chọn `transactionSubscribe`, bao gồm `tokenAccounts`.
  </Card>

  <Card title="Token Account Filtering (gRPC)" icon="coins" href="/docs/vi/laserstream/token-account-filtering">
    Tính năng mở rộng `tokenAccounts` tương tự trên các bộ lọc giao dịch gRPC của LaserStream.
  </Card>

  <Card title="WebSocket Quickstart" icon="rocket" href="/docs/vi/rpc/websocket/quickstart">
    Kết nối với WebSocket của LaserStream và truyền phát các sự kiện đầu tiên.
  </Card>
</CardGroup>
