Skip to main content
Метод RPC getProgramAccounts — это мощный инструмент для выполнения запросов к блокчейну Solana. Он позволяет получить все аккаунты, принадлежащие определённой ончейн-программе. Это необходимо для широкого спектра приложений: от поиска всех аккаунтов токенов, связанных с пользователем для определённого минта токена, до обнаружения всех аккаунтов с данными конкретного пользователя в децентрализованном приложении. Поскольку программа может владеть большим количеством аккаунтов, getProgramAccounts предоставляет расширенные возможности фильтрации. Они помогают сузить область поиска и эффективно получить только необходимые данные. Для приложений, которым требуется запрашивать очень большие наборы аккаунтов программы, рассмотрите возможность использования getProgramAccountsV2. Этот метод поддерживает пагинацию на основе курсора и настраиваемый размер страницы — до 10 000 аккаунтов на запрос.

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

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

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

  1. programId (string, обязательный):
    • Публичный ключ программы в кодировке base58, аккаунты которой вы хотите получить.
    • Пример: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" (для программы SPL Token).
  2. options (object, необязательный): объект конфигурации со следующими полями:
    • commitment (string): задаёт уровень подтверждения, например "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.

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

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

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

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

API Reference

getProgramAccounts

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

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

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

  • Производительность: getProgramAccounts может потреблять много ресурсов узлов RPC, особенно при отсутствии фильтров или при работе с программами, имеющими большое количество аккаунтов. По возможности всегда используйте фильтры dataSize и memcmp, а также dataSlice, чтобы сузить область запроса и уменьшить размер ответа.
  • Большие наборы результатов: ответы на запросы с большим количеством результатов могут быть усечены, либо время ожидания может истечь. Используйте фильтры, чтобы сузить область запроса, или рассмотрите getProgramAccountsV2, который поддерживает пагинацию.
  • Ограничения частоты запросов: учитывайте ограничения частоты запросов поставщика RPC, поскольку частые или ресурсоёмкие вызовы getProgramAccounts могут привести к превышению этих ограничений.
  • Знание структуры данных: для эффективного использования memcmp необходимо понимать побайтовую структуру запрашиваемых данных аккаунта.
  • Доступность jsonParsed: кодировка jsonParsed доступна, только если узел RPC имеет парсер для типов аккаунтов конкретной программы. Она широко поддерживается для распространённых программ, таких как SPL Token.
getProgramAccounts — незаменимый метод для разработчиков, которым необходимо запрашивать наборы аккаунтов, принадлежащих программе, и взаимодействовать с ними. Освоение его параметров фильтрации — ключ к созданию эффективных и надёжных приложений Solana.

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

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

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

getProgramAccountsV2

Версия с пагинацией и навигацией на основе курсора для больших наборов данных