> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbitflare.com/llms.txt
> Use this file to discover all available pages before exploring further.

# getTokenAccountsByOwner

> Возвращает все токеновые счета для заданного владельца

## Параметры

<ResponseField name="owner" type="string" required>
  Открытый ключ владельца (в кодировке base-58)
</ResponseField>

<ResponseField name="config" type="object" required>
  Объект конфигурации, содержащий:

  <ResponseField name="programId" type="string" required>
    Открытый ключ программы токенов (в кодировке base-58)
  </ResponseField>

  <ResponseField name="commitment" type="string" optional>
    Уровень подтверждения (processed, confirmed, finalized)
  </ResponseField>

  <ResponseField name="encoding" type="string" optional>
    Кодирование данных счёта (base58, base64, jsonParsed)
  </ResponseField>

  <ResponseField name="dataSlice" type="object" optional>
    <ResponseField name="offset" type="number">
      Смещение в данных счёта
    </ResponseField>

    <ResponseField name="length" type="number">
      Длина возвращаемых данных
    </ResponseField>
  </ResponseField>
</ResponseField>

## Ответ

<ResponseField name="result" type="object">
  Объект, содержащий:

  <ResponseField name="context" type="object">
    <ResponseField name="slot" type="number">
      Слот, в котором был обработан запрос
    </ResponseField>
  </ResponseField>

  <ResponseField name="value" type="array">
    Массив объектов токеновых счетов, содержащих:

    <ResponseField name="pubkey" type="string">
      Открытый ключ токенового счёта (в кодировке base-58)
    </ResponseField>

    <ResponseField name="account" type="object">
      <ResponseField name="lamports" type="number">
        Количество lamports на счёте
      </ResponseField>

      <ResponseField name="owner" type="string">
        Открытый ключ владельца счёта (в кодировке base-58)
      </ResponseField>

      <ResponseField name="executable" type="boolean">
        Является ли счёт исполняемым
      </ResponseField>

      <ResponseField name="rentEpoch" type="number">
        Эпоха, в которую счёт должен будет оплатить аренду следующий раз
      </ResponseField>

      <ResponseField name="data" type="object">
        <ResponseField name="parsed" type="object">
          <ResponseField name="info" type="object">
            <ResponseField name="tokenAmount" type="object">
              <ResponseField name="amount" type="string">
                Необработанное количество токенов в виде строки
              </ResponseField>

              <ResponseField name="decimals" type="number">
                Количество десятичных знаков, настроенных для монетного двора токена
              </ResponseField>

              <ResponseField name="uiAmount" type="number" optional>
                Количество токенов в виде числа с плавающей точкой с учётом десятичных знаков
              </ResponseField>

              <ResponseField name="uiAmountString" type="string" optional>
                Количество токенов в виде строки с учётом десятичных знаков
              </ResponseField>
            </ResponseField>

            <ResponseField name="mint" type="string">
              Открытый ключ монетного двора токена (в кодировке base-58)
            </ResponseField>

            <ResponseField name="owner" type="string">
              Открытый ключ владельца токенового счёта (в кодировке base-58)
            </ResponseField>

            <ResponseField name="delegate" type="string" optional>
              Открытый ключ делегата (в кодировке base-58)
            </ResponseField>
          </ResponseField>

          <ResponseField name="type" type="string">
            Тип счёта (account)
          </ResponseField>
        </ResponseField>

        <ResponseField name="program" type="string">
          Программа, владеющая счётом (spl-token)
        </ResponseField>

        <ResponseField name="space" type="number">
          Количество байтов, выделенных для счёта
        </ResponseField>
      </ResponseField>
    </ResponseField>
  </ResponseField>
</ResponseField>

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

### Базовый запрос

```bash theme={null}
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "getTokenAccountsByOwner",
  "params": [
    "4vJ9JU1bJJE96FWSJKvHsmmFADCg4gpZQff4P3bkLZj",
    {
      "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
    }
  ]
}'
```

### Использование web3.js

```typescript theme={null}
import { Connection, PublicKey } from '@solana/web3.js';

const connection = new Connection('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY');

// Get token accounts by owner
const owner = new PublicKey('4vJ9JU1bJJE96FWSJKvHsmmFADCg4gpZQff4P3bkLZj');
const programId = new PublicKey('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA');
const accounts = await connection.getTokenAccountsByOwner(owner, { programId });
console.log('Token accounts:', accounts);

// Get token accounts by owner with analysis
async function getTokenAccountsByOwnerWithAnalysis(
  owner: PublicKey,
  config: { programId: PublicKey; commitment?: string }
) {
  const accounts = await connection.getTokenAccountsByOwner(owner, config);
  
  return {
    accounts,
    analysis: {
      totalAccounts: accounts.value.length,
      totalBalance: accounts.value.reduce((sum, acc) => {
        const amount = BigInt(acc.account.data.parsed.info.tokenAmount.amount);
        return sum + amount;
      }, BigInt(0)),
      byMint: accounts.value.reduce((acc, account) => {
        const mint = account.account.data.parsed.info.mint;
        const amount = BigInt(account.account.data.parsed.info.tokenAmount.amount);
        acc[mint] = (acc[mint] || BigInt(0)) + amount;
        return acc;
      }, {} as Record<string, bigint>),
      metadata: {
        timestamp: Date.now(),
        commitment: config.commitment
      }
    }
  };
}
```

