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

# API исторических состояний аккаунтов Solana (бета-версия)

> Получайте состояние аккаунта Solana на момент любого прошлого слота или транзакции с помощью методов Helius getHistoricalAccountInfo и getHistoricalTokenAccountsByOwner (бета-версия).

> [!NOTE]
>
> Исторические состояния аккаунтов доступны в бета-версии. Параметры, цены, форматы ответов и охват данных могут измениться.

## Что такое историческое состояние аккаунта?

Стандартные методы RPC Solana, такие как `getAccountInfo` и `getTokenAccountsByOwner`, возвращают только текущее состояние аккаунта. Валидаторы хранят только последнюю версию каждого аккаунта, поэтому каждая запись заменяет предыдущую. История транзакций не восполняет этот пробел: `getTransaction` и `getBlock` возвращают инструкции, журналы и изменения баланса, но не данные аккаунта, записанные программой.

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

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

Эти методы RPC доступны только в Helius. Они не входят в стандартный RPC Solana.

## Какой метод использовать?

| Что вам нужно | Используйте | Результат |
| - | - | - |
| Один аккаунт в прошлой позиции | [`getHistoricalAccountInfo`](https://www.helius.dev/docs/ru/api-reference/rpc/http/gethistoricalaccountinfo) | Аккаунт или `null`, если он не существовал |
| Аккаунты токенов кошелька в прошлой позиции | [`getHistoricalTokenAccountsByOwner`](https://www.helius.dev/docs/ru/api-reference/rpc/http/gethistoricaltokenaccountsbyowner) | Страница аккаунтов SPL Token и Token-2022, при необходимости для одного минта |

Оба метода принимают одинаковые три параметра: адрес, объект запроса, выбирающий позицию в истории, и объект конфигурации.

## Доступность и цены

* **Тарифы**: Business и более высокие [тарифы](https://www.helius.dev/docs/ru/billing/plans.md).
* **Стоимость**: 0 кредитов за вызов в период бета-тестирования (цены могут измениться).
* **Ограничения частоты запросов**: `getHistoricalAccountInfo` допускает 100 запросов в секунду с максимальным всплеском до 100. `getHistoricalTokenAccountsByOwner` допускает 10 запросов в секунду с максимальным всплеском до 10. Эти ограничения не зависят от ограничения частоты RPC-запросов вашего тарифа. При их превышении запросы возвращают HTTP `429`. См. [ограничения частоты запросов](https://www.helius.dev/docs/ru/billing/rate-limits.md).
* **Сеть**: только Mainnet. Вызывайте методы через стандартную конечную точку Mainnet `https://mainnet.helius-rpc.com` или конечную точку [Gatekeeper](https://www.helius.dev/docs/ru/gatekeeper/overview.md) `https://beta.helius-rpc.com`. Devnet возвращает ошибку `-32601`.

## Охват данных

История доступна начиная со слота 444,959,999 (7 сентября 2026 года). Это последний слот эпохи 1029, поэтому в нем хранится состояние на начало эпохи 1030. Запросы более ранних слотов возвращают ошибку `-32018` ("История аккаунта недоступна").

## Выбор позиции в истории

Второй параметр — объект запроса с двумя необязательными полями: `slot` и `transactionIndex`:

| Запрос | Возвращаемое состояние |
| - | - |
| Не указано или `{}` | В последнем проиндексированном слоте с учетом запрошенного уровня подтверждения |
| `{ "slot": 445000000 }` | В конце слота 445,000,000, после всех транзакций и записей вне транзакций, например вознаграждений за эпоху |
| `{ "slot": 445000000, "transactionIndex": 10 }` | Сразу после выполнения транзакции с индексом 10 в слоте 445,000,000 |

Для `transactionIndex` требуется `slot`.

Записи вне транзакций, например вознаграждения за эпоху, применяются в конце слота. Запрос с `transactionIndex` никогда не включает их, даже для последней транзакции в слоте. Чтобы включить их, запросите `slot` без `transactionIndex`.

### Чтение состояния до и после транзакции

Чтобы проверить, что изменила транзакция, прочитайте аккаунт дважды:

* **После транзакции**: укажите в запросе ее собственные `slot` и `transactionIndex`.
* **До транзакции**: укажите в запросе тот же `slot` и значение `transactionIndex`, уменьшенное на 1. Если транзакция была первой в слоте (индекс 0), запросите предыдущий слот без `transactionIndex`.

[`getTransactionsForAddress`](https://www.helius.dev/docs/ru/rpc/gettransactionsforaddress) возвращает `slot` и `transactionIndex` для каждой транзакции, поэтому вы можете найти в нем позицию транзакции и напрямую передать ее этим методам.

```bash theme={"system"}
# State of the account right after the transaction at index 10 in slot 445000000
curl https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "getHistoricalAccountInfo",
    "params": [
      "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      { "slot": 445000000, "transactionIndex": 10 },
      { "encoding": "jsonParsed" }
    ]
  }'
```

## Описание lastUpdatedAt

Каждый возвращенный аккаунт содержит `lastUpdatedAt` — позицию записи, создавшей полученное вами состояние:

```json theme={"system"}
"lastUpdatedAt": { "slot": 444999837, "transactionIndex": 700 }
```

* **`slot` и `transactionIndex`** указывают на последнюю запись в запрошенной позиции или перед ней. В приведенном выше примере запрос для слота 445,000,000 вернул состояние, которое в последний раз было записано транзакцией с индексом 700 в слоте 444,999,837.
* **`transactionIndex: null`** означает, что запись была выполнена вне транзакции, например при начислении вознаграждений за эпоху.
* **`slot: 444959999` с `transactionIndex: null`** означает, что аккаунт не менялся с начала охвата истории. Это не означает, что аккаунт был записан в этом слоте.

## Что означает значение null

`value` имеет значение `null`, если аккаунт не существовал в запрошенной позиции. Он либо еще не был создан, либо уже был закрыт.

* **Ответ с `null` не содержит `lastUpdatedAt`**, поэтому по нему нельзя определить, когда аккаунт был создан или закрыт. Чтобы найти эти транзакции, используйте [`getTransactionsForAddress`](https://www.helius.dev/docs/ru/rpc/gettransactionsforaddress).
* **Адрес, который никогда не существовал**, также возвращает `null`, а не ошибку.
* **Слот до начала охвата истории** возвращает ошибку `-32018` для любого адреса независимо от того, существовал аккаунт или нет.

## Обход истории аккаунта в обратном порядке

Используйте `lastUpdatedAt` как курсор, чтобы получить список всех состояний аккаунта, начиная с самого нового. После каждого чтения запрашивайте позицию непосредственно перед полученной записью:

| Полученное значение `lastUpdatedAt` | Следующий запрос |
| - | - |
| `{ "slot": S, "transactionIndex": N }`, где N больше 0 | `{ "slot": S, "transactionIndex": N - 1 }` |
| `{ "slot": S, "transactionIndex": 0 }` | `{ "slot": S - 1 }` |
| `{ "slot": S, "transactionIndex": null }` | `{ "slot": S - 1 }` |

Остановитесь, когда `value` получит значение `null`. Это означает, что запись, перед которой вы только что перешли, создала аккаунт. Также остановитесь, когда `lastUpdatedAt.slot` достигнет 444,959,999 — начала охвата истории.

```typescript theme={"system"}
const url = `https://mainnet.helius-rpc.com/?api-key=${process.env.HELIUS_API_KEY}`;
const COVERAGE_START_SLOT = 444959999;

type Position = { slot?: number; transactionIndex?: number };

async function getAccountHistory(address: string, start: Position = {}, maxStates = 100) {
  const states = [];
  let position = start;

  while (states.length < maxStates) {
    const response = await fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: "1",
        method: "getHistoricalAccountInfo",
        params: [address, position, { encoding: "base64" }],
      }),
    });
    const { result, error } = await response.json();
    if (error) throw new Error(`${error.code}: ${error.message}`);

    const account = result.value;
    if (!account) break; // The account didn't exist before this write

    states.push(account);
    const { slot, transactionIndex } = account.lastUpdatedAt;
    if (slot <= COVERAGE_START_SLOT) break; // Reached the start of history coverage

    // Step to the position just before this write
    position = transactionIndex ? { slot, transactionIndex: transactionIndex - 1 } : { slot: slot - 1 };
  }

  return states; // Newest first
}
```

* **Аккаунты, закрытые в настоящее время**, возвращают `null` в последнем слоте. Передайте позицию `start`, относящуюся к моменту, когда аккаунт еще существовал.
* **Записи вне транзакций** переводят курсор к предыдущему слоту. Если тот же аккаунт ранее в этом слоте также был записан транзакцией, обход пропустит это состояние.
* **Чтобы выполнить обход вперед во времени**, получите список транзакций аккаунта от самых старых к самым новым с помощью [`getTransactionsForAddress`](https://www.helius.dev/docs/ru/rpc/gettransactionsforaddress) и `sortOrder: "asc"`. Затем считайте состояние в `slot` и `transactionIndex` каждой транзакции.

## Контекст ответа

`context.slot` в каждом ответе — это последний слот, проиндексированный Helius на момент обработки запроса. Это не запрошенный вами слот. Чтобы анализировать полученные данные, используйте `slot` из запроса или `lastUpdatedAt`.

## Согласованная пагинация

`getHistoricalTokenAccountsByOwner` возвращает результаты постранично. Каждый ответ содержит `value.accounts` и `value.paginationKey`.

* **Передайте `paginationKey` обратно** в объекте конфигурации, чтобы получить следующую страницу.
* **Останавливайтесь только тогда, когда `paginationKey` имеет значение `null`.** Страница может быть неполной или пустой, но после нее могут оставаться дополнительные результаты.
* **Зафиксируйте `slot` для всех страниц.** Если не указать `slot`, каждая страница будет считывать последний проиндексированный слот, поэтому страницы могут относиться к разным моментам времени.
* **Задайте `limit`** в диапазоне от 1 до 5 000. Значение по умолчанию — 5 000.

## Кодировки и разобранные данные

* **Поддерживаемые кодировки**: `base64` (по умолчанию), `base64+zstd` и `jsonParsed`. `base58` и `binary` не поддерживаются.
* **Аккаунты токенов `jsonParsed`** используют количество десятичных разрядов минта в запрошенной позиции, поэтому суммы остаются корректными, даже если с тех пор минт изменился. Если минт невозможно прочитать в этой позиции, аккаунт возвращается в формате base64.
* **`dataSlice`** работает так же, как в `getAccountInfo`.

## Уровень подтверждения

`commitment` принимает `finalized` (по умолчанию) и `confirmed`. `processed` не поддерживается. Если `slot` новее, чем допускает запрошенный уровень подтверждения, возвращается ошибка `-32004`.

## Ошибки

| Код | Значение | Что делать |
| - | - | - |
| `-32018` | Слот находится до начала охвата истории | Запросите слот 444,959,999 или более поздний |
| `-32004` | Слот новее, чем допускает запрошенный уровень подтверждения | Используйте `confirmed` или запросите более старый слот |
| `-32602` | Недопустимые параметры | Проверьте сообщение об ошибке, чтобы определить конкретное поле |
| `-32601` | Метод не найден | Используйте конечную точку Helius Mainnet или Gatekeeper. Методы исторических состояний аккаунтов недоступны в Devnet |

## Часто задаваемые вопросы

### Как получить состояние аккаунта Solana в определенном слоте?

Вызовите `getHistoricalAccountInfo`, передав адрес и `{ "slot": S }`. Метод вернет аккаунт в том виде, в котором он находился в конце слота S, в том же формате, что и `getAccountInfo`.

### Можно ли прочитать аккаунт между двумя транзакциями в одном слоте?

Да. Добавьте `transactionIndex` в запрос, чтобы получить состояние аккаунта сразу после выполнения этой транзакции. См. [Чтение состояния до и после транзакции](#чтение-состояния-до-и-после-транзакции).

### Насколько далеко в прошлое можно выполнять запросы?

История начинается со слота 444,959,999 от 7 сентября 2026 года. Для более ранних слотов возвращается ошибка `-32018`.

### Какие тарифы включают методы исторических состояний аккаунтов?

Тариф Business и более высокие. В период бета-тестирования вызовы стоят 0 кредитов. Цены могут измениться. Методы доступны только в Mainnet.

### Каковы ограничения частоты запросов?

`getHistoricalAccountInfo` допускает 100 запросов в секунду, а `getHistoricalTokenAccountsByOwner` — 10 запросов в секунду. Оба ограничения не зависят от ограничения частоты RPC-запросов вашего тарифа. См. [Доступность и цены](#доступность-и-цены).

### Как получить все прошлые состояния аккаунта?

Переходите назад от одной записи к предыдущей с помощью `lastUpdatedAt`. См. [Обход истории аккаунта в обратном порядке](#обход-истории-аккаунта-в-обратном-порядке).

### Нужен ли новый SDK?

Нет. Это методы JSON-RPC, поэтому подойдет любой HTTP-клиент. Стандартные клиентские библиотеки Solana не включают эти методы, поэтому отправляйте запрос напрямую, как в примерах выше.

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

> [card] [getHistoricalAccountInfo](https://www.helius.dev/docs/ru/api-reference/rpc/http/gethistoricalaccountinfo.md)
>
> Получите один аккаунт в прошлом слоте или транзакции

> [card] [getHistoricalTokenAccountsByOwner](https://www.helius.dev/docs/ru/api-reference/rpc/http/gethistoricaltokenaccountsbyowner.md)
>
> Получите список аккаунтов токенов кошелька в прошлом слоте

> [card] [getTransactionsForAddress](https://www.helius.dev/docs/ru/rpc/gettransactionsforaddress.md)
>
> Найдите слот и transactionIndex транзакций, которые хотите проверить

> [card] [Historical data overview](https://www.helius.dev/docs/ru/rpc/historical-data.md)
>
> История транзакций, переводы и другие архивные методы


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