账户模型背景
如果您熟悉 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- “给我所有由这个程序管理的账户” 2. 按结构过滤 与datasize- “但只有这个特定类型的账户” 3. 针对特定数据 与memcmp- “并且只有那些包含这个特定信息的账户” 4. 监控已知账户 与account- “或者只监控我关心的这些精确账户”
理解更大的图景
将账户订阅想象成观看数据库变化的实时流。Solana的状态本质上是一个庞大的键值存储,每个账户都是一个条目。当程序执行时,它们会修改这些账户。你的订阅让你能够实时观看特定条目的变化。 过滤系统就像数据库索引——你不是在监控“所有变化”,而是在监控“符合这些标准的账户变化”。这样可以构建响应式应用程序,即时响应相关的链上事件,而不会被无关数据淹没系统。将此模式应用于其他程序
我们学过的方法适用于任何 Solana 程序。以下是通用模式:- 研究账户结构 - 查看程序的源代码或文档 2. 从所有者过滤开始 - 针对管理账户的程序 3. 应用结构性过滤器 - 使用账户大小、数据模式或其他特征缩小到特定账户类型 4. 添加针对性过滤器 - 专注于对你的应用程序重要的特定账户、状态或数据值