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

# getHistoricalTokenAccountsByOwner

> 列出 Solana 钱包在过去某个时隙或特定交易执行后拥有的 SPL Token 和 Token-2022 账户，支持铸币筛选和分页。

> [!NOTE]
>
> `getHistoricalTokenAccountsByOwner` 目前处于 Beta 阶段。参数、定价、响应格式和数据覆盖范围可能会发生变化。

## 概述

`getHistoricalTokenAccountsByOwner` 返回钱包在过去某个时隙拥有的 SPL Token 和 Token-2022 账户，或该时隙中特定交易执行后立即呈现的账户。这是 Helius 独有的 RPC 方法。标准 `getTokenAccountsByOwner` 仅返回当前状态。

使用 `jsonParsed` 编码时，代币数量会采用每个铸币在请求位置时的小数位数，因此余额反映钱包在该时间点持有的数量。

历史数据从时隙 444,959,999（2026 年 9 月 7 日）开始提供，该时隙对应纪元 1030 开始时的状态。

`getHistoricalTokenAccountsByOwner` 可在主网的 Business 及更高级别套餐中使用，Beta 期间每次调用消耗 0 个额度。定价可能会发生变化。

## 与 getTokenAccountsByOwner 的区别

* **铸币或程序筛选条件为可选项。** 不设置筛选条件时，你会获得钱包拥有的所有代币账户。若要缩小结果范围，请在配置对象（第三个参数）中设置 `mint` 或 `programId`，但不能同时设置两者。
* **第二个参数是查询对象**，用于选择历史记录中的位置，而不是铸币或程序筛选条件。
* **`result.value` 是一个对象**，包含 `accounts` 和 `paginationKey`，而不是数组。

## 选择历史记录中的位置

第二个参数是查询对象：

* **省略或设为 `{}`**：最新的已索引时隙，但不超过所请求确认级别允许的范围。
* **`{ "slot": 445000000 }`**：时隙 445,000,000 结束时。
* **`{ "slot": 445000000, "transactionIndex": 10 }`**：该时隙中索引为 10 的交易执行后立即呈现的状态。

有关位置的工作原理，请参阅[历史账户指南](https://www.helius.dev/docs/zh/rpc/historical-accounts.md)。

## 请求示例

此请求返回钱包在时隙 445,000,000 结束时的 USDC 代币账户：

```bash theme={"system"}
curl https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": "1",
    "method": "getHistoricalTokenAccountsByOwner",
    "params": [
      "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
      { "slot": 445000000 },
      { "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", "encoding": "jsonParsed" }
    ]
  }'
```

## 分页获取所有代币账户

结果先按铸币排序，再按代币账户地址排序。每个响应都会返回 `value.accounts` 和 `value.paginationKey`，后者是格式为 `<mint>:<tokenAccount>` 的游标。将其传入下一个请求，直到它变为 `null`。

> [!WARNING]
>
> 即使某一页的结果很少甚至为空，也可能仍包含 `paginationKey`。只有当 `paginationKey` 为 `null` 时，才表示已到达末尾。

分页时，请始终显式传入 `slot`。如果省略，每一页都会读取最新的已索引时隙，因此不同页面的数据可能来自不同时间点。

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

async function getTokenAccountsAt(owner: string, slot: number) {
  const accounts = [];
  let paginationKey: string | null = null;

  do {
    const response = await fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: "1",
        method: "getHistoricalTokenAccountsByOwner",
        params: [
          owner,
          { slot },
          { encoding: "jsonParsed", limit: 1000, ...(paginationKey && { paginationKey }) },
        ],
      }),
    });
    const { result, error } = await response.json();
    if (error) throw new Error(`${error.code}: ${error.message}`);

    accounts.push(...result.value.accounts);
    paginationKey = result.value.paginationKey;
  } while (paginationKey);

  return accounts;
}

