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

# Как использовать getTokenAccountsByOwner

> Изучите сценарии использования getTokenAccountsByOwner, примеры кода, параметры запроса, структуру ответа и рекомендации.

Метод RPC [`getTokenAccountsByOwner`](https://www.helius.dev/docs/api-reference/rpc/http/gettokenaccountsbyowner) используется для получения всех [токен-аккаунтов](https://www.helius.dev/blog/how-to-get-token-holders-on-solana) SPL, принадлежащих определенному публичному ключу. Это основной метод для кошельков и приложений, которым нужно отображать токены пользователя или взаимодействовать с его различными токен-аккаунтами.

Запрос необходимо отфильтровать либо по определенному `mint` токена, либо по `programId` (например, программе SPL Token или Token-2022).

Для кошельков с обширными портфелями токенов рекомендуется использовать [`getTokenAccountsByOwnerV2`](/docs/ru/api-reference/rpc/http/gettokenaccountsbyownerv2), который поддерживает пагинацию на основе курсора и настраиваемый размер страницы до 10 000 аккаунтов на запрос.

## Распространенные сценарии использования

* **Отображение портфеля пользователя:** Получение всех токен-аккаунтов и, следовательно, их балансов для заданного адреса кошелька пользователя, чтобы отобразить полный портфель токенов.
* **Логика приложения:** Определение конкретного токен-аккаунта пользователя для определенного минта перед выполнением перевода или другого взаимодействия.
* **Проверка:** Проверка того, какими токен-аккаунтами для определенного типа токена владеет пользователь.
* **Индексирование держателей токенов:** Хотя этот способ менее эффективен для глобального индексирования, чем другие методы, его можно использовать для поиска аккаунтов известного набора владельцев.

## Параметры запроса

1. **`ownerPubkey`** (строка, обязательный): Публичный ключ владельца аккаунта в кодировке base-58, токен-аккаунты которого необходимо получить.

2. **`filter`** (объект, обязательный): Объект JSON, в котором **необходимо** указать `mint` или `programId`:
   * **`mint`** (строка): Публичный ключ определенного минта токена в кодировке base-58. Если он указан, будут возвращены только принадлежащие `ownerPubkey` токен-аккаунты этого минта.
   * **`programId`** (строка): Публичный ключ программы токенов, которая управляет аккаунтами, в кодировке base-58. Распространенные значения:
     * Программа SPL Token: `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`
     * Программа Token-2022: `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`

3. **`options`** (объект, необязательный): Необязательный объект конфигурации, который может включать:
   * **`commitment`** (строка, необязательный): Задает [уровень подтверждения](https://www.helius.dev/blog/solana-commitment-levels).
   * **`encoding`** (строка, необязательный): Кодировка данных аккаунта. Настоятельно рекомендуется `"jsonParsed"`. Другие варианты: `"base64"`, `"base64+zstd"`. Значение по умолчанию — `"base64"`.
   * **`dataSlice`** (объект, необязательный): Позволяет получить определенный фрагмент данных аккаунта (`offset`: usize, `length`: usize). Только для кодировок `base58`, `base64` или `base64+zstd`.
   * **`minContextSlot`** (u64, необязательный): Минимальный слот для запроса.

## Структура ответа

Поле `result.value` в ответе JSON-RPC представляет собой массив объектов. Каждый объект соответствует токен-аккаунту SPL, который принадлежит `ownerPubkey` и соответствует `filter`.

Каждый объект в массиве `value` содержит:

* **`pubkey`** (строка): Публичный ключ самого токен-аккаунта в кодировке base-58.
* **`account`** (объект): Подробная информация о токен-аккаунте:
  * **`lamports`** (u64): Баланс в лампортах для освобождения от арендной платы.
  * **`owner`** (строка): Программа-владелец (например, публичный ключ программы токенов).
  * **`data`**: Данные аккаунта. Если используется кодировка `"jsonParsed"`, это поле содержит:
    * **`program`** (строка): например, `"spl-token"`.
    * **`parsed`**: Объект со структурированной информацией:
      * **`info`**: Такие сведения, как:
        * **`mint`** (строка): Адрес минта токена.
        * **`owner`** (строка): Владелец токен-аккаунта (должен совпадать с `ownerPubkey` из запроса).
        * **`tokenAmount`** (объект): Баланс токенов (`amount`, `decimals`, `uiAmount`, `uiAmountString`).
        * **`state`** (строка): Состояние токен-аккаунта (например, `"initialized"`).
        * **`isNative`** (логическое значение): Указывает, содержит ли аккаунт обернутые SOL.
        * **`delegate`** (строка, необязательный): Адрес делегата, если он задан.
        * **`delegatedAmount`** (объект, необязательный): Делегированная сумма, если задан делегат.
      * **`type`** (строка): например, `"account"`.
  * **`executable`** (логическое значение): Является ли аккаунт исполняемым.
  * **`rentEpoch`** (u64): Следующая эпоха, в которой необходимо внести арендную плату.
  * **`space`** (u64, если не `jsonParsed`): Длина необработанных данных аккаунта в байтах.

**Пример ответа (с кодировкой `jsonParsed` и фильтрацией по `programId`):**

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "result": {
    "context": {
      "slot": 183459000
    },
    "value": [
      {
        "pubkey": "AssociatedTokenAccountPubkey1...",
        "account": {
          "data": {
            "program": "spl-token",
            "parsed": {
              "info": {
                "isNative": false,
                "mint": "SomeTokenMintPubkey...",
                "owner": "OwnerPubkeyProvidedInRequest...",
                "state": "initialized",
                "tokenAmount": {
                  "amount": "1000000000", // 1 token if decimals is 9
                  "decimals": 9,
                  "uiAmount": 1.0,
                  "uiAmountString": "1.0"
                }
              },
              "type": "account"
            },
            "space": 165
          },
          "executable": false,
          "lamports": 2039280,
          "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
          "rentEpoch": 380
        }
      },
      {
        "pubkey": "AnotherAssociatedTokenAccountPubkey...",
        "account": {
          // ... similar structure for another token owned by the same owner
        }
      }
    ]
  },
  "id": 1
}
```

## Примеры кода

<CodeGroup>
  ```bash cURL theme={"system"}
  # Replace <OWNER_PUBKEY> and <TOKEN_MINT_PUBKEY> or <TOKEN_PROGRAM_ID>

  # Example filtering by programId (SPL Token Program)
  curl -X POST -H "Content-Type: application/json" -d \
    '{
      "jsonrpc": "2.0",
      "id": 1,
      "method": "getTokenAccountsByOwner",
      "params": [
        "<OWNER_PUBKEY>",
        { "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
        { "encoding": "jsonParsed" }
      ]
    }' \
    <YOUR_RPC_URL>

  # Example filtering by a specific mint
  curl -X POST -H "Content-Type: application/json" -d \
    '{
      "jsonrpc": "2.0",
      "id": 1,
      "method": "getTokenAccountsByOwner",
      "params": [
        "<OWNER_PUBKEY>",
        { "mint": "<SPECIFIC_TOKEN_MINT_PUBKEY>" },
        { "encoding": "jsonParsed", "commitment": "confirmed" }
      ]
    }' \
    <YOUR_RPC_URL>
  ```

  ```javascript JavaScript (using @solana/web3.js) theme={"system"}
  const { Connection, PublicKey } = require('@solana/web3.js');

  async function findOwnerTokenAccounts(ownerAddress, filter, encoding = 'jsonParsed') {
    // Replace with your RPC endpoint
    const connection = new Connection('https://mainnet.helius-rpc.com/?api-key=<api-key>');
    const ownerPubKey = new PublicKey(ownerAddress);

    try {
      let actualFilter;
      if (filter.mint) {
        actualFilter = { mint: new PublicKey(filter.mint) };
      } else if (filter.programId) {
        actualFilter = { programId: new PublicKey(filter.programId) };
      } else {
        console.error("Filter must contain either 'mint' or 'programId'");
        return;
      }

      const accounts = await connection.getTokenAccountsByOwner(
        ownerPubKey,
        actualFilter,
        { encoding }
      );

      console.log(`Found ${accounts.value.length} token accounts for owner ${ownerAddress}:`);
      accounts.value.forEach(accInfo => {
        console.log(`  Token Account: ${accInfo.pubkey.toBase58()}`);
        if (encoding === 'jsonParsed' && accInfo.account.data.parsed) {
          console.log(`    Mint: ${accInfo.account.data.parsed.info.mint}`);
          console.log(`    Balance: ${accInfo.account.data.parsed.info.tokenAmount.uiAmountString}`);
        }
        // console.log(JSON.stringify(accInfo, null, 2)); // For full details
      });

    } catch (error) {
      console.error(`Error fetching token accounts for owner ${ownerAddress}:`, error);
    }
  }

  // Replace with an actual owner's public key
  const exampleOwner = 'HXtBm8XZbxaTt41uqaKhwUAa6Z1aPyvJdsZVENiWsetg'; // Example wallet address

  // Example 1: Find all SPL Token Program accounts owned by `exampleOwner`
  findOwnerTokenAccounts(exampleOwner, { programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' });

  // Example 2: Find USDC token accounts owned by `exampleOwner`
  // const usdcMint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
  // findOwnerTokenAccounts(exampleOwner, { mint: usdcMint });

  // Example 3: Find Token-2022 Program accounts owned by `exampleOwner`
  // findOwnerTokenAccounts(exampleOwner, { programId: 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' });
  ```
</CodeGroup>

## Рекомендации разработчикам

* **Обязательный фильтр:** В фильтре *необходимо* указать `mint` или `programId`. Без одного из этих основных фильтров невозможно запросить все токен-аккаунты владельца для всех типов токенов.
* **Ассоциированные токен-аккаунты:** Этот метод возвращает все токен-аккаунты, принадлежащие публичному ключу, включая стандартные ассоциированные токен-аккаунты (ATA) и любые другие токен-аккаунты SPL, которыми он может владеть (например, созданные более старыми реализациями кошельков или пользовательскими конфигурациями).
* **Кодировка:** Для параметра `encoding` настоятельно рекомендуется использовать `"jsonParsed"`. Эта кодировка преобразует двоичные данные аккаунта в более удобную структуру JSON.
* **Производительность:** Если у владельца очень много токен-аккаунтов, особенно при фильтрации только по `programId`, ответ может быть большим. В таких случаях используйте [`getTokenAccountsByOwnerV2`](/docs/ru/api-reference/rpc/http/gettokenaccountsbyownerv2), который имеет встроенную поддержку пагинации.
* **Token-2022 (расширения токенов):** Если вы работаете с токенами, созданными с помощью программы Token-2022, которая поддерживает такие расширения, как комиссии за перевод, проценты и другие, используйте правильный `programId`: `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`.

Это руководство дает полное представление о методе RPC `getTokenAccountsByOwner` и позволяет эффективно получать информацию о токен-аккаунтах для любого адреса Solana.

## Пагинация для крупных портфелей токенов

Для кошельков с большим количеством токенов используйте [`getTokenAccountsByOwnerV2`](/docs/ru/api-reference/rpc/http/gettokenaccountsbyownerv2), который предоставляет:

* **Пагинацию на основе курсора**: задайте `limit` (1–10 000) и используйте `paginationKey` для перехода между результатами
* **Инкрементальные обновления**: используйте `changedSinceSlot`, чтобы получить только токен-аккаунты, измененные после определенного слота
* **Повышенную производительность**: предотвращает тайм-ауты и позволяет отслеживать портфель в реальном времени
* **Поведение пагинации**: окончание пагинации обозначается только отсутствием возвращенных токен-аккаунтов. Из-за фильтрации может быть возвращено меньше аккаунтов, чем задано лимитом. Продолжайте пагинацию, пока `paginationKey` не станет null

```typescript theme={"system"}
// Example: Paginated query for all token accounts
const response = await fetch("https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: "1",
    method: "getTokenAccountsByOwnerV2",
    params: [
      "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
      { "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
      {
        encoding: "jsonParsed",
        limit: 1000
      }
    ]
  })
});

const data = await response.json();
console.log(`Found ${data.result.value.length} token accounts`);
if (data.result.paginationKey) {
  console.log("More results available, use paginationKey for next page");
  // Continue pagination even if fewer than limit accounts were returned
} else {
  console.log("End of pagination - no more token accounts available");
}
```

## Связанные методы

<CardGroup cols={2}>
  <Card title="getTokenAccountsByOwnerV2" href="/docs/ru/api-reference/rpc/http/gettokenaccountsbyownerv2">
    Версия с пагинацией и навигацией на основе курсора для крупных портфелей
  </Card>

  <Card title="getTokenAccountBalance" href="/docs/ru/api-reference/rpc/http/gettokenaccountbalance">
    Получение баланса определенного токен-аккаунта
  </Card>
</CardGroup>


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