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

# Фильтрация аккаунтов токенов (ATA) через WebSocket

> Отслеживайте входящие переводы SPL-токенов на кошелек в потоках LaserStream WebSocket с помощью фильтра tokenAccounts в transactionSubscribe — сопоставление выполняется по владельцу.

Фильтр `tokenAccounts` метода WebSocket [`transactionSubscribe`](/docs/ru/rpc/websocket/transaction-subscribe) позволяет подписке сопоставлять активность в **ассоциированных аккаунтах токенов (ATA), принадлежащих кошельку**, а не только транзакции, в которых непосредственно присутствует публичный ключ кошелька. Этот же фильтр доступен через gRPC — версию для gRPC см. в разделе [Фильтрация аккаунтов токенов (ATA)](/docs/ru/laserstream/token-account-filtering).

## Проблема: обычные фильтры аккаунтов пропускают входящие переводы токенов

При отслеживании кошелька с помощью `accountInclude: [wallet]` сопоставляются только транзакции, в ключах аккаунтов которых присутствует публичный ключ этого кошелька. При этом пропускается распространенный сценарий: когда кто-либо отправляет на кошелек SPL-токен (например, USDC), перевод затрагивает **ассоциированный аккаунт токена (ATA)** кошелька — отдельный адрес, производный от программы, — а не публичный ключ самого кошелька.

Поэтому обычная подписка `accountInclude: [wallet]` не обнаруживает входящие переводы токенов. Вам пришлось бы заранее перечислить все принадлежащие кошельку ATA и добавить каждый из них в фильтр. Однако ATA создаются по мере необходимости (по одному для каждого минта), поэтому заранее узнать их полный набор невозможно.

## Как работает расширение `tokenAccounts`

Укажите `tokenAccounts` в подписке, чтобы расширить сопоставление: тогда кошелек из `accountInclude` **также** будет соответствовать транзакциям, затрагивающим принадлежащий ему аккаунт токена. Сопоставление выполняется **по владельцу**: LaserStream во время сопоставления определяет аккаунты токенов, принадлежащие адресам из `accountInclude`. Поэтому фильтр обнаруживает любой принадлежащий кошельку аккаунт токена, включая неканонические, а не только производный адрес ATA. Вам не нужно самостоятельно перечислять ATA.

Подписки без `tokenAccounts` работают точно так же, как раньше, поэтому этот параметр можно безопасно добавить в существующий фильтр.

## Режимы расширения

`tokenAccounts` принимает одно из трех строковых значений:

| Значение | Что сопоставляется | Объем | Когда использовать |
| - | - | - | - |
| `"balanceChanged"` | Транзакции, в которых баланс принадлежащего кошельку токена фактически изменился (или соответствующий аккаунт токена был закрыт) | Ниже — рекомендуемый вариант по умолчанию | «Сообщать, когда средства действительно перемещаются» — пополнения, выводы и свопы, средства от которых поступают на кошелек |
| `"all"` | Любая транзакция, ссылающаяся на принадлежащий кошельку аккаунт токена, даже если баланс не изменился | Выше | Полная видимость всего, что каким-либо образом затрагивает аккаунты токенов кошелька |
| `"none"` | Без расширения — аналогично отсутствию этого поля | — | Значение по умолчанию |

Начните с `"balanceChanged"`. Этот режим обнаруживает реальное перемещение средств, создавая лишь малую долю объема `"all"`.

## Использование в `transactionSubscribe`

`tokenAccounts` — это расширение Helius для стандартного API Solana WebSocket. При недопустимом значении возвращается ошибка 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);
});
```

## Анализ результатов сопоставления

После сопоставления транзакции через расширение ATA перемещение токенов кошелька отображается в полях транзакции `meta.postTokenBalances` и `meta.preTokenBalances`. Отфильтруйте эти записи по `owner`, чтобы выделить балансы, которые действительно принадлежат вашему кошельку. Затем сравните `preTokenBalances` с `postTokenBalances` для одного и того же `accountIndex`, чтобы определить изменение количества каждого минтируемого токена. В примере выше показан этот этап фильтрации.

## Связанные материалы

<CardGroup cols={2}>
  <Card title="transactionSubscribe" icon="bolt" href="/docs/ru/rpc/websocket/transaction-subscribe">
    Все фильтры и параметры `transactionSubscribe`, включая `tokenAccounts`.
  </Card>

  <Card title="Token Account Filtering (gRPC)" icon="coins" href="/docs/ru/laserstream/token-account-filtering">
    Такое же расширение `tokenAccounts` для фильтров транзакций LaserStream gRPC.
  </Card>

  <Card title="WebSocket Quickstart" icon="rocket" href="/docs/ru/rpc/websocket/quickstart">
    Подключитесь к LaserStream WebSocket и запустите потоковую передачу первых событий.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.