I really like the library, but I spent an hour trying to figure out how to get past events, and when I did, it was painfully slow with provider.resetEventsBlock(fromBlock)
Please let me know how I can have the same speed as web3.getPastEvents
Thank you
You should be able to just use the provider.getLogs(filter) to query for historic events. The speed shouldn鈥檛 be any different though, are you using the most recent version of ethers?
In v5, contracts have a simpler interface too. Coming soon. :)
I can confirm that getting past events with provider.getLogs is fast. I am using the latest version of ethers.
For a quick note about the upcoming v5, I've already added a method to Contract, which can be used as: contract.queryFilter(filter [ , fromBlock [ , toBlock ] ]), which can take in any EventFilter object (e.g. a string name, "ValueChanged"; a topic array [ topic0, [ topic1a, topic1b ] ]; a full filter { address: someAddress, topics: topics }).
I'll be putting it up soon for feedback. :)
@ricmoo
would you be able to provide a full example, please?
I've tried to follow the one from official documentation and it didn't seem to work :-(
I really think I'm doing something wrong, if you could perhaps show the full example, I'd really appreciate it.
I tried just using
let contractEnsName = '0x123....123';
let topic = ethers.utils.id("nameRegistered(bytes32,address,uint256)");
let filter = {
address: contractEnsName,
fromBlock: 7400416,
toBlock: 'latest',
topics: [ topic ]
}
provider.getLogs(filter).then((result) => {
console.log(result);
})
a few questions come up:
allEvents like in web3.js libraryThank you
I'm still confused by both answers above because they don't provide actual examples.
It's great to have an explanation, but the actual code is self-explanatory like in web3.js docs.
The reason why I want to migrate off web3.js - is because they have been inconsistent with their stability (like if you switch from npm to yarn - things will break) and I really loved ethers.js from day1(it was yesterday) because you allow doing things like nonce overwriting in the tx construction, non-hardcoded 50 blocks wait to throw and bunch of other cool stuff.
We still need truffle team to convince to generate ethers.js-type of readable abi type, so we can just copy/paste from it.
So, for a few examples (which I agree, the documentation could certainly use more of):
let abi = [
"event Transfer(bytes32 indexed node, address owner)"
];
let ens = new Contract("0x314159265dD8dbb310642f98f50C066173C1259b", abi, provider)
// Get the filter event
filter = ens.filters.Transfer()
// {
// address: "0x314159265dD8dbb310642f98f50C066173C1259b",
// topics: [ "0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266" ]
// }
// Oryou could pass in a parameter to the above call to filter by node, sine it is indexed,
// let filter = ens.filters.Transfer(ethers.utils.namehash("ricmoo.firefly.eth"));
// Now you can specify fromBlock and toBlock (you may pass in promises; no need to await)
filter.fromBlock = provider.getBlockNumber().then((b) => b - 10000);
filter.toBlock = "latest";
// And query:
provider.getLogs(filter).then((logs) => {
console.log(logs);
});
// Of course, you can get all events, just by not including topics (again, you can use promises):
let filterAll = {
address: provider.getNetwork().then((n) => n.ensAddress),
fromBlock: provider.getBlockNumber().then((b) => b - 10000),
toBlock: "latest"
}
// Or if you want an event listener, you can do something like:
contract.on("Transfer", function(node, owner, eventObject) {
console.log(node, owner, eventObject);
});
// You could also use a filter object:
// contract.on(ens.filters.Transfer(), function(node, owner, eventObject) { ... }
// Or listen for all events:
contract.on("*", function(eventObject) {
// If the event matches anything in the ABI, it will add the parsed parameters for you,
// otherwise, you only get the raw data and topics.
console.log(eventObject);
});
I will focus on getting more examples together in the next round of documentation, since I'll be sprucing it up for v5, but hopefully that will get you started. Here is an overview on the eventObject too, which is quite useful: https://docs.ethers.io/ethers.js/html/api-contract.html#event-emitter
Let me know if you have any more questions.
@ricmoo thank you so much! Now I'm ready to say good bye to web3.js
Things like this is killing me. Hopefully ether.js can also do dry-run on state changing methods
@ricmoo
Here is what I ended up doing:
const ethers = require('ethers')
const fs = require('fs')
let abi = [
"event Transfer(address indexed from, address indexed to, uint tokens)"
];
let infuraProvider = new ethers.providers.InfuraProvider('mainnet');
let ens = new ethers.Contract("0xB8c77482e45F1F44dE1745F52C74426C631bDD52", abi, infuraProvider)
filter = ens.filters.Transfer()
filter.fromBlock = infuraProvider.getBlockNumber().then((b) => b - 10000);
filter.toBlock = "latest";
infuraProvider.getLogs(filter).then((logs) => {
logs.forEach((log) => {
const data = ens.interface.parseLog(log)
fs.appendFileSync('addressesBNB.csv', data.values.to +'\n')
})
})
is there a way to do getLogs without additional parseLog func? just to optimize things up?
I think that is as good as you are going to get for now. In v5, you will be able to do:
ens.queryFilter(ens.filters.Transfer(), infuraProvider.getBlockNumber().then((b) => b - 10000), "latest")
which should be coming out soon, as a public beta. :)
@ricmoo I was able to record a video and tell the world about ethers.js
https://twitter.com/rstormsf/status/1110250992111476737
Keep up the good work!
Human Readable ABI - is the killer feature. I was able to quickly make a call to the contract function during the video tutorial
The contract.queryFilter ( filter [ , fromBlock [ , toBlock ] ] ) should be available now in the latest version of the v5 beta. Try it out and let me know if you have any problems.
The dry-run can be done using the new contract.callStatic.transfer(); callStatic will always use a call. But please keep in mind that blockchains are eventually-consistent, and a success/failure to a function using staticCall can still not jive with actual results for myriad reasons...
Thanks! :)
This works very well inn in v5, thanks Ricmoo!
For those still on v4, here is another simple example:
const topicTransfer= ethers.utils.id("Transfer(address,address,uint256)") //This is the interface for your event
console.log("topic ID for your event", topicTransfer);
const web3 = await getWeb3(); // Your provider
const logs = await web3.getLogs({
fromBlock: 0,
address: "0xC841dCc53D20560c77F0C6d858383568CDf96182", // Address of contract
toBlock: 'latest',
topics: [topicTransfer]
}).catch(() => [])
console.log("logs qued", logs);
The transfer Event on the Smart Contract: event Transfer(address indexed from, address indexed to, uint256 value);
// Get the Users Account Transfer Events.
var txn = await tokenInstance.getPastEvents("Transfer", {
filter: { from: userAccount },
fromBlock: 0,
toBloack: "lastest",
});
console.log(txn);
The above code is using web3. How can I replicate this simple code with ethers. Getting an array of the 'Transfer' event, so that I can get the address indexed _to and the uint256 _value
If you are using v5 (which I recommend) this has been made much easier.
// Get the filter (the second null could be omitted)
const filter = tokenInstance.filters.Transfer(userAccount, null);
// Query the filter (the latest could be omitted)
const logs = tokenInstance.queryFilter(filter, 0, "latest");
// Print out all the values:
logs.forEach((log) => {
// The log object contains lots of useful things, but the args are what you prolly want)
console.log(log.args._to, log.args._value);
});
@ricmoo is it posible to filter by multiple addresses like in web3?
{ filter: { from: [userAccount1, userAccount2] }, fromBlock: 0, toBlock: 'lastest' })
Most helpful comment
So, for a few examples (which I agree, the documentation could certainly use more of):
I will focus on getting more examples together in the next round of documentation, since I'll be sprucing it up for v5, but hopefully that will get you started. Here is an overview on the eventObject too, which is quite useful: https://docs.ethers.io/ethers.js/html/api-contract.html#event-emitter
Let me know if you have any more questions.