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

# Solana 履歴アカウント API（ベータ版）

> Helius の getHistoricalAccountInfo と getHistoricalTokenAccountsByOwner（ベータ版）を使用して、過去の任意のスロットまたはトランザクション時点の Solana アカウント状態を読み取ります。

> [!NOTE]
>
> 履歴アカウント状態はベータ版です。パラメータ、料金、レスポンス形式、データ対象範囲は変更される可能性があります。

## 履歴アカウント状態とは？

`getAccountInfo` や `getTokenAccountsByOwner` などの標準 Solana RPC メソッドは、アカウントの現在の状態のみを返します。バリデータは各アカウントの最新バージョンのみを保持するため、書き込みのたびに以前の状態が置き換えられます。トランザクション履歴でもこの不足は補えません。`getTransaction` と `getBlock` が返すのは命令、ログ、残高の変更であり、プログラムが書き込んだアカウントデータではありません。

Helius の履歴アカウントメソッドは、過去のスロット時点、またはそのスロット内の特定のトランザクション直後のアカウントを返します。同じスロット内の 2 つのトランザクション間の状態を読み取れるため、1 つのスロット内でアカウントが何度も書き込まれた場合でも、1 つのトランザクションによる変更を正確に確認できます。次の用途に使用できます。

* 監査、会計、税務申告のために、特定時点でのウォレットのトークン残高を確認する
* トランザクションの実行直前と直後に、そのトランザクションが操作したアカウントを読み取り、デバッグする
* 台帳を自分でリプレイせずに、過去のスロット時点におけるプール、ボールト、オラクルなどのプロトコルアカウントを読み取る

これらは Helius 専用の RPC メソッドです。標準の Solana RPC には含まれていません。

## どのメソッドを使用すべきですか？

