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

# Отслеживание свопов Jupiter с помощью Parsed Streams

> Создайте фильтр Parsed Streams для инструкций маршрутов Jupiter с помощью describeProgram и подпишитесь на него.

В этом руководстве вы шаг за шагом создадите реальный фильтр для отслеживания свопов Jupiter выбранного кошелька. Используйте [обнаружение программ](/docs/ru/parsed-streams/quickstart#обнаружение), чтобы проверить правильность фильтра до открытия подписки.

<Steps>
  <Step title="Look Up the Program">
    Угаданные имена инструкций — самая распространенная причина того, что фильтр неявно не находит совпадений. Сначала вызовите `describeProgram`, чтобы получить точные имена, с которыми выполняется сопоставление. Сейчас этот метод доступен только на `wss://fs-beta.helius-rpc.com/?api-key=<API_KEY>`, поэтому отправляйте запрос туда, а не через подключение подписки.

    ```json Request theme={"system"}
    { "jsonrpc": "2.0", "id": 1, "method": "describeProgram", "params": [{ "program": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4" }] }
    ```

    ```json Response theme={"system"}
    {
      "jsonrpc": "2.0", "id": 1,
      "result": {
        "id": "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
        "name": "jupiter",
        "instructions": ["route", "shared_accounts_route", "exact_out_route"],
        "events": ["SwapEvent"],
        "roles": ["user_transfer_authority", "destination_token_account"]
      }
    }
    ```

    Используйте **адрес** программы вместо имени из каталога: несколько записей каталога могут иметь одинаковое имя, а поиск по имени может вернуть более старую версию программы. `route` и `shared_accounts_route` — две инструкции, охватывающие большинство свопов Jupiter v6, поэтому фильтр будет настроен на них.
  </Step>

  <Step title="Build the Filter">
    Объедините идентификатор программы, имена инструкций из предыдущего шага и отслеживаемый кошелек. Поля объединяются оператором AND, поэтому фильтр находит инструкции маршрута, в которых задействован SOL-счет кошелька:

    ```json theme={"system"}
    {
      "programs": ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
      "instructionNames": ["route", "shared_accounts_route"],
      "accounts": {
        "include": ["So11111111111111111111111111111111111111112"],
        "roles": { "user_transfer_authority": "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin" }
      },
      "includeFailed": false,
      "includeCpi": true
    }
    ```

    `accounts.roles` привязывает `user_transfer_authority` к точной позиции кошелька в инструкции. Это условие строже, чем использование одного `accounts.include`: простое сопоставление по адресу также находило бы кошелек, указанный в инструкции в качестве другого, не связанного с ним счета. Имена ролей должны совпадать точно, поэтому они скопированы из списка `roles`, возвращаемого `describeProgram`, а не подобраны приблизительно. Оставьте `includeCpi: true` со значением по умолчанию: фактические перемещения токенов при свопе происходят во внутренних инструкциях.
  </Step>

  <Step title="Subscribe and Handle Notifications">
    Откройте подписку с этим фильтром, а затем считывайте декодированные аргументы каждой совпавшей инструкции:

    ```typescript theme={"system"}
    import WebSocket from "ws";

    const ws = new WebSocket("wss://beta.helius-rpc.com/?api-key=<API_KEY>");

    const filter = {
      programs: ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
      instructionNames: ["route", "shared_accounts_route"],
      accounts: {
        include: ["So11111111111111111111111111111111111111112"],
        roles: { user_transfer_authority: "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin" },
      },
      includeFailed: false,
      includeCpi: true,
    };

    ws.on("open", () => {
      ws.send(JSON.stringify({
        jsonrpc: "2.0",
        id: 1,
        method: "parsedTransactionSubscribe",
        params: [filter, { commitment: "confirmed", details: "full" }],
      }));
    });

    ws.on("message", (data) => {
      const msg = JSON.parse(data.toString());
      if (msg.method === "parsedTransactionNotification") {
        const { transaction, instructions, matchedIndexes } = msg.params.result.value;
        for (const i of matchedIndexes) {
          const ix = instructions[i];
          if (!ix.decoded) continue;
          console.log(transaction.signature, ix.decoded.args.in_amount, ix.decoded.args.slippage_bps);
        }
      }
    });
    ```

    `matchedIndexes` указывает только на инструкции, совпавшие с фильтром. Пропускайте все остальные инструкции транзакции. Перед чтением убедитесь, что поле `decoded` присутствует: инструкция маршрута из неиндексированной версии программы вместо него поступает с `decoded: null` и необработанными полями.
  </Step>
</Steps>

## Дальнейшие действия

<CardGroup cols={2}>
  <Card title="Filter Fields Reference" icon="filter" href="/docs/ru/parsed-streams/quickstart#поля-фильтра">
    Все поля, параметры и ограничения фильтра.
  </Card>

  <Card title="Handling Reconnects" icon="rotate" href="/docs/ru/parsed-streams/guides/handling-reconnects">
    Поддерживайте эту подписку при разрывах соединения и развертываниях.
  </Card>
</CardGroup>


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