blockchain - 以太坊/BSC 区块链交易数据
问题描述
我正在尝试在 Binance Smart Chain 区块链上使用 web3js,但我在理解交易数据时碰壁了。
以这个交易为例,有三个交易转移(Tokens Transferred),大多数时候有两个(到目前为止我已经看到了 2、3 和 5)。我不明白是什么决定了单笔交易的转账次数。以及如何使用 web3js 检索该数据。
如果交易是关于出售代币而不是购买,我想知道支付的 BNB 金额和在该交易中收到的代币数量,反之亦然。
我设法获得了支付的价格和代币金额,但仅适用于有 2 次代币转移的交易。但如果有 3 个或更多,我无法获得此信息。
web3.eth.getTransaction('0x899e7f3c2138d051eb5246850ded99d519ab65eba58e5f806245cf346ab40e83').then((result) => {
console.log(result)
console.log(web3.utils.fromWei(result.value))
let tx_data = result.input;
let input_data = '0x' + tx_data.slice(10); // get only data without function selector
let params = web3.eth.abi.decodeParameters([
{
indexed: false,
internalType: 'uint256',
name: 'value',
type: 'uint256'
},
{
indexed: false,
internalType: 'uint256',
name: 'ethReceived',
type: 'uint256'
},
]
, input_data);
console.log(params)
})
这部分代码只为我提供了 2 次令牌传输的数据。无论交易中有多少笔转账,如何让它始终向我退还已支付/收到的现金/代币的金额?可能吗??从我所看到的情况来看,交易中的第一次转账和最后一次转账将是我感兴趣的值。有没有简单的方法来获得这些值?我正在努力理解这一点并使用 ABI 进行解码。它们可以有点通用吗?
解决方案
“Tokens Transferred”信息来自事件日志。大多数令牌标准都定义了一个事件Transfer(address indexed from, address indexed to, uint256 value)
,因此您可以在事务中查找此事件的日志。
事件日志在getTransactionReceipt()中可用,而不是常规的getTransaction()。
事件定义中的indexed
修饰符意味着该值将在topics
属性中可用(topics[0]
是事件签名的 keccak256 哈希,在索引值之后)。然后将“未索引”值存储在data
属性中 - 根据它们的定义顺序排序。
const transferEventSignature = web3.utils.keccak256('Transfer(address,address,uint256)'); // 0xddf252...
const jsonAbi = [{
"constant" :true,
"inputs": [],
"name": "decimals",
"outputs": [{"name":"","type":"uint8"}],
"type": "function"
}]; // simplified JSON abi that is only able to read decimals
web3.eth.getTransactionReceipt('0x899e7f3c2138d051eb5246850ded99d519ab65eba58e5f806245cf346ab40e83').then(async (result) => {
for (const log of result.logs) {
if (log.topics[0] !== transferEventSignature) {
continue; // only interested in Transfer events
}
const from = web3.eth.abi.decodeParameter('address', log.topics[1]);
const to = web3.eth.abi.decodeParameter('address', log.topics[2]);
const value = web3.eth.abi.decodeParameter('uint256', log.data);
const tokenContractAddress = log.address;
const contractInstance = new web3.eth.Contract(jsonAbi, tokenContractAddress);
const decimals = await contractInstance.methods.decimals().call();
console.log('From: ', from);
console.log('To: ', to);
console.log('Value: ', value);
console.log('Token contract: ', tokenContractAddress);
console.log('Token decimals: ', decimals);
console.log('---');
}
});
输出:
From: 0xC6A93610eCa5509E66f9B2a95A5ed1d576cC9b7d
To: 0xE437fFf464c6FF2AA5aD5c15B4CCAD98DF38cF52
Value: 31596864050517135
Token contract: 0x78F1A99238109C4B834Ac100d1dfCf14e3fC321C
Token decimals: 9
---
From: 0xE437fFf464c6FF2AA5aD5c15B4CCAD98DF38cF52
To: 0x58F876857a02D6762E0101bb5C46A8c1ED44Dc16
Value: 4064578781674512
Token contract: 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c
Token decimals: 18
---
From: 0x58F876857a02D6762E0101bb5C46A8c1ED44Dc16
To: 0xC6A93610eCa5509E66f9B2a95A5ed1d576cC9b7d
Value: 2552379452401563824
Token contract: 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56
Token decimals: 18
注意:一些令牌实现是不正确的(即不遵循令牌标准)并且没有将事件参数标记为indexed
. 在这种情况下,topics[0]
仍然是相同的,但是地址from
和to
中不存在topics
,但是您必须从data
字段中解析它们。an 的长度address
是 64 个十六进制字符(在实际的 40 个字符地址之前添加零)。
推荐阅读
- assembly - 在 JMP 命令之后,程序不会返回到它被调用的地方
- reactjs - 从本地托管的 MongoDB (Node.js) 获得快速响应的问题
- excel - 在 Excel 中使用小数向上或向下舍入
- r - 发现变量长度不同
- angular - 每当使用 RouterModule.forChild() 从 app.module 调用不同模块的组件时,整个页面都会重新加载
- python - 分配随机变量随机值
- c - 如何将二维矩阵作为参数传递给函数?
- java - Spring Boot 连接两个 MySQL 数据库
- c# - 我怎样才能发布这样的东西?
- sql - 通过减少内部查询来优化此 SQL 查询?