## Примечания

1. Возвращает все токеновые счета, принадлежащие указанному открытому ключу
2. Владелец имеет полный контроль над этими счетами
3. Ответ приходит немедленно, так как читается из текущего состояния
4. Счета могут изменяться при переводах токенов и других операциях
5. Владелец должен быть действительным открытым ключом

## Рекомендации

1. Используйте подходящий уровень подтверждения в зависимости от ваших потребностей
2. Кэшируйте результаты там, где это уместно, для снижения нагрузки на RPC
3. Отслеживайте изменения в принадлежащих счетах
4. Рассмотрите использование подписки на websocket для обновлений в реальном времени
5. Обрабатывайте сетевые ошибки и выполняйте повторные попытки при необходимости

## Распространённые ошибки

| Код    | Сообщение          | Решение                                          |
| ------ | ------------------ | ------------------------------------------------ |
| -32601 | Method not found   | Убедитесь, что вы подключены к узлу Solana RPC   |
| -32602 | Invalid params     | Проверьте открытый ключ владельца и конфигурацию |
| -32007 | Owner not found    | Убедитесь, что владелец существует               |
| -32008 | Invalid program ID | Проверьте корректность ID программы              |

## Сценарии использования

1. **Анализ счетов владельца**
   ```typescript theme={null}
   interface OwnerAccountAnalysis {
     owner: string;
     accounts: Array<{
       pubkey: string;
       mint: string;
       balance: string;
       delegate?: string;
     }>;
     metrics: {
       totalAccounts: number;
       totalBalance: string;
       byMint: Record<string, string>;
       delegatedAccounts: number;
     };
     metadata: {
       timestamp: number;
       commitment?: string;
     };
   }

   class OwnerAccountAnalyzer {
     async analyzeOwnerAccounts(
       owner: PublicKey,
       config: { programId: PublicKey; commitment?: string }
     ): Promise<OwnerAccountAnalysis> {
       const accounts = await connection.getTokenAccountsByOwner(owner, config);
       
       const byMint: Record<string, bigint> = {};
       let totalBalance = BigInt(0);
       let delegatedAccounts = 0;
       
       accounts.value.forEach(account => {
         const mint = account.account.data.parsed.info.mint;
         const amount = BigInt(account.account.data.parsed.info.tokenAmount.amount);
         const delegate = account.account.data.parsed.info.delegate;
         
         byMint[mint] = (byMint[mint] || BigInt(0)) + amount;
         totalBalance += amount;
         if (delegate) {
           delegatedAccounts++;
         }
       });
       
       return {
         owner: owner.toBase58(),
         accounts: accounts.value.map(account => ({
           pubkey: account.pubkey,
           mint: account.account.data.parsed.info.mint,
           balance: account.account.data.parsed.info.tokenAmount.amount,
           delegate: account.account.data.parsed.info.delegate
         })),
         metrics: {
           totalAccounts: accounts.value.length,
           totalBalance: totalBalance.toString(),
           byMint: Object.fromEntries(
             Object.entries(byMint).map(([mint, amount]) => [mint, amount.toString()])
           ),
           delegatedAccounts
         },
         metadata: {
           timestamp: Date.now(),
           commitment: config.commitment
         }
       };
     }
   }
   ```

