ethers-io / ethers.js

Complete Ethereum library and wallet implementation in JavaScript.
https://ethers.org/
MIT License
7.97k stars 1.85k forks source link

TypeError being thrown when creating multiple WebSocketProvider instances #2658

Open DomenicCrypto opened 2 years ago

DomenicCrypto commented 2 years ago

Describe the bug When creating multiple web socket providers (i.e. via new ethers.providers.WebSocketProvider()), the second one always causes a crash.

The crash is a TypeError and it seems to be coming from the line request.callback(null, result.result) inside @ethersproject\providers\lib\websocket-provider.js:112.

Full stack trace:

@ethersproject\providers\lib\websocket-provider.js:112
                    request.callback(null, result.result);
                            ^

TypeError: Cannot read properties of undefined (reading 'callback')
    at WebSocketProvider._this._websocket.onmessage (node_modules\@ethersproject\providers\lib\websocket-provider.js:112:29)
    at WebSocket.onMessage (node_modules\ws\lib\event-target.js:132:16)       
    at WebSocket.emit (node:events:390:28)
    at Receiver.receiverOnMessage (node_modules\ws\lib\websocket.js:834:20)   
    at Receiver.emit (node:events:390:28)
    at Receiver.dataMessage (node_modules\ws\lib\receiver.js:437:14)
    at Receiver.getData (node_modules\ws\lib\receiver.js:367:17)
    at Receiver.startLoop (node_modules\ws\lib\receiver.js:143:22)
    at Receiver._write (node_modules\ws\lib\receiver.js:78:10)
    at writeOrBuffer (node:internal/streams/writable:389:12)

To repoduce it you just need to connect to two WebSocketProvider's. I created an isolated test, and this reproduces the bug everytime:

async main(args: string[]) {
    const moralisWs = 'wss://*';
    const quickNodeWs = 'wss://*';
    const providerOne = new ethers.providers.WebSocketProvider(moralisWs)
    const providerTwo = new ethers.providers.WebSocketProvider(quickNodeWs)
}

What makes this super strange to me, is that it has been working all week - it just suddenly stopped! I thought I might be rate limited by the service that I am using, but when connecting individually to the seperate websockets my app works fine. Also when reordering them, the first one is always fine.

Environment: I am using a simple NodeJS/Typescript environment, and connecting to Moralis and QuickNode BSC nodes using WSS URLs.

My package.json to see the versions:

{
  "dependencies": {
    "@ethersproject/providers": "^5.5.3",
    "@ethersproject/units": "^5.1.0",
    "@types/node": "^17.0.8",
    "dotenv": "^16.0.0",
    "ethers": "^5.5.4",
    "node-fetch": "^2.6.6",
    "typescript": "^4.5.4",
    "web3": "^1.2.11",
    "winston": "^3.4.0"
  }
}

I am not sure if I am doing something wrong or dumb, so let me know if I can do something different! Cheers.

DomenicCrypto commented 2 years ago

Would also like to add that the error thrown is uncatchable when surrounding in a try/catch block

coding-velociraptor commented 1 year ago

@DomenicCrypto I'm running into this issue right now. Have you found a workaround?

freeatnet commented 1 year ago

It looks like the issue is back; Alchemy WebSocket provider responds with request ID 0 when a request is rate-limited. Here's a sample sequence of responses:

{
    "jsonrpc": "2.0",
    "id": 112,
    "result": "0x0000000000000000000000004976fb03c32e5b8cfe2b6ccb31c09ba78ebaba41"
}

{
    "jsonrpc": "2.0",
    "id": 0,
    "error": {
        "code": 429,
        "message": "Your app has exceeded its compute units per second capacity. If you have retries enabled, you can safely ignore this message. If not, check out https://docs.alchemy.com/reference/throughput"
    }
}

{
    "jsonrpc": "2.0",
    "id": 124,
    "result": "0x000000000000000000000000dad1d029d7ab8142beb1b882c9cad7c02da6a165"
}

I think the solution could be to ignore the errant response — or maybe to handle it with a logger warning rather than an exception. @ricmoo would you open to a patch?

Quix44 commented 1 year ago

Bump, Strangely, this is happening more often now.

ricmoo commented 1 year ago

@Quix44 Have you tried v6? A lot of the work in v6 was to abstract the WebSocket (and similar) provider.

In v5, the provider sub-class did not have great deal of flexibility to deal with socket-based providers. This was remedied in v6.

philosofonusus commented 1 year ago

Also happens for me using quicknode

ahyammona commented 9 months ago

facing the same issue