| 必要なもの | 使用するメソッド | 戻り値 |
| - | - | - |
| 過去の位置における 1 つのアカウント | [`getHistoricalAccountInfo`](https://www.helius.dev/docs/ja/api-reference/rpc/http/gethistoricalaccountinfo) | アカウント。存在しなかった場合は `null` |
| 過去の位置におけるウォレットのトークンアカウント | [`getHistoricalTokenAccountsByOwner`](https://www.helius.dev/docs/ja/api-reference/rpc/http/gethistoricaltokenaccountsbyowner) | SPL Token および Token-2022 アカウントの 1 ページ分。必要に応じて 1 つのミントに限定可能 |

どちらも同じ 3 つのパラメータを受け取ります。アドレス、履歴内の位置を選択するクエリオブジェクト、設定オブジェクトです。

## 提供状況と料金

* **プラン**: Business [プラン](https://www.helius.dev/docs/ja/billing/plans.md)以上。
* **コスト**: ベータ期間中は 1 回の呼び出しにつき 0 クレジット（料金は変更される可能性があります）。
* **レート制限**: `getHistoricalAccountInfo` は 1 秒あたり 100 リクエスト、最大バースト 100 です。`getHistoricalTokenAccountsByOwner` は 1 秒あたり 10 リクエスト、最大バースト 10 です。これらの制限はプランの RPC レート制限とは別であり、超過したリクエストには HTTP `429` が返されます。[レート制限](https://www.helius.dev/docs/ja/billing/rate-limits.md)を参照してください。
* **ネットワーク**: Mainnet のみ。標準の Mainnet エンドポイント `https://mainnet.helius-rpc.com`、または [Gatekeeper](https://www.helius.dev/docs/ja/gatekeeper/overview.md) エンドポイント `https://beta.helius-rpc.com` で呼び出してください。Devnet ではエラー `-32601` が返されます。

## データ対象範囲

履歴はスロット 444,959,999（2026 年 9 月 7 日）以降で利用できます。これはエポック 1029 の最後のスロットであるため、エポック 1030 の開始時点の状態を保持しています。それより前のスロットに対するリクエストでは、エラー `-32018`（「Account history not available」）が返されます。

## 履歴内の位置を選択する

2 番目のパラメータは、2 つの省略可能なフィールド `slot` と `transactionIndex` を持つクエリオブジェクトです。

| クエリ | 返される状態 |
| - | - |
| 省略、または `{}` | リクエストしたコミットメントを上限とする、インデックス作成済みの最新スロット時点 |
| `{ "slot": 445000000 }` | すべてのトランザクションと、エポック報酬などのトランザクション外の書き込みが完了した後の、スロット 445,000,000 の終了時点 |
| `{ "slot": 445000000, "transactionIndex": 10 }` | スロット 445,000,000 のインデックス 10 にあるトランザクションの実行直後 |

`transactionIndex` には `slot` が必要です。

エポック報酬などのトランザクション外の書き込みは、スロットの終了時に適用されます。`transactionIndex` を指定したクエリには、スロット内の最後のトランザクションを指定した場合でも、これらは含まれません。含めるには、`transactionIndex` を指定せずに `slot` をクエリしてください。

### トランザクションの前後の状態を読み取る

トランザクションによる変更を調べるには、アカウントを 2 回読み取ります。

* **トランザクション後**: そのトランザクション自体の `slot` と `transactionIndex` をクエリします。
* **トランザクション前**: 同じ `slot` を、`transactionIndex` から 1 を引いた値でクエリします。トランザクションがスロット内の最初（インデックス 0）の場合は、`transactionIndex` を指定せずに前のスロットをクエリします。

[`getTransactionsForAddress`](https://www.helius.dev/docs/ja/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 のクエリに対して、スロット 444,999,837 のインデックス 700 にあるトランザクションが最後に書き込んだ状態が返されています。
* **`transactionIndex: null`** は、エポック報酬など、書き込みがトランザクション外で発生したことを意味します。
* **`transactionIndex: null` を伴う `slot: 444959999`** は、履歴対象範囲の開始以降、アカウントが変更されていないことを意味します。そのスロットでアカウントが書き込まれたという意味ではありません。

## null 値の意味

クエリした位置にアカウントが存在しなかった場合、`value` は `null` になります。その時点でまだ作成されていなかったか、すでに閉じられていたかのいずれかです。

* **`null` レスポンスには `lastUpdatedAt` がありません**。そのため、アカウントがいつ作成または閉鎖されたかは分かりません。該当するトランザクションを見つけるには、[`getTransactionsForAddress`](https://www.helius.dev/docs/ja/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/ja/rpc/gettransactionsforaddress) と `sortOrder: "asc"` を使用して、アカウントのトランザクションを古い順に一覧表示します。次に、各トランザクションの `slot` と `transactionIndex` における状態を読み取ります。

## レスポンスコンテキスト

各レスポンスの `context.slot` は、リクエストの処理時に Helius がインデックスを作成済みだった最新スロットです。クエリしたスロットではありません。受け取ったデータを判断するには、リクエスト内の `slot`、または `lastUpdatedAt` を使用してください。

## 一貫性を保ってページネーションする

`getHistoricalTokenAccountsByOwner` は、結果を 1 ページずつ返します。各レスポンスには `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 アカウントの状態を取得するにはどうすればよいですか？

アドレスと `{ "slot": S }` を指定して `getHistoricalAccountInfo` を呼び出します。スロット S の終了時点におけるアカウントが、`getAccountInfo` と同じ形式で返されます。

### 同じスロット内の 2 つのトランザクション間でアカウントを読み取れますか？

はい。クエリに `transactionIndex` を追加すると、そのトランザクションの実行直後におけるアカウントの状態を取得できます。[トランザクションの前後の状態を読み取る](#トランザクションの前後の状態を読み取る)を参照してください。

### どこまで過去に遡ってクエリできますか？

履歴は 2026 年 9 月 7 日のスロット 444,959,999 から始まります。それより前のスロットでは、エラー `-32018` が返されます。

### 履歴アカウントメソッドを利用できるプランはどれですか？

Business プラン以上です。ベータ期間中の呼び出しは 0 クレジットですが、料金は変更される可能性があります。これらのメソッドは Mainnet でのみ利用できます。

### レート制限はいくつですか？

`getHistoricalAccountInfo` は 1 秒あたり 100 リクエスト、`getHistoricalTokenAccountsByOwner` は 1 秒あたり 10 リクエストまで許可されます。どちらの制限も、プランの RPC レート制限とは別です。[提供状況と料金](#提供状況と料金)を参照してください。

### アカウントの過去のすべての状態を取得するにはどうすればよいですか？

`lastUpdatedAt` を使用して、1 つの書き込みから前の書き込みへと遡ります。[アカウント履歴を遡る](#アカウント履歴を遡る)を参照してください。

### 新しい SDK は必要ですか？

いいえ。これらは JSON-RPC メソッドなので、任意の HTTP クライアントを使用できます。標準の Solana クライアントライブラリには含まれていないため、上の例のようにリクエストを直接送信してください。

## 次のステップ

> [card] [getHistoricalAccountInfo](https://www.helius.dev/docs/ja/api-reference/rpc/http/gethistoricalaccountinfo.md)
>
> 過去のスロットまたはトランザクション時点の 1 つのアカウントを読み取ります

> [card] [getHistoricalTokenAccountsByOwner](https://www.helius.dev/docs/ja/api-reference/rpc/http/gethistoricaltokenaccountsbyowner.md)
>
> 過去のスロット時点におけるウォレットのトークンアカウントを一覧表示します

> [card] [getTransactionsForAddress](https://www.helius.dev/docs/ja/rpc/gettransactionsforaddress.md)
>
> 調査するトランザクションのスロットと transactionIndex を確認します

> [card] [Historical data overview](https://www.helius.dev/docs/ja/rpc/historical-data.md)
>
> トランザクション履歴、送金、その他のアーカイブメソッドを確認します


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