getProgramAccounts — это мощный инструмент для выполнения запросов к блокчейну Solana. Он позволяет получить все аккаунты, принадлежащие определённой ончейн-программе. Это необходимо для широкого спектра приложений: от поиска всех аккаунтов токенов, связанных с пользователем для определённого минта токена, до обнаружения всех аккаунтов с данными конкретного пользователя в децентрализованном приложении.
Поскольку программа может владеть большим количеством аккаунтов, getProgramAccounts предоставляет расширенные возможности фильтрации. Они помогают сузить область поиска и эффективно получить только необходимые данные.
Для приложений, которым требуется запрашивать очень большие наборы аккаунтов программы, рассмотрите возможность использования getProgramAccountsV2. Этот метод поддерживает пагинацию на основе курсора и настраиваемый размер страницы — до 10 000 аккаунтов на запрос.
Распространённые сценарии использования
- Поиск всех аккаунтов токенов для минта: найдите всех держателей определённого SPL-токена.
- Получение данных конкретного пользователя: получите все аккаунты, созданные программой для определённого пользователя, например позиции пользователя в DeFi-протоколе или его состояние в игре формата Play-to-Earn.
- Получение списка всех экземпляров пользовательского типа аккаунта: если ваша программа определяет конкретную структуру аккаунта,
getProgramAccountsможет найти все экземпляры этой структуры. - Мониторинг состояния программы: отслеживайте все связанные с программой аккаунты, чтобы наблюдать за её общим состоянием или активностью.
- Создание обозревателей и аналитических инструментов: агрегируйте данные о программах и связанных с ними аккаунтах.
Параметры запроса
-
programId(string, обязательный):- Публичный ключ программы в кодировке base58, аккаунты которой вы хотите получить.
- Пример:
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"(для программы SPL Token).
-
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
Версия с пагинацией и навигацией на основе курсора для больших наборов данных