了解如何解码和解析来自Laserstream的交易数据,以更好地理解Solana交易。
<Buffer 00 bf a0 e8...>
,而不是可读的地址和签名。
本指南将向您展示如何: 将这些二进制数据解码为人类可读的格式,提取有意义的信息,并理解从提案到执行的完整交易过程。
filters
,createdAt
加上一个transaction
分支,隐藏了两个子项:
transaction.transaction.transaction
→ 签署的消息transaction.transaction.meta
→ 执行的元数据Uint8Array
的内容目前仍然不透明。
当您运行带有解码功能的脚本时,您将看到实际的嵌套结构和可读的地址:
Uint8Array
对象的形式存在,不可读。您需要将这些转换为base58字符串,以理解交易。
解决方案: Laserstream使用Yellowstone gRPC,它提供了内置的解码工具。我们使用一个递归函数将所有二进制数据转换为人类可读的格式,而不是为每种字段类型编写单独的解码器。
transaction.transaction.transaction
→ 签名消息(用户的提案)transaction.transaction.meta
→ 执行元数据(验证者的响应)numRequiredSignatures
告诉验证者需要验证多少个签名,而两个 numReadonly*
值标记运行时可以视为只读的账户,从而实现并行执行。
accountKeys
是一个公共密钥的简单列表,作为查找表。交易中的每个后续整数 - programIdIndex
,指令的每个元素 accounts
数组 - 通过索引指回这个列表,每条消息节省超过一千字节。
recentBlockhash
一旦滚出最后150个区块哈希后就会过期,在主网上大约是九十秒。
programIdIndex
): 指向 accountKeys
数组中的一个地址(例如,索引10 = ComputeBudget111111111111111111111111111111
)accounts
): 一个 base58 编码的字符串,表示此指令涉及的账户索引data
): 实际的指令数据,编码为 base58convertBuffers
函数,账户显示为 base58,但实际上包含账户索引(例如,"3vtmrQMafzDoG2CBz1iqgXPTnC"
解码为索引 [21, 19, 12, 17, 2, 6, 1, 22])
这种设计意味着每个指令只需引用查找表中的位置,而不是重复完整的 32 字节地址。
signatures
包含加密签名,证明所需账户授权了此交易。签名数量必须与 header.numRequiredSignatures
匹配。
versioned
是 true
,addressTableLookups
出现在链上表和两个索引列表中。查找表将地址数量的硬性上限提升到几十个,同时保持数据包在 1,232 字节 MTU 之内。
accountKeys
列出此交易将涉及的所有地址header
指定需要多少个签名以及哪些账户是只读的instruction
指向:
programIdIndex
→ accountKeys[index]
)accounts
→ 多个 accountKeys[index]
位置)data
中)signatures
证明所需账户批准了此交易recentBlockhash
确保此交易不能在以后重放err: null
= 成功err: {...}
= 失败并带有错误详情fee
= 此交易收取的 lamportsaccountKeys
数组:
bs58.encode()
将二进制字段转换为可读的base58字符串accountKeys
数组中引用账户preBalances
和postBalances
以查看变化