2. **Мониторинг счетов владельца**
   ```typescript theme={null}
   interface OwnerAccountChange {
     owner: string;
     changes: Array<{
       type: 'added' | 'removed' | 'modified';
       account: string;
       previousBalance?: string;
       currentBalance?: string;
       previousDelegate?: string;
       currentDelegate?: string;
     }>;
     metadata: {
       timestamp: number;
     };
   }

   class OwnerAccountMonitor {
     private previousAccounts: Map<string, {
       balance: string;
       delegate?: string;
     }> = new Map();
     
     async monitorOwnerAccounts(
       owner: PublicKey,
       config: { programId: PublicKey; commitment?: string }
     ): Promise<OwnerAccountChange | null> {
       const accounts = await connection.getTokenAccountsByOwner(owner, config);
       const currentAccounts = new Map(
         accounts.value.map(account => [
           account.pubkey,
           {
             balance: account.account.data.parsed.info.tokenAmount.amount,
             delegate: account.account.data.parsed.info.delegate
           }
         ])
       );
       
       const changes: Array<{
         type: 'added' | 'removed' | 'modified';
         account: string;
         previousBalance?: string;
         currentBalance?: string;
         previousDelegate?: string;
         currentDelegate?: string;
       }> = [];
       
       // Check for removed or modified accounts
       this.previousAccounts.forEach((data, account) => {
         if (!currentAccounts.has(account)) {
           changes.push({
             type: 'removed',
             account,
             previousBalance: data.balance,
             previousDelegate: data.delegate
           });
         } else {
           const current = currentAccounts.get(account)!;
           if (current.balance !== data.balance || current.delegate !== data.delegate) {
             changes.push({
               type: 'modified',
               account,
               previousBalance: data.balance,
               currentBalance: current.balance,
               previousDelegate: data.delegate,
               currentDelegate: current.delegate
             });
           }
         }
       });
       
       // Check for added accounts
       currentAccounts.forEach((data, account) => {
         if (!this.previousAccounts.has(account)) {
           changes.push({
             type: 'added',
             account,
             currentBalance: data.balance,
             currentDelegate: data.delegate
           });
         }
       });
       
       this.previousAccounts = currentAccounts;
       
       if (changes.length > 0) {
         return {
           owner: owner.toBase58(),
           changes,
           metadata: {
             timestamp: Date.now()
           }
         };
       }
       
       return null;
     }
   }
   ```

3. **Планирование счетов владельца**
   ```typescript theme={null}
   interface OwnerAccountPlan {
     owner: string;
     currentAccounts: Array<{
       pubkey: string;
       mint: string;
       balance: string;
       delegate?: string;
     }>;
     recommendations: Array<{
       type: 'consolidate' | 'diversify' | 'rebalance' | 'delegate';
       accounts: string[];
       reason: string;
     }>;
     metadata: {
       timestamp: number;
     };
   }

   class OwnerAccountPlanner {
     private readonly minBalancePerAccount = BigInt(1000000); // 1 token
     private readonly maxAccountsPerMint = 5;
     
     async planOwnerAccounts(
       owner: PublicKey,
       config: { programId: PublicKey; commitment?: string }
     ): Promise<OwnerAccountPlan> {
       const accounts = await connection.getTokenAccountsByOwner(owner, config);
       
       const byMint = accounts.value.reduce((acc, account) => {
         const mint = account.account.data.parsed.info.mint;
         if (!acc[mint]) {
           acc[mint] = [];
         }
         acc[mint].push(account);
         return acc;
       }, {} as Record<string, typeof accounts.value>);
       
       const recommendations: Array<{
         type: 'consolidate' | 'diversify' | 'rebalance' | 'delegate';
         accounts: string[];
         reason: string;
       }> = [];
       
       Object.entries(byMint).forEach(([mint, mintAccounts]) => {
         // Check for accounts with low balances
         const lowBalanceAccounts = mintAccounts.filter(account => 
           BigInt(account.account.data.parsed.info.tokenAmount.amount) < this.minBalancePerAccount
         );
         
         if (lowBalanceAccounts.length > 0) {
           recommendations.push({
             type: 'consolidate',
             accounts: lowBalanceAccounts.map(account => account.pubkey),
             reason: `Accounts with balances below minimum threshold for mint ${mint}`
           });
         }
         
         // Check for too many accounts per mint
         if (mintAccounts.length > this.maxAccountsPerMint) {
           recommendations.push({
             type: 'consolidate',
             accounts: mintAccounts.map(account => account.pubkey),
             reason: `Too many accounts (${mintAccounts.length}) for mint ${mint}`
           });
         }
         
         // Check for accounts without delegates
         const accountsWithoutDelegates = mintAccounts.filter(
           account => !account.account.data.parsed.info.delegate
         );
         
         if (accountsWithoutDelegates.length > 0) {
           recommendations.push({
             type: 'delegate',
             accounts: accountsWithoutDelegates.map(account => account.pubkey),
             reason: `Accounts without delegates for mint ${mint}`
           });
         }
       });
       
       return {
         owner: owner.toBase58(),
         currentAccounts: accounts.value.map(account => ({
           pubkey: account.pubkey,
           mint: account.account.data.parsed.info.mint,
           balance: account.account.data.parsed.info.tokenAmount.amount,
           delegate: account.account.data.parsed.info.delegate
         })),
         recommendations,
         metadata: {
           timestamp: Date.now()
         }
       };
     }
   }
   ```
