I read that to listen to events you need to use web3.js. Are there other ways of doing it? Can a contract even somehow listen to events of another contract? Thanks!
[Ethereum] Can a contract listen to events of another contract
contract-designcontract-developmenteventslogsweb3js
Related Solutions
event.watch is not a function in web3.0 v1.0
Use the snippet below instead, but remember that:
myContract
should be a variable you assigned which is an instance of your contractMyEvent
should be replaced with the actual name of your event.
myContract.events.MyEvent({ filter: {myIndexedParam: [20,23], myOtherIndexedParam: '0x123456789...'}, // Using an array means OR: e.g. 20 or 23 fromBlock: 0 }, function(error, event){ console.log(event); }) .on('data', function(event){ console.log(event); // same results as the optional callback above }) .on('changed', function(event){ // remove event from local database }) .on('error', console.error);
Also see the docs here.
This answer assumes that you understand how to connect to a contract using Ethers.
Your question specifies listening for an event to be emitted, and to do a task based on that.
Here is the link to the Ethers v5 documentation, which we'll expand on a bit below: https://docs.ethers.io/v5/api/providers/provider/#Provider--events
Basically, the on
function is what you're looking for. Using a provider, you can set up an on
to trigger something whenever a particular event is emitted. This will trigger the callback (the second argument in the on
, a function) anytime that event is emitted on the blockchain. If you are looking for the on
to be triggered only when the events of a particular contract are called, you'll need to use a filter - the provider will trigger the callback anytime this event is emitted from any contract.
If you look at the example in the link above to the v5 docs (at least right now 22/09/2020), towards the bottom there are examples of how to use filters (either a general filter or a topic filter - we'll discuss the first). Basically:
filter = {
address: THE_ADDRESS_OF_YOUR_CONTRACT,
topics: [
// the name of the event, parnetheses containing the data type of each event, no spaces
utils.id("Transfer(address,address,uint256)")
]
}
provider.on(filter, () => {
// do whatever you want here
// I'm pretty sure this returns a promise, so don't forget to resolve it
})
There are many more details about how and what you can filter in the links above, but this is the fundamental building block. I hope this helps!
Update: Based on a comment, I thought I should add that on
can also be used with a contract object. If you have a variable representing a contract (which we'll call contract
), you can also hook an on
onto it. Here's a link to a section in the v4 docs which has an example (which at least as of now isn't in the v5 docs yet) - scroll down to the "listening to an Event" code example. It has the same format where you pass in an event name or filter for the first arg, and then can write a function callback as the second. This will only return events from contract
.
Best Answer
A contract cannot listen to events of another contract. From Solidity docs:
web3.js is a wrapper around JSON-RPC, so another way of accessing event data is via "filters" in JSON-RPC such as eth_newFilter.
Note the dichotomy that a contract can't access events and web3.js is needed, but web3.js can't access return values from a contract invocation. So a pattern of using both an event and a return value like this may be needed: