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 contract
MyEvent
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.
I stumbled upon a related issue that addresses a broader scope of this problem. The challenge isn't isolated to websocket subscriptions for events, but actually pertains to the entire websocket communication process with web3 providers.
In essence, this affects all websocket provider interactions when using Ethers.js. The core of the problem seems to be a lack of an efficient reconnection mechanism in ethers.js. As a result, the connection might get interrupted or even miss certain events, especially during reconnection attempts.
Two potential solutions stood out from the discussions on the issue:
Manual Reconnection Enhancement: Enhance the existing WebSocket behavior by introducing a custom reconnection mechanism. A sample implementation is available here.
Using the Alchemy SDK: Alternatively, you can consider the Alchemy SDK. This SDK enhances the ethers.js WebSocket provider by integrating heartbeat checks. These checks ensure the WebSocket reconnects if the connection gets dropped. Moreover, it incorporates a backfill logic, ensuring that events missed during reconnections are still emitted. However, a potential limitation is the dependency on Alchemy provider services.
Additionally, I found a discussion about a similar problem when using Infura provider with web3. It can be helpful as well.
Best Answer
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
(Ethers v4 is here and here)
Basically, the
on
function is what you're looking for. Using a provider, you can set up anon
to trigger something whenever a particular event is emitted. This will trigger the callback (the second argument in theon
, a function) anytime that event is emitted on the blockchain. If you are looking for theon
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:
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 callcontract
), you can also hook anon
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 fromcontract
.