Seems that removeAllListener method isn't removing listeners properly.
I've written the test case below to simulate the expected behavior and how it seems wrong.
Tested on ethers.js 4.0.12 and 4.0.20 versions.
it("ethers.js removeAllListeners bug - listeners remain registered", async () => {
const eventFakeFn = sinon.fake();
const sentTx = await contract.setValue("hello world");
let eventListener;
await new Promise(function(resolve, reject) {
eventListener = () => {
eventFakeFn();
resolve();
};
contract.on("ValueChanged", eventListener);
});
// Not working
contract.removeAllListeners("ValueChanged");
// Working
// contract.removeListener("ValueChanged", eventListener);
expect(eventFakeFn.called).to.be.true;
expect(contract.listenerCount("ValueChanged")).to.equal(0);
expect(contract.provider._events).to.be.empty;
});
Thanks
Ack! Looking at the contract code, I believe you are correct; I do not pass the de-registration onto the provider, just remove it from the member events list. I will look into this shortly.
Thanks! :)
Ok. I have a simple example running. Just to confirm, your problem is not that events are being triggered after being removed. The problem is that the listener lingers, and therefore doesn't shut down the process, correct?
Yes, the process still runs and contract.provider._events remains with an event even after removal.
I've not checked if the event is being triggered after remove but seems that didn't.
Can you try out 4.0.21 and see if that solves your problem?
Thanks! :)
It's working now.
Thank you!
Awesome!!
Thanks! :)
This is still a problem using the latest version 5.0.32 I am unable to stop/remove ongoing listeners
@JefferyHus the most recent version is 5.2.0. Can you try that and let me know? I don’t think anything regarding this should have changed though…
If it is still a problem, can you please include some minimum code that reproduces it?
@ricmoo
factory = new ethers.Contract(
addresses.factory,
[
'event PairCreated(address indexed token0, address indexed token1, address pair, uint)'
],
account,
);
factory.on('PairCreated', async (token0, token1, pairAddress) => {
// do things here
// if done
factory.off('PairCreated'); // this fails, I even did this factory.removeAllListeners(); and I can still see the event registred
});
This is not working at all
@JefferyHus if you want to execute an event once, you can do factory.once('PairCreated', callback).
Also in your example, can you confirm if the condition in your if statement is true? so that the flow actually goes in and factory.off is done
My conditions do execute. I don't want to run it once but I should keep it running till I find the proper pair.
I tried this last week and did find there might possibly be a bug. I will test this again tomorrow. Are you using an address or ens name for the contract address?
running into this issue right now also... any updates?
Most helpful comment
It's working now.
Thank you!