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

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

> Узнайте о сценариях использования getProgramAccounts, примерах кода, параметрах запроса, структуре ответа и рекомендациях.

Метод RPC [`getProgramAccounts`](https://www.helius.dev/docs/api-reference/rpc/http/getprogramaccounts) — это мощный инструмент для выполнения запросов к блокчейну Solana. Он позволяет получить все аккаунты, принадлежащие определённой ончейн-программе. Это необходимо для широкого спектра приложений: от поиска всех аккаунтов токенов, связанных с пользователем для определённого минта токена, до обнаружения всех аккаунтов с данными конкретного пользователя в децентрализованном приложении.

Поскольку программа может владеть большим количеством аккаунтов, `getProgramAccounts` предоставляет расширенные возможности фильтрации. Они помогают сузить область поиска и эффективно получить только необходимые данные.

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

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

* **Поиск всех аккаунтов токенов для минта:** найдите всех держателей определённого SPL-токена.
* **Получение данных конкретного пользователя:** получите все аккаунты, созданные программой для определённого пользователя, например позиции пользователя в DeFi-протоколе или его состояние в игре формата Play-to-Earn.
* **Получение списка всех экземпляров пользовательского типа аккаунта:** если ваша программа определяет конкретную структуру аккаунта, `getProgramAccounts` может найти все экземпляры этой структуры.
* **Мониторинг состояния программы:** отслеживайте все связанные с программой аккаунты, чтобы наблюдать за её общим состоянием или активностью.
* **Создание обозревателей и аналитических инструментов:** агрегируйте данные о программах и связанных с ними аккаунтах.

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

1. **`programId`** (`string`, обязательный):
   * Публичный ключ программы в кодировке base58, аккаунты которой вы хотите получить.
   * Пример: `"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"` (для программы SPL Token).

2. **`options`** (`object`, необязательный): объект конфигурации со следующими полями:
   * **`commitment`** (`string`): задаёт [уровень подтверждения](https://www.helius.dev/blog/solana-commitment-levels), например `"finalized"` или `"confirmed"`.
   * **`encoding`** (`string`): кодировка поля `data` в каждом возвращаемом аккаунте. По умолчанию используется `"base64"`.
     * `"base58"`: более медленная альтернатива для двоичных данных.
     * `"base64"`: стандартная кодировка base64 для двоичных данных.
     * `"base64+zstd"`: двоичные данные, сжатые с помощью zstd и закодированные в base64.
     * `"jsonParsed"`: если узел RPC имеет парсер для типа аккаунта программы, например SPL Token или Stake, поле `data` будет структурированным объектом JSON. Этот вариант настоятельно рекомендуется для удобства чтения и использования.
   * **`filters`** (`array`): массив объектов фильтров, применяемых к аккаунтам. Это особенно важно для производительности и релевантности. Можно использовать до четырёх фильтров. Распространённые фильтры:
     * **`dataSize`** (`object`):
       * `dataSize` (`u64`): фильтрует аккаунты по длине их данных в байтах. Пример: `{ "dataSize": 165 }` (для аккаунтов SPL Token).
     * **`memcmp`** (`object`): сравнение областей памяти. Сопоставляет часть данных аккаунта с указанными байтами.
       * `offset` (`usize`): смещение в байтах в данных аккаунта, с которого начинается сравнение.
       * `bytes` (`string`): строка сопоставляемых байтов в кодировке base58. Длина строки байтов должна составлять менее 129 байт.
       * Пример: чтобы найти аккаунты токенов для определённого минта, используйте `memcmp` со значением `offset: 0`, где в аккаунте токена хранится адрес минта, и задайте для `bytes` публичный ключ минта.
   * **`dataSlice`** (`object`): возвращает только определённый срез данных каждого аккаунта. Полезно для больших аккаунтов, если вам нужна только часть данных.
     * `offset` (`usize`): смещение в байтах, с которого начинается срез.
     * `length` (`usize`): количество возвращаемых байтов.
     * *Примечание: `dataSlice` предназначен преимущественно для двоичных кодировок, а не для `jsonParsed`.*
   * **`withContext`** (`boolean`): если установлено значение `true`, ответ будет объектом `RpcResponse`, содержащим `context` с `slot` и `value` — массив аккаунтов. Если установлено значение `false` или параметр не указан, обычно возвращается только массив аккаунтов. Поведение может немного различаться в зависимости от поставщика RPC.
   * **`minContextSlot`** (`u64`): минимальный слот, на котором может быть обработан запрос.

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

Ответ представляет собой массив объектов. Каждый объект соответствует найденному аккаунту и содержит:

* **`pubkey`** (`string`): публичный ключ аккаунта в кодировке base58.
* **`account`** (`object`):
  * `lamports` (`u64`): баланс аккаунта в лампортах.
  * `owner` (`string`): публичный ключ программы, владеющей этим аккаунтом, в кодировке base58. Это будет `programId`, по которому выполнялся запрос.
  * `data` (`string`, `array` или `object`): данные аккаунта, отформатированные в соответствии с параметром `encoding`.
    * Для `jsonParsed`: объект JSON, представляющий десериализованное состояние аккаунта.
    * Для `base64`: массив `["encoded_string", "base64"]`.
  * `executable` (`boolean`): является ли аккаунт исполняемым, то есть программой.
  * `rentEpoch` (`u64`): эпоха, в которую аккаунт должен будет в следующий раз внести арендную плату.
  * `space` (`u64`, необязательный): длина данных аккаунта в байтах. Иногда обозначается как `data.length`, если данные представлены буфером, либо включается в разобранную структуру.

Если используется `withContext: true`, этот массив будет вложен в поле `value` объекта `RpcResponse`.

## Примеры

### 1. Поиск всех аккаунтов токенов для определённого минта (USDC)

В этом примере выполняется поиск всех аккаунтов SPL Token, на которых хранится USDC. Фильтр `dataSize` выбирает аккаунты токенов размером 165 байт, а `memcmp` сопоставляет адрес минта USDC по смещению 0.

<CodeGroup>
  ```bash cURL theme={"system"}
  # Replace <api-key> with your Helius API key
  # USDC Mint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
  # Token Program ID: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
  curl https://mainnet.helius-rpc.com/?api-key=<api-key> -X POST -H "Content-Type: application/json" -d \
    '{
      "jsonrpc": "2.0",
      "id": 1,
      "method": "getProgramAccounts",
      "params": [
        "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
        {
          "encoding": "jsonParsed",
          "filters": [
            { "dataSize": 165 },
            {
              "memcmp": {
                "offset": 0, 
                "bytes": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
              }
            }
          ]
        }
      ]
    }'
  ```

  ```javascript JavaScript (using @solana/web3.js) theme={"system"}
  // Replace <api-key> with your Helius API key
  const { Connection, PublicKey } = require('@solana/web3.js');
  const { TOKEN_PROGRAM_ID } = require('@solana/spl-token');

  const USDC_MINT_ADDRESS = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';

  async function findUsdcTokenAccounts() {
    const connection = new Connection('https://mainnet.helius-rpc.com/?api-key=<api-key>');

    try {
      const accounts = await connection.getProgramAccounts(TOKEN_PROGRAM_ID, {
        encoding: 'jsonParsed',
        filters: [
          {
            dataSize: 165, // Standard token account size
          },
          {
            memcmp: {
              offset: 0, // Offset for the mint address in a token account
              bytes: USDC_MINT_ADDRESS, // Base-58 encoded mint address
            },
          },
        ],
      });

      console.log(`Found ${accounts.length} USDC token accounts.`);
      accounts.forEach((accountInfo, index) => {
        console.log(`--- Account ${index + 1} ---`);
        console.log(`  Pubkey: ${accountInfo.pubkey.toBase58()}`);
        // Accessing parsed data
        const parsedData = accountInfo.account.data.parsed.info;
        console.log(`  Owner: ${parsedData.owner}`);
        console.log(`  Amount: ${parsedData.tokenAmount.uiAmountString}`);
      });
    } catch (error) {
      console.error('Error fetching USDC token accounts:', error);
    }
  }

  findUsdcTokenAccounts();
  ```
</CodeGroup>

### 2. Поиск всех аккаунтов токенов, принадлежащих определённому кошельку

В этом примере выполняется поиск всех аккаунтов SPL Token, принадлежащих определённому адресу кошелька. Используются `dataSize` (165 байт) и `memcmp` со смещением 32, где в аккаунте токена хранится публичный ключ владельца.

<CodeGroup>
  ```bash cURL theme={"system"}
  # Replace <api-key> with your Helius API key
  # Example Wallet Address: Helioo21241PANoNdeG55722hgUnp2VawDgsz2g
  # Token Program ID: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
  curl https://mainnet.helius-rpc.com/?api-key=<api-key> -X POST -H "Content-Type: application/json" -d \
    '{
      "jsonrpc": "2.0",
      "id": 1,
      "method": "getProgramAccounts",
      "params": [
        "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
        {
          "encoding": "jsonParsed",
          "filters": [
            { "dataSize": 165 },
            {
              "memcmp": {
                "offset": 32, 
                "bytes": "Helioo21241PANoNdeG55722hgUnp2VawDgsz2g"
              }
            }
          ]
        }
      ]
    }'
  ```

  ```javascript JavaScript (using @solana/web3.js) theme={"system"}
  // Replace <api-key> with your Helius API key
  const { Connection, PublicKey } = require('@solana/web3.js');
  const { TOKEN_PROGRAM_ID } = require('@solana/spl-token');

  const TARGET_WALLET_ADDRESS = 'Helioo21241PANoNdeG55722hgUnp2VawDgsz2g';

  async function findWalletTokenAccounts() {
    const connection = new Connection('https://mainnet.helius-rpc.com/?api-key=<api-key>');

    try {
      const accounts = await connection.getProgramAccounts(TOKEN_PROGRAM_ID, {
        encoding: 'jsonParsed',
        filters: [
          {
            dataSize: 165, // Standard token account size
          },
          {
            memcmp: {
              offset: 32, // Offset for the owner address in a token account
              bytes: TARGET_WALLET_ADDRESS, // Base-58 encoded wallet address
            },
          },
        ],
      });

      console.log(`Found ${accounts.length} token accounts for wallet ${TARGET_WALLET_ADDRESS}.`);
      accounts.forEach((accountInfo, index) => {
        console.log(`--- Account ${index + 1} (${accountInfo.pubkey.toBase58()}) ---`);
        const parsedData = accountInfo.account.data.parsed.info;
        console.log(`  Mint: ${parsedData.mint}`);
        console.log(`  Amount: ${parsedData.tokenAmount.uiAmountString}`);
      });
    } catch (error) {
      console.error('Error fetching token accounts for wallet:', error);
    }
  }

  findWalletTokenAccounts();
  ```
</CodeGroup>

## Расширенная фильтрация

Оптимизируйте запросы с помощью фильтров, чтобы уменьшить размер ответа и повысить производительность:

```typescript theme={"system"}
// Example filtering by memcmp (memory comparison)
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: "getProgramAccounts",
      params: [
        "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Solana Token Program
        {
          encoding: "jsonParsed",
          filters: [
            {
              dataSize: 165, // Size of token account data
            },
            {
              memcmp: {
                offset: 32, // Location of owner address in the token account
                bytes: "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",
              },
            },
          ],
        },
      ],
    }),
  }
);
const data = await response.json();
console.log("Filtered program accounts data:", data);
```

<Card title="API Reference" horizontal icon="code" href="/docs/ru/api-reference/rpc/http/getprogramaccounts">
  getProgramAccounts
</Card>

### Типы фильтров

* `memcmp`: фильтрует аккаунты, соответствующие определённому шаблону по заданному смещению
* `dataSize`: фильтрует аккаунты по точному размеру данных
* Несколько фильтров: должны выполняться все условия (логическое И)

## Советы разработчикам

* **Производительность:** `getProgramAccounts` может потреблять много ресурсов узлов RPC, особенно при отсутствии фильтров или при работе с программами, имеющими большое количество аккаунтов. По возможности всегда используйте фильтры `dataSize` и `memcmp`, а также `dataSlice`, чтобы сузить область запроса и уменьшить размер ответа.
* **Большие наборы результатов:** ответы на запросы с большим количеством результатов могут быть усечены, либо время ожидания может истечь. Используйте фильтры, чтобы сузить область запроса, или рассмотрите [`getProgramAccountsV2`](/docs/ru/api-reference/rpc/http/getprogramaccountsv2), который поддерживает пагинацию.
* **Ограничения частоты запросов:** учитывайте ограничения частоты запросов поставщика RPC, поскольку частые или ресурсоёмкие вызовы `getProgramAccounts` могут привести к превышению этих ограничений.
* **Знание структуры данных:** для эффективного использования `memcmp` необходимо понимать побайтовую структуру запрашиваемых данных аккаунта.
* **Доступность `jsonParsed`:** кодировка `jsonParsed` доступна, только если узел RPC имеет парсер для типов аккаунтов конкретной программы. Она широко поддерживается для распространённых программ, таких как SPL Token.

`getProgramAccounts` — незаменимый метод для разработчиков, которым необходимо запрашивать наборы аккаунтов, принадлежащих программе, и взаимодействовать с ними. Освоение его параметров фильтрации — ключ к созданию эффективных и надёжных приложений Solana.

## Пагинация для больших наборов данных

Для приложений, работающих с программами, которым принадлежит большое количество аккаунтов (10 000 и более), используйте [`getProgramAccountsV2`](/docs/ru/api-reference/rpc/http/getprogramaccountsv2). Этот метод предоставляет:

* **Пагинацию на основе курсора**: задайте `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: "getProgramAccountsV2",
    params: [
      "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
      {
        encoding: "base64",
        filters: [{ dataSize: 165 }],
        limit: 5000
      }
    ]
  })
});

const data = await response.json();
console.log(`Found ${data.result.accounts.length} 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 accounts available");
}
```

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

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


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