我们经常会遇到查询或访问某个合约的历史log日志,并解析合约地址相关日志,当然也可以是某个用户的地址。
下面根据案例,讲实际需求和解决方案
这是一个token合约,我们将获取此token合约的所有转账事件的历史记录
https://kovan.etherscan.io/address/0x29abca1f656a18d765971b4bad0ce112669e866e#code
以上链接是源码链接地址;
我们的需求这样的
通过web3js获取此token合约的转账事件,并解析此token合约对应的日志
这是event事件代码
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
这是要解析的日志log,下面emit 后面的代码
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "BEP20: transfer from the zero address");
require(recipient != address(0), "BEP20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount, "BEP20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
//要解析的日志logs
emit Transfer(sender, recipient, amount);
}
首先打开web3js官方文档:web3.eth.Contract — web3.js 1.0.0 documentation
这里提供了三种直接访问的方案(其它方案这里不阐述)
分别是:1:once
2:events
3:getPastEvents
这里我们以getPastEvents为例详细阐述
读取合约的历史事件。
调用:
myContract.getPastEvents(event[, options][, callback])
参数:
返回值:
一个Promise对象,其解析值为历史事件对象数组
示例代码:
myContract.getPastEvents('MyEvent', {
filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // Using an array means OR: e.g. 20 or 23
fromBlock: 0,
toBlock: 'latest'
}, function(error, events){ console.log(events); })
.then(function(events){
console.log(events) // same results as the optional callback above
});
> [{
returnValues: {
myIndexedParam: 20,
myOtherIndexedParam: '0x123456789...',
myNonIndexParam: 'My String'
},
raw: {
data: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
topics: ['0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7', '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385']
},
event: 'MyEvent',
signature: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
logIndex: 0,
transactionIndex: 0,
transactionHash: '0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385',
blockHash: '0xfd43ade1c09fade1c0d57a7af66ab4ead7c2c2eb7b11a91ffdd57a7af66ab4ead7',
blockNumber: 1234,
address: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'
},{
...
}]
我们的代码;
var Web3 = require('web3');
var web3;
var topic=["0x29abca1F656A18D765971B4Bad0cE112669E866e"];
var abi = [{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[],"name":"_decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}];
async function createWeb3(){
try {
web3 = new Web3(new Web3.providers.HttpProvider('https://kovan.infura.io/v3/097a55226aad462e913bbf6c60ca039e'));
} catch (error) {
console.log(error);
return false;
}
}
// main();
async function main(){
if (await createWeb3() == false) {
console.log('Web3 Create Error'.yellow);
process.exit();
}
var fomo =new web3.eth.Contract(abi,
topic);
fomo.getPastEvents("Transfer",{fromBlock: 0,
toBlock: 'latest'
}, function(error, events){ console.log(events); })
.then(function(events){
console.log(events) // same results as the optional callback above
});
}
main();
返回结果:
[{
address: '0x29abca1F656A18D765971B4Bad0cE112669E866e',
blockHash: '0xfcfc3a30ddd6e7cf792f8f5b0ae34ecce279ef53d8d1fa2803b5e97c40ec7a6e',
blockNumber: 33488693,
logIndex: 0,
removed: false,
transactionHash: '0xba0694b985d51d845ed028062bd272b3b0261f59f93068663fa3e06b45bfbbfc',
transactionIndex: 0,
transactionLogIndex: '0x0',
type: 'mined',
id: 'log_f5d16985',
returnValues: Result {
'0': '0x65518F078Ea391fdFFa3ebe916778b70440116D7',
'1': '0xe980414De23cb6fD52958B4E9b7720823cb18F41',
'2': '100000000000000000000',
from: '0x65518F078Ea391fdFFa3ebe916778b70440116D7',
to: '0xe980414De23cb6fD52958B4E9b7720823cb18F41',
value: '100000000000000000000'
},
event: 'Transfer',
signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
raw: {
data: '0x0000000000000000000000000000000000000000000000056bc75e2d63100000',
topics: [Array]
}
}
]
其中一下便是我们解析事件和日志的结果
returnValues: Result {
'0': '0x65518F078Ea391fdFFa3ebe916778b70440116D7',
'1': '0xe980414De23cb6fD52958B4E9b7720823cb18F41',
'2': '100000000000000000000',
from: '0x65518F078Ea391fdFFa3ebe916778b70440116D7',
to: '0xe980414De23cb6fD52958B4E9b7720823cb18F41',
value: '100000000000000000000'
},
关于topics怎么来的怎么计算的请看这篇文章:Web3Js订阅Log示例_北纬32.6的博客-CSDN博客
以及参考链接:web3.eth.abi — web3.js 1.0.0 documentation