getProgramAccounts
RPC 方法是查询 Solana 区块链的强大工具。它允许您检索由特定链上程序拥有的所有账户。这对于广泛的应用程序至关重要,从查找与特定代币铸造相关的用户的所有代币账户,到发现去中心化应用程序的所有用户特定数据账户。
由于程序可能拥有的账户数量可能很大,getProgramAccounts
提供了强大的过滤功能,帮助您缩小搜索范围并高效地检索所需数据。
对于需要查询非常大规模程序账户的应用程序,考虑使用 getProgramAccountsV2
,它提供基于游标的分页支持,配置的页面大小每次请求最多可达 10,000 个账户。
常见用例
- 查找铸币的所有代币账户: 发现特定 SPL 代币的所有持有者。
- 检索用户特定数据: 获取由程序为特定用户创建的所有账户(例如,用户在 DeFi 协议中的头寸,他们在 Play-to-Earn 游戏中的游戏状态)。
- 列出自定义账户类型的所有实例: 如果您的程序定义了特定的账户结构,
getProgramAccounts
可以找到该结构的所有实例。 - 监控程序状态: 观察与程序相关的所有账户以跟踪其整体状态或活动。
- 构建浏览器和分析工具: 聚合有关程序及其关联账户的数据。
请求参数
-
programId
(string
,必需):- 您要获取其账户的程序的 base-58 编码公钥。
- 示例:
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
(用于 SPL 代币程序)。
-
options
(object
, 可选): 一个配置对象,包含以下字段:commitment
(string
): 指定承诺级别(例如,"finalized"
,"confirmed"
)。encoding
(string
): 每个返回账户中data
字段的编码。默认为"base64"
。"base58"
: 二进制数据的较慢替代方案。"base64"
: 二进制数据的标准base64编码。"base64+zstd"
: base64编码的zstd压缩二进制数据。"jsonParsed"
: 如果RPC节点有程序账户类型的解析器(例如,SPL Token, Stake),则data
字段将是一个结构化的JSON对象。强烈推荐用于可读性和易用性。
filters
(array
): 一个应用于账户的过滤对象数组。这对于性能和相关性至关重要。您可以使用最多4个过滤器。常见的过滤器包括:dataSize
(object
):dataSize
(u64
): 按数据长度(字节)过滤账户。例如:{ "dataSize": 165 }
(用于SPL Token账户)。
memcmp
(object
): 内存比较。将账户数据的一个切片与提供的字节进行比较。offset
(usize
): 开始比较的账户数据字节偏移量。bytes
(string
): 要匹配的字节的base-58编码字符串。字节串必须小于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
):账户的 base-58 编码公钥。account
(object
):lamports
(u64
):账户的 lamports 余额。owner
(string
):拥有此账户的程序的 base-58 编码公钥(这将是您查询的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)的所有代币账户
此示例查找持有 USDC 的所有 SPL 代币账户。它使用dataSize
过滤代币账户(165 字节),并使用 memcmp
匹配偏移量 0 处的 USDC 铸币地址。
2. 查找由特定钱包拥有的所有代币账户
此示例查找由特定钱包地址拥有的所有 SPL 代币账户。它使用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