I have a smart contract that emits events whenever the following line of code in the contract is called:
emit Transfer(from, to, value);
The script that is used to list these events is shown below:
var ethers = require('ethers');
var provider = new ethers.providers.InfuraProvider('ropsten');
const metacoinArtifacts = require('../build/contracts/MyToken.json');
const address = metacoinArtifacts.networks[3].address;
var filter = {
address: address,
fromBlock: 0
};
var callPromise = provider.getLogs(filter);
callPromise.then(function(events) {
console.log("Printing array of events:");
console.log(events);
}).catch(function(err){
console.log(err);
});
The output is the following:
[ { blockNumber: 5196629,
blockHash: '0x19b083ee0752347f0bba9cd1cf19c827fd108c0f5d4973e33719d97a60cf14ca',
transactionIndex: 1,
removed: false,
address: '0xF92298d72afE68300EA065c0EdaDbb1A29804faa',
data: '0x00000000000000000000000000000000000000000000021e19e0c9bab2400000',
topics:
[ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x0000000000000000000000000000000000000000000000000000000000000000',
'0x000000000000000000000000f58e01ac4134468f9ad846034fb9247c6c131d8c' ],
transactionHash: '0xdad8bc380240548aafecba06bf6cee898513da850bb37859cfea5f93d8dd25da',
logIndex: 0 },
{ blockNumber: 5301391,
blockHash: '0x00b7bfeade71c17fd99bcc7c9b684cedad05fede5201e0dbc64614e14b07b07c',
transactionIndex: 23,
removed: false,
address: '0xF92298d72afE68300EA065c0EdaDbb1A29804faa',
data: '0x00000000000000000000000000000000000000000000000000038d7ea4c68000',
topics:
[ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f58e01ac4134468f9ad846034fb9247c6c131d8c',
'0x0000000000000000000000002d92bce8a6cf0fd32cffcabed026a6cb34ee0e9b' ],
transactionHash: '0xf4f973b90fea5b32bf09b55166ee106b81cffd9d1ca8dd4752541d927f12dc18',
logIndex: 33 },
{ blockNumber: 5301417,
blockHash: '0x474fd08cad1d1ea870b8ed60d39505afd8b6e6be40f72c61581602056d7c8d1f',
transactionIndex: 0,
removed: false,
address: '0xF92298d72afE68300EA065c0EdaDbb1A29804faa',
data: '0x00000000000000000000000000000000000000000000000000005af3107a4000',
topics:
[ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f58e01ac4134468f9ad846034fb9247c6c131d8c',
'0x0000000000000000000000002d92bce8a6cf0fd32cffcabed026a6cb34ee0e9b' ],
transactionHash: '0x8fa45694dc0c06b8b447f56221551cdec7987414b127d215d27e992f745d30a8',
logIndex: 0 },
{ blockNumber: 5321681,
blockHash: '0x600fad7a526ac89210378b63df96c09b45238a526fc10df42bfd34643d6b3cfa',
transactionIndex: 24,
removed: false,
address: '0xF92298d72afE68300EA065c0EdaDbb1A29804faa',
data: '0x000000000000000000000000000000000000000000000000000000000000000a',
topics:
[ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f58e01ac4134468f9ad846034fb9247c6c131d8c',
'0x00000000000000000000000015c72944b325a3e1c7a4dbdc6f883bd5948d3d9f' ],
transactionHash: '0x3518b448d9091b3afa3822c4f7ed2216879bba875078b7cc3499142eb50be828',
logIndex: 22 },
{ blockNumber: 5326453,
blockHash: '0x2d709809aa31acc2e047f5d9f2c87aaff958c823725aa3ba7e5cbf5ff5bd7f7a',
transactionIndex: 33,
removed: false,
address: '0xF92298d72afE68300EA065c0EdaDbb1A29804faa',
data: '0x000000000000000000000000000000000000000000000000000000000000000a',
topics:
[ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f58e01ac4134468f9ad846034fb9247c6c131d8c',
'0x00000000000000000000000015c72944b325a3e1c7a4dbdc6f883bd5948d3d9f' ],
transactionHash: '0x0e594a0cfc3bd89df75e9e178f1ef63441e950b621d145fdc063123af595a2f5',
logIndex: 66 },
{ blockNumber: 5326455,
blockHash: '0x85d1bb0651b8064e367b3958133712774d205039cfc8d25a9234e875e48c9615',
transactionIndex: 16,
removed: false,
address: '0xF92298d72afE68300EA065c0EdaDbb1A29804faa',
data: '0x000000000000000000000000000000000000000000000000000000000000000a',
topics:
[ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f58e01ac4134468f9ad846034fb9247c6c131d8c',
'0x00000000000000000000000015c72944b325a3e1c7a4dbdc6f883bd5948d3d9f' ],
transactionHash: '0xf8f2affa3ea09c609dba11b2da4ec0946ae72f269887dd239729c5951f661b21',
logIndex: 38 },
{ blockNumber: 5326525,
blockHash: '0xa0b85af06cbed82cfdea7658c21983502c01679efa79142d34470eb58c3ba9a2',
transactionIndex: 43,
removed: false,
address: '0xF92298d72afE68300EA065c0EdaDbb1A29804faa',
data: '0x000000000000000000000000000000000000000000000000000000000000000a',
topics:
[ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000f58e01ac4134468f9ad846034fb9247c6c131d8c',
'0x00000000000000000000000015c72944b325a3e1c7a4dbdc6f883bd5948d3d9f' ],
transactionHash: '0xc6a8fa37107ed2bd3d9c07be0c86ff8a83002ab590d296cc3af303f09f68b368',
logIndex: 122 } ]
What I am wondering is how do I decode the output of this script to get _from_, _to_, _value_ from the event that was originally emitted?
The easiest way to do this, if you are not using the Contract API, is to use the Interface object API:
// You can also pull in your JSON ABI; I'm not sure of the structure inside artifacts
let abi = [ "event Transfer(address indexed from, address indexed to, uint value)" ];
let iface = new ethers.utils.Interface(abi);
var logPromise = provider.getLogs(filter);
logPromise.then(function(logs) {
console.log("Printing array of events:");
let events = logs.map((log) => iface.parseLog(log))
console.log(events);
}).catch(function(err){
console.log(err);
});
Which will output (given your logs):
[ _LogDescription {
decode: [Function],
name: 'Transfer',
signature: 'Transfer(address,address,uint256)',
topic:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
values: {
'0': '0x0000000000000000000000000000000000000000',
'1': '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
'2': [BigNumber],
from: '0x0000000000000000000000000000000000000000',
to: '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
value: [BigNumber],
length: 3 } },
_LogDescription {
decode: [Function],
name: 'Transfer',
signature: 'Transfer(address,address,uint256)',
topic:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
values:
Result {
'0': '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
'1': '0x2D92bce8a6cf0FD32CFfCABed026a6cb34ee0e9b',
'2': [BigNumber],
from: '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
to: '0x2D92bce8a6cf0FD32CFfCABed026a6cb34ee0e9b',
value: [BigNumber],
length: 3 } },
_LogDescription {
decode: [Function],
name: 'Transfer',
signature: 'Transfer(address,address,uint256)',
topic:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
values: {
'0': '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
'1': '0x2D92bce8a6cf0FD32CFfCABed026a6cb34ee0e9b',
'2': [BigNumber],
from: '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
to: '0x2D92bce8a6cf0FD32CFfCABed026a6cb34ee0e9b',
value: [BigNumber],
length: 3 } },
_LogDescription {
decode: [Function],
name: 'Transfer',
signature: 'Transfer(address,address,uint256)',
topic:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
values: {
'0': '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
'1': '0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f',
'2': [BigNumber],
from: '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
to: '0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f',
value: [BigNumber],
length: 3 } },
_LogDescription {
decode: [Function],
name: 'Transfer',
signature: 'Transfer(address,address,uint256)',
topic:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
values: {
'0': '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
'1': '0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f',
'2': [BigNumber],
from: '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
to: '0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f',
value: [BigNumber],
length: 3 } },
_LogDescription {
decode: [Function],
name: 'Transfer',
signature: 'Transfer(address,address,uint256)',
topic:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
values: {
'0': '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
'1': '0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f',
'2': [BigNumber],
from: '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
to: '0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f',
value: [BigNumber],
length: 3 } },
_LogDescription {
decode: [Function],
name: 'Transfer',
signature: 'Transfer(address,address,uint256)',
topic:
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
values: {
'0': '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
'1': '0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f',
'2': [BigNumber],
from: '0xF58E01Ac4134468F9Ad846034fb9247c6C131d8C',
to: '0x15c72944b325a3E1c7a4DBdc6F883bD5948d3D9f',
value: [BigNumber],
length: 3 } } ]
Note the values inside each event object are what you would be interested in.
I think we are close. I now get the following output:
Printing array of events:
[ undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined ]
Note that this output is produced based on the changes that were made to create the following script:
var ethers = require('ethers');
var provider = new ethers.providers.InfuraProvider('ropsten');
const metacoinArtifacts = require('../build/contracts/MyToken.json');
const address = metacoinArtifacts.networks[3].address;
var abi = [ "event Transfer(address indexed from, address indexed to, uint256 value)" ];
var iface = new ethers.utils.Interface(abi);
var filter = {
address: address,
fromBlock: 0
};
var callPromise = provider.getLogs(filter);
callPromise.then(function(events) {
console.log("Printing array of events:");
var parsedEvents = events.map(function(log) {iface.parseLog(log)});
console.log(parsedEvents);
}).catch(function(err){
console.log(err);
});
What could I be doing wrong here?
You forgot the return in the callback to map. :)
(return iface.parseLog(log))
Is there any good way to convert a Log into an Event?
This is my current attempt to fetch Events from the last n blocks:
const getPastEvents = (eventName, fromBlock, args) => {
const filter = myContract.filters[eventName](...args)
filter.fromBlock = fromBlock
filter.toBlock = "latest"
const logs = await this.provider.getLogs(filter)
const events = []
for (let i in logs) {
events.push(myAbi.parseLog(logs[i]))
}
return events
}
But at the end I'm getting a set of LogDescription which is missing the helpful transaction-accessing methods. Ultimately, the args (aka values) is what I need so not a deal breaker but would be nice to have.
Oh, you'd like the getBlock(), getTransaction() and getTransactionReceipt() operations on the object returned from parseLog? I can add that easy enough.
I may only add it to the v5 branch though, which should be available for public beta later today. :)
These have been added to v5. If you try it out, let me know how they work for you.
Please feel free to re-open or continue discussion (I monitor closed issues) if you have any problems.
Thanks! :)
Oh, that鈥檚 just what console.log does. If you want more context logged, you can use console.dir(result, { depth: null }). :)
Most helpful comment
The easiest way to do this, if you are not using the Contract API, is to use the Interface object API:
Which will output (given your logs):
Note the
valuesinside each event object are what you would be interested in.