Ethereum: Viem’s PublicClient#watchContractEvent with WSS transport: Socket closed
As developers, we all want to ensure that our Ethereum-based applications are running smoothly and securely. Recently, I encountered an issue with the PublicClient#watchContractEvent
method in my application, which led me to investigate further.
The problem lies in the way we set up the WebSocket (WSS) transport when creating a new PublicClient instance. Specifically, when using WebSockets, if the client is not created or used for an extended period of time between app startups, it can lead to socket closure issues.
The Issue
Here’s what happened:
- I created two instances of
PublicClient
with the same options (e.g., same wallet address and network).
- I then connected one instance to a WebSocket endpoint using WSS transport.
- Later on, when my app became inactive for several hours or even days, neither client was able to establish a connection to the WebSocket server.
The Solution
To resolve this issue, you need to ensure that both PublicClient instances are created with the same options and used simultaneously before entering an extended period of inactivity. Here’s how you can modify your code to achieve this:
- Create both
PublicClient
instances using the same options:
const publicClient1 = new PublicClient({
...options1,
// Same wallet address as options1
});
const publicClient2 = new PublicClient({
...options2,
// Same wallet address as options2
});
- Use both clients simultaneously before entering an extended period of inactivity:
setInterval(() => {
publicClient1.connect();
publicClient2.connect();
// Continue with your app's logic here...
}, 10000); // Connect every 10 seconds for a short duration
// When you're ready to disconnect, call disconnect
on one or both clients.
setTimeout(() => {
publicClient1.disconnect();
publicClient2.disconnect();
}, 60000); // Disconnect after 60 seconds
Additional Recommendations
To further optimize your application’s performance and reduce socket closure issues:
- Consider using a more robust WebSocket library that provides better error handling and connection management, such as
ws
orwebsocket-client
.
- Implement a more advanced polling mechanism to detect when the client is no longer connected. You can use libraries like
connect-socket-poller
to create a custom poller.
- Regularly clean up stale connections by periodically disconnecting disconnected clients.
By following these recommendations, you should be able to resolve the issue with the PublicClient#watchContractEvent
method and ensure that your Ethereum-based applications run smoothly and securely.