如何从TransactionResponse对象正确获取交易的Fee Payer?
结论先行
直接取transaction.transaction.message.accountKeys[0]作为交易Fee Payer的做法完全不可靠,不要在公共脚本里使用。
为什么索引0的取值方式不靠谱
你观察到的accountKeys首元素为Fee Payer只是主流客户端构造交易时的默认行为,没有任何协议层面的强制规则保证这个位置永远是Fee Payer:
- 自定义构造的交易可以随意调整accountKeys数组的顺序,完全可以把Fee Payer放在非0索引的位置
- v0版本化交易、经过地址查找表解析后的交易响应,accountKeys的排序逻辑和Legacy旧交易存在差异,很容易出现首元素不是Fee Payer的情况
- 部分链上程序自动触发的交易、多签构造的交易,accountKeys的排序也可能不符合常规客户端的默认顺序,直接取0号索引会得到错误结果。
可靠的Fee Payer获取方法
不需要自己猜索引,web3.js本身提供了官方封装的属性可以直接拿,适配所有交易类型:
- 针对Legacy格式的旧交易,直接读取Message实例的内置
feePayer字段即可,这个字段会自动根据消息头定位Fee Payer的正确索引,不受accountKeys排序影响:
const feePayer = transaction.transaction.message.feePayer
- 针对v0版本化交易,先将返回的交易数据解析为VersionedTransaction实例,再直接读取实例的
feePayer属性:
const versionedTx = VersionedTransaction.populate( transaction.transaction.message, transaction.transaction.signatures ) const feePayer = versionedTx.feePayer
额外提示:你提到的「绝大多数场景下Fee Payer就是代币初始铸造者」的经验判断在主流发射平台的普通发币场景下基本成立,但要注意代付Gas工具、批量发币脚本发起的交易可能出现Fee Payer和实际铸造权限持有者不一致的情况,如果需要更高准确率,可以额外校验Mint初始化指令关联的签名账户列表。
内容的提问来源于stack exchange,提问作者Oguzhan
相关产品推荐
相关产品推荐