const tokenAccounts = await getTokenAccountsAt("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY", 445000000);
```

## 读取响应

`value.accounts` 中的每个条目都包含代币账户的 `pubkey` 和一个 `account` 对象。该账户对象包含与 `getAccountInfo` 相同的字段，并额外包含 `lastUpdatedAt`：

* **`lastUpdatedAt.slot`** 和 **`lastUpdatedAt.transactionIndex`** 标识生成此状态的写入操作。
* **`lastUpdatedAt.slot` 为 444,959,999 且 `transactionIndex` 为 `null`**，表示自历史数据覆盖开始以来，该代币账户一直没有变化。
* **`context.slot`** 是 Helius 处理请求时已索引的最新时隙，而不是你查询的时隙。

## 错误

| 代码 | 含义 |
| - | - |
| `-32018` | 该时隙早于历史数据覆盖的起始位置（时隙 444,959,999） |
| `-32004` | 该时隙比所请求确认级别允许的范围更新。请使用 `confirmed` 或查询更早的时隙 |
| `-32602` | 参数无效，例如同时设置 `mint` 和 `programId`、`programId` 不是代币程序，或 `paginationKey` 中的铸币与 `mint` 不匹配 |
| `-32601` | 找不到方法。请调用你的 Helius 主网或 Gatekeeper 端点；该方法在开发网上不可用 |

## 相关方法

> [card] [Historical Accounts Guide](https://www.helius.dev/docs/zh/rpc/historical-accounts.md)
>
> 了解历史账户方法中的位置、数据覆盖范围和 lastUpdatedAt 的工作原理

> [card] [getHistoricalAccountInfo](https://www.helius.dev/docs/zh/api-reference/rpc/http/gethistoricalaccountinfo.md)
>
> 读取单个账户在过去某个时隙的状态

> [card] [getTransactionsForAddress](https://www.helius.dev/docs/zh/rpc/gettransactionsforaddress.md)
>
> 查找要检查的交易对应的时隙和 transactionIndex

> [card] [getTokenAccountsByOwnerV2](https://www.helius.dev/docs/zh/api-reference/rpc/http/gettokenaccountsbyownerv2.md)
>
> 分页获取钱包当前的代币账户

## 请求参数

**owner** `string` *required*

拥有这些代币账户的钱包的 Base-58 编码地址。请传入所有者钱包，而不是代币账户。

**slot** `number`

要读取状态的时隙。返回该时隙结束时的账户状态。最早支持的时隙是 444959999，即纪元 1030 开始时的状态。省略时，将读取最新的已索引时隙，但不超过所请求确认级别允许的范围。

**transactionIndex** `number`

交易在时隙内的位置。返回该交易执行后立即呈现的账户状态，而不是时隙结束时的状态。必须同时提供 slot。

**mint** `string`

仅返回此铸币的代币账户。不能与 programId 同时使用。

**programId** `string`

仅返回所有者为此代币程序的代币账户。不能与 mint 同时使用。

* `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`
* `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`

**encoding** `string` (default: base64)

账户数据的编码格式。使用 jsonParsed 时，代币数量会采用铸币在请求位置时的小数位数。不支持 base58 和 binary。

* `base64`
* `base64+zstd`
* `jsonParsed`

**dataSlice** `object`

仅返回每个账户数据的一个切片。适用于 base64 和 base64+zstd 编码。

**dataSlice.offset** `number` *required*

开始读取位置的字节偏移量。

**dataSlice.length** `number` *required*

要返回的字节数。

**limit** `number` (default: 5000)

要返回的代币账户数量上限（1-5,000）。

**paginationKey** `string`

上一个响应的 paginationKey 游标，格式为 `&lt;mint&gt;:&lt;tokenAccount&gt;`。如果同时设置 mint，游标中的铸币必须与其匹配。

**commitment** `string` (default: finalized)

确认级别。不支持 processed。

* `finalized`
* `confirmed`

**minContextSlot** `number`

可用于评估此请求的最小时隙。


## OpenAPI

````yaml zh/openapi/rpc-http/getHistoricalTokenAccountsByOwner.yaml POST /
openapi: 3.1.0
info:
  title: Solana RPC API
  version: 1.0.0
  description: >-
    历史 Solana 代币账户 API，用于列出钱包在过去某个时隙拥有的 SPL Token 和 Token-2022
    账户，支持可选的铸币地址或代币程序筛选以及基于游标的分页。
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
  - url: https://mainnet.helius-rpc.com
    description: 主网 RPC 端点
security: []
paths:
  /:
    post:
      tags:
        - RPC
      summary: getHistoricalTokenAccountsByOwner
      description: |
        **测试版。** 参数、响应格式和数据覆盖范围可能会发生变化。

        返回钱包在过去某个时隙拥有的 SPL Token 和 Token-2022 账户，或
        该时隙内特定交易执行后立即产生的账户状态。默认情况下，此 Helius RPC 方法
        返回所有代币账户。可以在配置对象中使用铸币地址或代币 programId
        缩小结果范围。

        结果先按铸币地址排序，再按代币账户地址排序。即使某一页的数据较少或
        为空，也可能返回 paginationKey；
        请持续分页，直到 paginationKey 为 null。
      operationId: getHistoricalTokenAccountsByOwner
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - jsonrpc
                - id
                - method
                - params
              properties:
                jsonrpc:
                  type: string
                  enum:
                    - '2.0'
                  example: '2.0'
                  description: JSON-RPC 协议版本。
                  default: '2.0'
                id:
                  type: string
                  example: '1'
                  description: 请求的唯一标识符。
                  default: '1'
                method:
                  type: string
                  enum:
                    - getHistoricalTokenAccountsByOwner
                  example: getHistoricalTokenAccountsByOwner
                  description: 要调用的 RPC 方法名称。
                  default: getHistoricalTokenAccountsByOwner
                params:
                  type: array
                  description: 包含所有者钱包地址、用于选择历史位置的可选查询对象和可选配置对象的数组。
                  minItems: 1
                  maxItems: 3
                  default:
                    - 86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY
                    - slot: 445000000
                    - encoding: jsonParsed
                      limit: 2
                  items:
                    oneOf:
                      - type: string
                        title: 所有者
                        description: 拥有这些代币账户的钱包的 Base-58 编码地址。请传入所有者钱包，而不是代币账户。
                        example: 86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY
                      - $ref: '#/components/schemas/HistoricalAccountQuery'
                        title: 查询
                      - type: object
                        title: 配置
                        description: 可选配置对象。mint 和 programId 最多只能设置一个。
                        properties:
                          mint:
                            type: string
                            description: 仅返回此铸币地址对应的代币账户。不能与 programId 同时使用。
                            example: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
                          programId:
                            type: string
                            description: 仅返回此代币程序拥有的代币账户。不能与 mint 同时使用。
                            enum:
                              - TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
                              - TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
                            example: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
                          encoding:
                            type: string
                            description: >-
                              账户数据的编码格式。使用 jsonParsed 时，代币数量采用所请求位置处铸币的 decimals
                              值。尚不支持 base58 和 binary。
                            enum:
                              - base64
                              - base64+zstd
                              - jsonParsed
                            default: base64
                            example: jsonParsed
                          dataSlice:
                            $ref: '#/components/schemas/DataSliceConfig'
                          limit:
                            type: integer
                            description: 要返回的代币账户最大数量（1-5,000）。
                            minimum: 1
                            maximum: 5000
                            default: 5000
                            example: 1000
                          paginationKey:
                            type: string
                            description: >-
                              来自上一个响应 paginationKey 的游标，格式为
                              `<mint>:<tokenAccount>`。如果同时设置了 mint，游标中的 mint
                              必须与其匹配。
                            example: >-
                              11112zAgXhc6hGfdfr5anSY91mq7Cs4HHpSVEQc4ASG:EKyGnXReqmmXyqBHmMjV2CKCLafJS47xyhXXZ5WuFMxD
                          commitment:
                            type: string
                            description: 确认级别。不支持 processed。
                            enum:
                              - finalized
                              - confirmed
                            default: finalized
                            example: finalized
                          minContextSlot:
                            type: integer
                            description: 可评估请求的最小时隙。
                            example: 445000000
                        additionalProperties: false
      responses:
        '200':
          description: 已成功检索一页历史代币账户。
          content:
            application/json:
              schema:
                type: object
                properties:
                  jsonrpc:
                    type: string
                    description: JSON-RPC 协议版本。
                    enum:
                      - '2.0'
                    example: '2.0'
                  id:
                    type: string
                    description: 与请求匹配的标识符。
                    example: '1'
                  result:
                    type: object
                    properties:
                      context:
                        $ref: '#/components/schemas/HistoricalContext'
                      value:
                        type: object
                        properties:
                          accounts:
                            type: array
                            description: 此页中的代币账户，先按铸币地址排序，再按代币账户地址排序。
                            items:
                              $ref: '#/components/schemas/HistoricalKeyedAccount'
                          paginationKey:
                            oneOf:
                              - type: string
                              - type: 'null'
                            description: >-
                              下一页的游标，格式为 `<mint>:<tokenAccount>`；返回所有账户后为
                              null。如果数据较少或为空的页面带有
                              paginationKey，表示扫描提前停止，而不是已经到达末尾。
                            example: >-
                              11112zAgXhc6hGfdfr5anSY91mq7Cs4HHpSVEQc4ASG:EKyGnXReqmmXyqBHmMjV2CKCLafJS47xyhXXZ5WuFMxD
        '400':
          description: 错误请求 - 请求参数无效或请求格式不正确。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32602
                  message: 参数无效
                id: '1'
        '401':
          description: 未授权 - API 密钥无效或缺失。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32001
                  message: 未授权
                id: '1'
        '429':
          description: 请求过多 - 已超出速率限制。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32005
                  message: 请求过多
                id: '1'
        '500':
          description: 内部服务器错误 - 服务器发生错误。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32603
                  message: 内部错误
                id: '1'
        '503':
          description: 服务不可用 - 服务暂时不可用。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32002
                  message: 服务不可用
                id: '1'
        '504':
          description: 网关超时 - 请求已超时。
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32003
                  message: 网关超时
                id: '1'
      security:
        - ApiKeyQuery: []
components:
  schemas:
    HistoricalAccountQuery:
      type: object
      description: 要读取的历史位置。省略此项或发送空对象可读取最新的已索引时隙。
      properties:
        slot:
          type: integer
          description: >-
            要读取状态的时隙。返回该时隙结束时的账户状态。最早支持的时隙是 444959999，即纪元 1030
            开始时的状态。省略时，将读取最新的已索引时隙，但不会超过所请求的确认级别。
          minimum: 444959999
          example: 445000000
        transactionIndex:
          type: integer
          description: 交易在时隙中的位置。返回该交易执行后立即产生的账户状态，而不是时隙结束时的状态。必须指定 slot。
          minimum: 0
          maximum: 16777214
          example: 10
      additionalProperties: false
    DataSliceConfig:
      type: object
      description: 仅返回每个账户数据的一个切片。适用于 base64 和 base64+zstd 编码。
      properties:
        offset:
          type: integer
          description: 开始读取位置的字节偏移量。
          example: 0
        length:
          type: integer
          description: 要返回的字节数。
          example: 8
      required:
        - offset
        - length
    HistoricalContext:
      type: object
      description: 响应元数据。
      properties:
        slot:
          type: integer
          description: 处理请求时，历史存储已索引的最新时隙。这不是你查询的时隙。
          example: 468129571
    HistoricalKeyedAccount:
      type: object
      properties:
        pubkey:
          type: string
          description: 代币账户的 Base-58 编码地址。
          example: EKyGnXReqmmXyqBHmMjV2CKCLafJS47xyhXXZ5WuFMxD
        account:
          $ref: '#/components/schemas/HistoricalAccount'
      required:
        - pubkey
        - account
    ErrorResponse:
      type: object
      properties:
        jsonrpc:
          type: string
          description: JSON-RPC 协议版本。
          enum:
            - '2.0'
          example: '2.0'
        error:
          type: object
          properties:
            code:
              type: integer
              description: 错误代码。
              example: -32602
            message:
              type: string
              description: 错误消息。
            data:
              type: object
              description: 有关错误的其他数据。
        id:
          type: string
          description: 与请求匹配的标识符。
          example: '1'
    HistoricalAccount:
      type: object
      description: 账户在所请求位置的状态，以及该状态最后一次写入的位置。
      properties:
        lamports:
          type: integer
          description: 分配给此账户的 lamport 数量。
          example: 531589475273
        owner:
          type: string
          description: 分配此账户的程序的 Base-58 编码公钥。
          example: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
        data:
          description: >-
            账户数据。使用 base64 或 base64+zstd 时，返回由编码数据和编码格式组成的双元素数组。使用 jsonParsed
            时，返回包含 program、parsed 和 space 的对象。无法解析的账户将回退为 base64 数组。
          oneOf:
            - type: array
              items:
                type: string
            - type: object
              properties:
                program:
                  type: string
                  description: 拥有该账户的程序名称。
                  example: spl-token
                parsed:
                  type: object
                  description: 特定于程序的已解析账户状态。
                space:
                  type: integer
                  description: 账户的数据大小。
                  example: 82
        executable:
          type: boolean
          description: 账户是否包含程序。
          example: false
        rentEpoch:
          type: integer
          description: 此账户下一次需要支付租金的纪元。免租账户返回 u64 的最大值。
        space:
          type: integer
          description: 账户数据的大小，以字节为单位。
          example: 82
        lastUpdatedAt:
          $ref: '#/components/schemas/AccountWritePosition'
      required:
        - lamports
        - owner
        - data
        - executable
        - rentEpoch
        - space
        - lastUpdatedAt
    AccountWritePosition:
      type: object
      description: 返回的状态在所请求位置或之前最后一次写入的位置。
      properties:
        slot:
          type: integer
          description: >-
            最后一次写入的时隙。如果值为 444959999 且 transactionIndex 为
            null，则表示自历史覆盖开始以来账户未发生变化。
          example: 444999837
        transactionIndex:
          oneOf:
            - type: integer
            - type: 'null'
          description: 执行最后一次写入的交易位置。如果写入发生在交易之外（例如纪元奖励），或者自历史覆盖开始以来账户未发生变化，则为 null。
          example: 700
      required:
        - slot
        - transactionIndex
  securitySchemes:
    ApiKeyQuery:
      type: apiKey
      in: query
      name: api-key
      description: >-
        你的 Helius API
        密钥。你可以在[控制面板](https://dashboard.helius.dev/api-keys)中免费获取一个。

````

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