账户模型背景
如果您熟悉 Solana 账户及其结构,请跳过此部分。
- 数据:存储程序状态、代币余额或其他信息的实际字节
- 所有者:控制此账户并可以修改其数据的程序
- Lamports:账户的 SOL 余额用于租金豁免
- 可执行:此账户是否包含程序代码
基本账户订阅
让我们从一个简单的示例开始,该示例订阅代币账户的变化。此脚本将在代币余额发生变化时通知您:BKMHWYLAX4un3HUbR7a3u9jPmzCiLNa4mSj1RiX11eWF的更新。
该账户具有:
- 2,039,280 lamports(约0.002 SOL余额 - 这是该代币账户的免租金额)
- 所有者程序
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA(这是SPL代币程序) - 交易签名
5C9Hr5nG2j8eQz6inxPmfyjbYdmXddzUDyR1iQgEnjYQ3RNvuP4Zzc8t1enLNy7Rk8KNCtQPEQztENYWxkt9GaVD,显示导致此账户变化的具体交易 - 插槽352366983,指示此更新何时在区块链上发生
- 数据字段,包含165字节的账户数据,编码为base58
理解使用datasize进行账户过滤
数据字段至关重要 - 它包含实际的代币账户结构。让我们利用这一理解进行智能账户过滤。为什么使用datasize过滤?
要理解我们为什么需要过滤,首先要了解代币账户到底是什么。对于钱包持有的每个代币,链上都有一个单独的账户。 如果您的钱包持有3种不同的代币(USDC、BONK和SOL),实际上您有1个钱包账户(您的主SOL账户)加上3个代币账户(每种代币类型一个)。每个代币账户正好是165字节,并存储:它持有的代币(铸造地址),谁拥有它(您的钱包地址),以及它包含多少该代币(数量)。 Token Program在Solana上拥有数百万个账户,但并非所有账户都是我们认为的持有用户余额的“代币账户”。以下是有过滤和无过滤的情况: 无过滤 - 洪水般的数据:- Token 账户(165 字节)- 用户余额:数百万个账户
- Mint 账户(82 字节)- 代币定义:数十万个账户
- Multisig 账户(355 字节)- 共享钱包控制:数万个账户
- Associated Token Program 账户(各种大小)- 数百万个账户
- 无过滤: 数百万个账户更新(代币创建、多重签名更改等)
- 使用数据大小过滤: 仅代币余额变化
165 字节从何而来?
这不是魔法 - 它来自SPL代币程序的账户结构。查看源代码,我们可以看到Account结构定义了正好165字节:
- Mint 账户(82 字节)
- Multisig 账户(355 字节)
- Associated token account program 账户
- 其他具有不同大小的代币相关账户
解码账户结构
现在我们已经了解了为什么要过滤165字节,让我们解码示例账户中的内容:- 字节 0-31: 铸币地址(此账户持有的代币)
- 字节 32-63: 拥有者地址(谁拥有此代币账户)
- 字节 64-71: 代币数量(账户中的代币数量)
- 字节 72-164: 附加元数据(委托、状态、关闭权限等)
结合过滤器:datasize + memcmp 实现精确定位
既然我们知道mint地址位于字节0-31,我们可以更具体。假设我们只想监控USDC代币账户。我们可以结合我们的datasize过滤器与memcmp过滤器来定位确切的mint地址:
- 拥有者过滤器: “给我由代币程序拥有的账户”(数百万个账户)
- 数据大小过滤器: “但仅限165字节的标准代币账户”(数十万个)
- Memcmp过滤器: “并且仅限持有USDC的账户”(数千个)
读取USDC账户更新:谁,多少,在哪里?
现在让我们看看这些过滤后的更新实际上包含什么。让我们创建一个USDC特定的监控器,以回答代币账户更改时的关键问题:- 谁 拥有这个代币账户?
- 多少 USDC 现在包含在其中?
- 哪里(哪个具体账户)发生了变化?
- 何时 发生了这种变化?
- 什么交易 导致了变化?
bs58.encode()函数将二进制Buffer对象转换为可读字符串。
完整过滤参考
除了我们使用的基本owner, datasize, 和memcmp过滤器外,账户订阅还支持其他过滤选项以进一步缩小结果范围:
特定账户过滤
通过公钥监控精确账户:组合过滤策略
强大的地方在于结合多种过滤类型。这里是思维模型:- 广泛筛选 使用
owner- “给我所有由此程序管理的账户” - 按结构过滤 使用
datasize- “但只有此特定类型的账户” - 针对具体数据 使用
memcmp- “并且仅包含此特定信息的账户” - 监控已知账户 使用
account- “或者只关注我关心的这些账户”
理解更大的图景
将账户订阅视为观看数据库更改的实时动态。Solana 的状态本质上是一个巨大的键值存储,每个账户都是一个条目。当程序执行时,它们会修改这些账户。您的订阅让您可以实时观看特定条目的变化。 过滤系统的工作原理类似于数据库索引——您不仅仅是在观看“所有更改”,而是在观看“符合这些标准的账户的更改”。这使得构建响应式应用程序成为可能,这些应用程序可以立即对相关的链上事件做出反应,而不会因不相关的数据而使您的系统不堪重负。将此模式应用于其他程序
我们学到的方法适用于任何 Solana 程序。以下是一般模式:- 研究账户结构 - 查看程序的源代码或文档
- 从所有者过滤开始 - 针对管理账户的程序
- 应用结构过滤器 - 使用账户大小、数据模式或其他特征来缩小到特定的账户类型
- 添加目标过滤器 - 专注于对您的应用程序重要的特定账户、状态或数据值