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

# preconfSubscribe

> Используйте preconfSubscribe для потоковой передачи транзакций Solana до преобразования в shreds: предподтверждения Helius содержат статус выполнения, а предподтверждения BAM поступают до выполнения.

Запустите подписку на [Preconfirmations](/docs/ru/pre-confirmations/overview) — транзакции, доставляемые до их объединения в записи и преобразования в shreds. Это сигнал о транзакциях с минимальной задержкой, который предлагает Helius. Одна подписка передает как предподтверждения Helius, отправляемые сразу после выполнения транзакции лидером и содержащие статус ее выполнения, так и [предподтверждения BAM](/docs/ru/pre-confirmations/overview#предподтверждения-bam), отправляемые, когда валидатор обязуется выполнить транзакцию. Установите `includeBam: false`, чтобы получать только предподтверждения Helius.

## Конечные точки

`preconfSubscribe` доступен через конечную точку Helius [Gatekeeper](/docs/ru/gatekeeper/overview):

* `wss://beta.helius-rpc.com/?api-key=<API_KEY>`

Имя хоста `beta` относится к развертыванию Gatekeeper, а не к степени готовности Preconfirmations. По мере переноса трафика на Gatekeeper эта конечная точка станет стандартной.

<Note>
  Поток не является непрерывным. Покрытие зависит от доли стейка сети,
  перенаправляемой в Helius или использующей BAM, поэтому в некоторых слотах сообщений не будет — корректно
  обрабатывайте такие пропуски. См. раздел [«Покрытие»](/docs/ru/pre-confirmations/overview#охват).
</Note>

## Авторизация

<ParamField query="api-key" type="string" required>
  Ваш ключ API Helius, передаваемый в параметре запроса `api-key`. Требуется тариф Professional или выше.
</ParamField>

## Тело запроса

<ParamField body="params" type="array">
  Необязательно. Не указывайте `params`, чтобы получать каждую транзакцию как от Helius, так и от BAM. Чтобы сузить поток, передайте объект фильтра первым элементом. Фильтрация выполняется на стороне сервера, поэтому вы получаете и оплачиваете только нужные вам транзакции.

  <Expandable title="Filter" defaultOpen>
    Все поля необязательны: отсутствие поля означает «без ограничений» для соответствующего условия, поэтому пустой фильтр соответствует каждой транзакции из обоих источников. Заданные поля объединяются оператором **AND** и проверяются в следующем порядке: `includeBam` → `failed` → `regionInclude` → `signatures` → `accountExclude` → `accountRequired` → `accountInclude` → `signerExclude` → `signerInclude` → `instructions`.

    <ParamField body="includeBam" type="boolean" default="true">
      `false` исключает предподтверждения BAM, поэтому вы получаете только предподтверждения Helius. `true`, как и отсутствие этого поля, сохраняет оба источника.
    </ParamField>

    <ParamField body="failed" type="boolean">
      `true` возвращает только неуспешные (отмененные) транзакции, а `false` — только успешные. Оба значения исключают транзакции Helius с неизвестным статусом. Не указывайте поле, чтобы получать транзакции со всеми статусами. Предподтверждения с неизвестным статусом по-прежнему доставляются, если они соответствуют фильтрам источника, региона, аккаунта и подписанта.
    </ParamField>

    <ParamField body="regionInclude" type="string[]">
      Если массив не пуст, транзакция должна исходить из **одного из** этих [регионов](#коды-регионов). Если это поле задано, транзакции без сведений о регионе отбрасываются.
    </ParamField>

    <ParamField body="accountInclude" type="string[]">
      Если массив не пуст, транзакция должна ссылаться **хотя бы на один** из этих аккаунтов (публичные ключи в формате base58). Не более 10 000 записей.
    </ParamField>

    <ParamField body="accountExclude" type="string[]">
      Транзакция отбрасывается, если она ссылается **на любой** из этих аккаунтов. Имеет приоритет над `accountInclude`. Не более 10 000 записей.
    </ParamField>

    <ParamField body="accountRequired" type="string[]">
      Транзакция должна ссылаться **на все** эти аккаунты. Не более 10 000 записей.
    </ParamField>

    <ParamField body="signerInclude" type="string[]">
      Если массив не пуст, транзакция должна быть подписана **хотя бы одним** из этих аккаунтов. Не более 10 000 записей.
    </ParamField>

    <ParamField body="signerExclude" type="string[]">
      Транзакция отбрасывается, если она подписана **любым** из этих аккаунтов. Имеет приоритет над `signerInclude`. Не более 10 000 записей.
    </ParamField>

    <ParamField body="signatures" type="string[]">
      Если массив не пуст, первая подпись транзакции должна соответствовать **одной** из этих подписей в формате base58. Не более 1 000 записей.
    </ParamField>

    <ParamField body="instructions" type="object[]">
      Если массив не пуст, хотя бы одна инструкция верхнего уровня должна соответствовать **одному** из этих фильтров инструкций. Не более 16 записей.

      <Expandable title="Instruction filter">
        <ParamField body="programId" type="string" required>
          Публичный ключ в формате base58 программы, вызываемой инструкцией.
        </ParamField>

        <ParamField body="memcmp" type="object[]">
          Сравнивает декодированные байты по смещению в данных инструкции. Все записи должны совпадать. Не более четырех записей.

          Для каждой записи требуются неотрицательное значение `offset` и строка `bytes`. Необязательное поле `encoding` может иметь значение `base58`, `base64` или `hex`. По умолчанию используется `base58`. Каждое значение после декодирования должно занимать от 1 до 128 байт.
        </ParamField>

        <ParamField body="dataSize" type="number">
          Точная длина данных инструкции в байтах. Максимальное значение — 4 096 байт.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

Недопустимый публичный ключ, подпись, фильтр инструкций или код региона приводит к ошибке JSON-RPC `-32602` (недопустимые параметры). Фильтры инструкций проверяют только инструкции верхнего уровня. Они не сопоставляются с инструкциями, вызванными посредством межпрограммного вызова (CPI). Конечное смещение `memcmp` и `dataSize` не должны превышать 4 096 байт.

Фильтры аккаунтов сопоставляются не только со статическими ключами аккаунтов транзакции. Helius разрешает v0 [таблицы поиска адресов](/docs/ru/glossary#таблица-поиска-адресов-alt) на стороне сервера, поэтому `accountInclude`, `accountExclude` и `accountRequired` также сопоставляются с аккаунтами, которые транзакция загружает через ALT.

### Коды регионов

| Код | Расположение | Код | Расположение |
| - | - | - | - |
| `slc` | Солт-Лейк-Сити | `tyo` | Токио |
| `fra` | Франкфурт | `ams` | Амстердам |
| `lon` | Лондон | `dal` | Даллас |
| `pit` | Питтсбург | `dub` | Дублин |
| `sgp` | Сингапур | `mia` | Майами |
| `ewr` | Ньюарк | `lax` | Лос-Анджелес |
| `iad` | Ашберн | `sea` | Сиэтл |
| `hkg` | Гонконг | `sqq` | Шяуляй, Литва |

Для предподтверждений Helius указывается регион, в котором Helius получил транзакцию. Для предподтверждений BAM указывается региональная конечная точка BAM, отправившая предподтверждение, а не место получения транзакции системой Helius. Конечные точки BAM в Сингапуре и Далласе соответствуют `sgp` и `dal`.

## Ответ

<ResponseField name="result" type="integer">
  Идентификатор подписки (необходим для отмены подписки)
</ResponseField>

<RequestExample>
  ```json Request theme={"system"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "preconfSubscribe",
    "params": [
      {
        "failed": false,
        "regionInclude": ["ewr", "fra"],
        "accountInclude": ["9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM"]
      }
    ]
  }
  ```

  ```json Helius only theme={"system"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "preconfSubscribe",
    "params": [{ "includeBam": false }]
  }
  ```

  ```json Instruction filter theme={"system"}
  {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "preconfSubscribe",
    "params": [
      {
        "instructions": [
          {
            "programId": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
            "memcmp": [
              {
                "offset": 0,
                "bytes": "66063d1201daebea",
                "encoding": "hex"
              }
            ]
          }
        ]
      }
    ]
  }
  ```

  ```javascript JavaScript theme={"system"}
  const WebSocket = require('ws');

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

  ws.on('open', () => {
    ws.send(JSON.stringify({
      jsonrpc: '2.0',
      id: 1,
      method: 'preconfSubscribe' // Helius and BAM preconfirmations by default
      // Optional filter:
      // params: [{ failed: false, accountInclude: ['9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM'] }]
      // Helius preconfirmations only:
      // params: [{ includeBam: false }]
    }));

    setInterval(() => ws.ping(), 30_000);
  });

  ws.on('message', (data, isBinary) => {
    // The subscribe acknowledgement arrives as a JSON text frame
    if (!isBinary) {
      const msg = JSON.parse(data.toString());
      if (msg.id === 1) console.log('Subscribed, ID:', msg.result);
      return;
    }

    // Notifications arrive as binary frames:
    // version (u8) | slot (u64 LE) | tx_index (u64 LE) | status (u8) | transaction bytes
    const buf = Buffer.from(data);
    const version = buf.readUInt8(0);
    if (version !== 1) return; // unknown schema version; update your decoder
    const slot = buf.readBigUInt64LE(1);
    const txIndex = buf.readBigUInt64LE(9); // always 0 for BAM; may be 0 for other sources
    const status = buf.readUInt8(17); // 0 = failed, 1 = success, 2 = unknown
    const txBytes = buf.subarray(18); // transaction in Solana wire format (legacy, v0, or v1)

    console.log('Preconfirmation:', { slot, txIndex, status, bytes: txBytes.length });
  });
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"system"}
  { "jsonrpc": "2.0", "id": 1, "result": 24040 }
  ```

  ```text Notification (binary frame) theme={"system"}
  version   u8              payload schema version, currently 1
  slot      u64 (LE)        slot the transaction is scheduled in
  tx_index  u64 (LE)        transaction index when available (always 0 for BAM)
  status    u8              0 = failed, 1 = success, 2 = unknown
  tx        bytes           transaction in Solana wire format (legacy, v0, or v1)
  ```
</ResponseExample>

## Уведомления

После подтверждения JSON уведомления доставляются в виде **двоичных** кадров WebSocket, а не JSON. Предподтверждения Helius и BAM используют одинаковую структуру. Каждый кадр представляет собой упакованную последовательность байтов, содержащую одну транзакцию:

| Байты | Поле | Тип | Описание |
| - | - | - | - |
| 0 | `version` | `u8` | Версия схемы полезной нагрузки. Текущее значение — `1`. |
| 1–8 | `slot` | `u64` (обратный порядок байтов) | Слот, в котором запланирована транзакция. |
| 9–16 | `tx_index` | `u64` (обратный порядок байтов) | Индекс транзакции внутри слота, если он доступен. Предподтверждения BAM всегда сообщают `0`. Другие источники также могут сообщать `0`, если индекс транзакции недоступен. |
| 17 | `status` | `u8` | Статус транзакции: `0` = ошибка, `1` = успешно, `2` = неизвестно. |
| 18+ | `transaction` | `bytes` | Транзакция в сетевом формате Solana. См. раздел [«Декодирование транзакции»](#декодирование-транзакции). |

Полезная нагрузка не содержит поля источника. Не определяйте происхождение из BAM по `tx_index = 0`, поскольку другие источники также могут сообщать `0`.

<Warning>
  **Всегда сначала считывайте и проверяйте байт `version`.** Сейчас он равен `1`. Если
  Helius потребуется обновить формат полезной нагрузки, номер версии увеличится. Создайте
  отдельную ветвь обработки для каждой версии, чтобы декодер продолжал работать при изменениях схемы.
</Warning>

Предподтверждение — это ранний сигнал, а не гарантия. Транзакция еще не попала в блокчейн и все еще может завершиться ошибкой или быть отброшена. Прежде чем считать ее окончательной, подтвердите ее включение с помощью стандартных проверок уровня подтверждения.

### Декодирование транзакции

Байты транзакции пересылаются точно в том виде, в котором их сериализовал валидатор, со стандартной сетевой кодировкой для соответствующей версии транзакции. Транзакции Legacy и v0 используют структуру с подписями в начале, которую создает `bincode`. Транзакция v1 ([SIMD-0385](https://github.com/solana-foundation/solana-improvement-documents/blob/main/proposals/0385-transaction-v1.md)) использует структуру с сообщением в начале и подписями в конце, поэтому `bincode` не может обработать полезную нагрузку v1.

Используйте декодер, поддерживающий все версии. В Rust [`agave-transaction-view`](https://docs.rs/agave-transaction-view) разбирает транзакции Legacy, v0 и v1 на месте и является рекомендуемым вариантом. Также подойдет [`wincode`](https://docs.rs/wincode) с актуальным `VersionedTransaction` SDK Solana. При использовании JavaScript убедитесь, что версия вашей библиотеки поддерживает транзакции v1. Пример для Rust приведен в [руководстве](/docs/ru/pre-confirmations/preconf-subscribe#декодирование-транзакции).

## Дублирующиеся уведомления

Предподтверждения Helius и BAM дедуплицируются отдельно для каждого источника, но не между источниками. Небольшая доля транзакций достигает Helius обоими путями, поэтому вы можете дважды получить одну и ту же подпись, причем две копии могут содержать разные слоты. Выполняйте дедупликацию по подписи на стороне клиента и обеспечьте идемпотентность действий, запускаемых транзакциями. См. [руководство](/docs/ru/pre-confirmations/preconf-subscribe#дублирующиеся-уведомления).

## Стоимость

<Note>
  Минимум в 300 кредитов за слот вступает в силу **14 октября 2026 года**. До этой даты
  Preconfirmations оплачиваются из расчета 10 кредитов за сообщение без минимальной платы.
</Note>

Для Preconfirmations требуется **тариф Professional или выше**. Стоимость составляет **10 кредитов за сообщение**, при этом для каждой подписки действует **минимум в 300 кредитов за слот**. Подробности см. в разделе [«Кредиты»](/docs/ru/billing/credits).

Минимальная плата применяется только к слотам с [покрытием](/docs/ru/pre-confirmations/overview#охват) Preconfirmations. В каждом покрытом слоте за подписку списывается большая из двух сумм: 10 кредитов за каждое доставленное сообщение или 300 кредитов. Слоты без покрытия не оплачиваются. Информацию о том, какие слоты учитываются при расчете минимума, см. в разделе [«Стоимость»](/docs/ru/pre-confirmations/overview#тарификация).

| Сообщения, доставленные в покрытом слоте | Списанные кредиты |
| - | - |
| 0 | 300 |
| 10 | 300 |
| 30 | 300 |
| 100 | 1 000 |

Минимальная плата рассчитывается отдельно для каждой подписки, поэтому за каждую открытую подписку `preconfSubscribe` списывается не менее 300 кредитов за покрытый слот. Закрывайте ненужные подписки с помощью [`preconfUnsubscribe`](/docs/ru/api-reference/pre-confirmations/preconfunsubscribe).

Оплата начисляется за каждое сообщение, а не за каждую уникальную подпись. Транзакция, доставленная как Helius, так и BAM, учитывается дважды. Установите `includeBam: false`, если хотите получать только предподтверждения Helius.

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

<CardGroup cols={2}>
  <Card title="Preconfirmations Overview" icon="bolt" href="/docs/ru/pre-confirmations/overview">
    Что такое Preconfirmations и какое место они занимают в конвейере валидатора.
  </Card>

  <Card title="preconfUnsubscribe" icon="circle-stop" href="/docs/ru/api-reference/pre-confirmations/preconfunsubscribe">
    Остановите подписку по ее идентификатору.
  </Card>
</CardGroup>


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