Draining Connection. 4040

how often does it happen?

depends, sometimes every 20 minutes than it runs for an hour or 2 but i have never had a connection running for more than 8 hours

OSError: Multiple exceptions: [Errno 111] Connect call failed (‘104.18.16.45’, 443), [Errno 111] Connect call failed (‘104.18.17.45’, 443), [Errno 101] Network is unreachable, [Errno 101] Network is unr
eachable

This is the error I get when running from pythonanywhere

And when running from my terminal I get this
websockets.exceptions.ConnectionClosedError: code = 4040 (private use), reason = Draining connection

I fixed above issue with this trick
So right now i run my script on pythonanywhere always-up and this seems to do the trick because it automatically restarts the script if it crashes

Actually its not working
Hopefully someone has a fix for this

Ok new update
when i run my script on a paid account on pythonanywhere
where I run my script as “always-on” task, the connection issue disapears because whenever it crashes it will restart.

When connecting to avalanche websocket I also get this error
websockets.exceptions.ConnectionClosedError: code = 4040 (private use), reason = Draining connection

2021-11-30T08:56:45.285696+00:00 app[arbitrage.1]:     at WebSocketConnection.emit (events.js:400:28)

2021-11-30T08:56:45.285696+00:00 app[arbitrage.1]:     at WebSocketConnection.handleSocketClose (/app/node_modules/websocket/lib/WebSocketConnection.js:389:14)

2021-11-30T08:56:45.285697+00:00 app[arbitrage.1]:     at TLSSocket.emit (events.js:412:35)

2021-11-30T08:56:45.285697+00:00 app[arbitrage.1]:     at net.js:686:12

2021-11-30T08:56:45.285698+00:00 app[arbitrage.1]:     at TCP.done (_tls_wrap.js:564:7) {

2021-11-30T08:56:45.285698+00:00 app[arbitrage.1]:   code: 4040,

2021-11-30T08:56:45.285698+00:00 app[arbitrage.1]:   reason: 'Draining connection'

2021-11-30T08:56:45.285699+00:00 app[arbitrage.1]: }

2021-11-30T08:56:45.498389+00:00 heroku[arbitrage.1]: Process exited with status 0

2021-11-30T08:56:45.571632+00:00 heroku[arbitrage.1]: State changed from up to crashed

2021-11-30T10:11:35.303205+00:00 heroku[arbitrage.1]: State changed from crashed to starting

2021-11-30T10:11:39.218702+00:00 heroku[arbitrage.1]: Starting process with command `node bscFlashArb1.js`

2021-11-30T10:11:39.788533+00:00 heroku[arbitrage.1]: State changed from starting to up

2021-11-30T10:16:37.187777+00:00 heroku[arbitrage.1]: Process exited with status 0

2021-11-30T10:16:37.289534+00:00 heroku[arbitrage.1]: State changed from up to crashed

2021-11-30T10:16:37.018779+00:00 app[arbitrage.1]: Error: CONNECTION ERROR: The connection got closed with the close code `4040` and the following reason string `Draining connection`

2021-11-30T10:16:37.018791+00:00 app[arbitrage.1]:     at Object.ConnectionError (/app/node_modules/web3-core-helpers/lib/errors.js:66:23)

2021-11-30T10:16:37.018791+00:00 app[arbitrage.1]:     at Object.ConnectionCloseError (/app/node_modules/web3-core-helpers/lib/errors.js:53:25)

2021-11-30T10:16:37.018792+00:00 app[arbitrage.1]:     at /app/node_modules/web3-core-requestmanager/lib/index.js:119:50

2021-11-30T10:16:37.018792+00:00 app[arbitrage.1]:     at Map.forEach (<anonymous>)

2021-11-30T10:16:37.018793+00:00 app[arbitrage.1]:     at WebsocketProvider.disconnect (/app/node_modules/web3-core-requestmanager/lib/index.js:118:37)

2021-11-30T10:16:37.018793+00:00 app[arbitrage.1]:     at WebsocketProvider.emit (/app/node_modules/eventemitter3/index.js:181:35)

2021-11-30T10:16:37.018793+00:00 app[arbitrage.1]:     at WebsocketProvider._onClose (/app/node_modules/web3-providers-ws/lib/index.js:152:10)

2021-11-30T10:16:37.018794+00:00 app[arbitrage.1]:     at W3CWebSocket._dispatchEvent [as dispatchEvent] (/app/node_modules/yaeti/lib/EventTarget.js:115:12)

2021-11-30T10:16:37.018794+00:00 app[arbitrage.1]:     at W3CWebSocket.onClose (/app/node_modules/websocket/lib/W3CWebSocket.js:228:10)

2021-11-30T10:16:37.018794+00:00 app[arbitrage.1]:     at WebSocketConnection.<anonymous> (/app/node_modules/websocket/lib/W3CWebSocket.js:201:17)

2021-11-30T10:16:37.018795+00:00 app[arbitrage.1]:     at WebSocketConnection.emit (events.js:400:28)

2021-11-30T10:16:37.018795+00:00 app[arbitrage.1]:     at WebSocketConnection.handleSocketClose (/app/node_modules/websocket/lib/WebSocketConnection.js:389:14)

2021-11-30T10:16:37.018795+00:00 app[arbitrage.1]:     at TLSSocket.emit (events.js:412:35)

2021-11-30T10:16:37.018795+00:00 app[arbitrage.1]:     at net.js:686:12

2021-11-30T10:16:37.018796+00:00 app[arbitrage.1]:     at TCP.done (_tls_wrap.js:564:7) {

2021-11-30T10:16:37.018796+00:00 app[arbitrage.1]:   code: 4040,

2021-11-30T10:16:37.018797+00:00 app[arbitrage.1]:   reason: 'Draining connection'

2021-11-30T10:16:37.018797+00:00 app[arbitrage.1]: }

2021-11-30T10:16:37.024479+00:00 app[arbitrage.1]: Error: CONNECTION ERROR: Couldn't connect to node on WS.

2021-11-30T10:16:37.024480+00:00 app[arbitrage.1]:     at Object.ConnectionError (/app/node_modules/web3-core-helpers/lib/errors.js:66:23)

2021-11-30T10:16:37.024480+00:00 app[arbitrage.1]:     at Object.InvalidConnection (/app/node_modules/web3-core-helpers/lib/errors.js:36:21)

2021-11-30T10:16:37.024481+00:00 app[arbitrage.1]:     at /app/node_modules/web3-providers-ws/lib/index.js:161:37

2021-11-30T10:16:37.024481+00:00 app[arbitrage.1]:     at Map.forEach (<anonymous>)

2021-11-30T10:16:37.024481+00:00 app[arbitrage.1]:     at WebsocketProvider._onClose (/app/node_modules/web3-providers-ws/lib/index.js:160:28)

2021-11-30T10:16:37.024482+00:00 app[arbitrage.1]:     at W3CWebSocket._dispatchEvent [as dispatchEvent] (/app/node_modules/yaeti/lib/EventTarget.js:115:12)

2021-11-30T10:16:37.024483+00:00 app[arbitrage.1]:     at W3CWebSocket.onClose (/app/node_modules/websocket/lib/W3CWebSocket.js:228:10)

2021-11-30T10:16:37.024483+00:00 app[arbitrage.1]:     at WebSocketConnection.<anonymous> (/app/node_modules/websocket/lib/W3CWebSocket.js:201:17)

2021-11-30T10:16:37.024483+00:00 app[arbitrage.1]:     at WebSocketConnection.emit (events.js:400:28)

2021-11-30T10:16:37.024484+00:00 app[arbitrage.1]:     at WebSocketConnection.handleSocketClose (/app/node_modules/websocket/lib/WebSocketConnection.js:389:14)

2021-11-30T10:16:37.024484+00:00 app[arbitrage.1]:     at TLSSocket.emit (events.js:412:35)

2021-11-30T10:16:37.024485+00:00 app[arbitrage.1]:     at net.js:686:12

2021-11-30T10:16:37.024486+00:00 app[arbitrage.1]:     at TCP.done (_tls_wrap.js:564:7) {

2021-11-30T10:16:37.024486+00:00 app[arbitrage.1]:   code: 4040,

2021-11-30T10:16:37.024487+00:00 app[arbitrage.1]:   reason: 'Draining connection'

2021-11-30T10:16:37.024487+00:00 app[arbitrage.1]: }

Disconnected from log stream. There may be events happening that you do not see here! Attempting to reconnect...

2021-11-30T10:16:37.024483+00:00 app[arbitrage.1]:     at WebSocketConnection.emit (events.js:400:28)

2021-11-30T10:16:37.024484+00:00 app[arbitrage.1]:     at WebSocketConnection.handleSocketClose (/app/node_modules/websocket/lib/WebSocketConnection.js:389:14)

2021-11-30T10:16:37.024484+00:00 app[arbitrage.1]:     at TLSSocket.emit (events.js:412:35)

2021-11-30T10:16:37.024485+00:00 app[arbitrage.1]:     at net.js:686:12

2021-11-30T10:16:37.024486+00:00 app[arbitrage.1]:     at TCP.done (_tls_wrap.js:564:7) {

2021-11-30T10:16:37.024486+00:00 app[arbitrage.1]:   code: 4040,

2021-11-30T10:16:37.024487+00:00 app[arbitrage.1]:   reason: 'Draining connection'

2021-11-30T10:16:37.024487+00:00 app[arbitrage.1]: }

2021-11-30T10:16:37.187777+00:00 heroku[arbitrage.1]: Process exited with status 0

2021-11-30T10:16:37.289534+00:00 heroku[arbitrage.1]: State changed from up to crashed

2021-11-30T10:50:55.859675+00:00 heroku[arbitrage.1]: State changed from crashed to starting

2021-11-30T10:50:58.714643+00:00 heroku[arbitrage.1]: Starting process with command `node bscFlashArb1.js`

2021-11-30T10:50:59.312175+00:00 heroku[arbitrage.1]: State changed from starting to up
I created a flashloan bot for arbitrage (on bsc) and deployed it to heroku. The bot keeps crashing with the same error (draining connection error 400). 
Here is the hole script:

require('dotenv').config();
const Web3 = require('web3');
const abis = require('./abis');
const { mainnet: addresses } = require('./addresses');

const web3 = new Web3(
    new Web3.providers.WebsocketProvider(process.env.MORALIS_WSS_URL)
);

// const web3 = new Web3(
//     new Web3.providers.WebsocketProvider(process.env.BSC_WSS_URL)
// );


const { address: admin } = web3.eth.accounts.wallet.add(process.env.PRIVATE_KEY);

const AMOUNT_DAI_WEI = web3.utils.toBN(web3.utils.toWei('THE_AMOUNT_YOU_WANT_TO_BORROW'));

const init = async () => {

    const BscFlashArb1 = new web3.eth.Contract(
        abis.bscFlashArb1.abi,
        addresses.bscFlashArb1.addr
    );

    const PancakeSwap = new web3.eth.Contract(
        abis.pancakeSwap.router,
        addresses.pancakeSwap.router
    );

    const BakerySwap = new web3.eth.Contract(
        abis.bakerySwap.router,
        addresses.bakerySwap.router
    );

    web3.eth.subscribe('newBlockHeaders')
    .on('data', async block => {
        try {

            // borrow DAI from pancakeswap and sell it on
            // bakeryswap. Repay in WBNB. Keep the profit in WBNB
            const [amountsIn1, amountsOut1] = await Promise.all([
                PancakeSwap.methods
                .getAmountsIn(
                    AMOUNT_DAI_WEI,
                    [addresses.tokens.WBNB, addresses.tokens.DAI]
                ).call(),
                BakerySwap.methods
                .getAmountsOut(
                    AMOUNT_DAI_WEI,
                    [addresses.tokens.DAI, addresses.tokens.WBNB]
                ).call()
            ]);

            const profit_in_WBNB = web3.utils.toBN(amountsOut1[1]).sub(web3.utils.toBN(amountsIn1[0]));

             // borrow WBNB from pancakeswap and sell it on
             // bakeryswap. Repay in DAI. Keep the profit in DAI
            const AMOUNT_WBNB_WEI = await PancakeSwap
                .methods
                .getAmountsOut(
                    AMOUNT_DAI_WEI,
                    [addresses.tokens.DAI, addresses.tokens.WBNB]
                ).call();

             
            const [amountsIn2, amountsOut2] = await Promise.all([            
              PancakeSwap
                .methods
                .getAmountsIn(
                    AMOUNT_WBNB_WEI[1],
                    [addresses.tokens.DAI, addresses.tokens.WBNB]
                ).call(),
              BakerySwap
                .methods
                .getAmountsOut(
                    AMOUNT_WBNB_WEI[1],
                    [addresses.tokens.WBNB, addresses.tokens.DAI]
                ).call()
            ]);

            const profit_in_DAI = web3.utils.toBN(amountsOut2[1]).sub(web3.utils.toBN(amountsIn2[0]));

            // arbitrage borrowing DAI
            if (profit_in_WBNB > 0) { 

                const tx = BscFlashArb1.methods.startArbitrage(
                  addresses.tokens.DAI,
                  addresses.tokens.WBNB,
                  AMOUNT_DAI_WEI,
                  0
                );

                const [gasPrice, gasCost] = await Promise.all([
                    web3.eth.getGasPrice(),
                    tx.estimateGas({from: admin})
                ]);

                const gas =  web3.utils.toBN(gasCost).add(
                    web3.utils.toBN(gasCost).div(web3.utils.toBN('20'))
                );

                const txCost = gas.mul(web3.utils.toBN(gasPrice));
                const profit = profit_in_WBNB.sub(txCost);

                if(profit.gte(txCost)) {

                    console.log('Arb opportunity found. Borrow DAI. Repay in WBNB!');
                    console.log(`Expected profit: ${web3.utils.fromWei(profit)} Dai`);

                    const data = tx.encodeABI();
                          const txData = {
                            from: admin,
                            to: addresses.bscFlashArb1.addr,
                            data,
                            gas,
                            gasPrice
                    };

                    const receipt = await web3.eth.sendTransaction(txData);
                    console.log(`Transaction hash: ${receipt.transactionHash}`);
                }
            }

            // arbitrage borrowing WBNB
            if (profit_in_DAI > 0) {

                const tx = BscFlashArb1.methods.startArbitrage(
                  addresses.tokens.DAI,
                  addresses.tokens.WBNB,
                  0,
                  AMOUNT_WBNB_WEI
                );

                const [gasPrice, gasCost] = await Promise.all([
                    web3.eth.getGasPrice(),
                    tx.estimateGas({from: admin})
                ]);

                const gas =  web3.utils.toBN(gasCost).add(
                    web3.utils.toBN(gasCost).div(web3.utils.toBN('20'))
                );

                const txCost = gas.mul(web3.utils.toBN(gasPrice));
                const txCost_in_Dai = web3.utils.toBN(amountsOut2[1]).mul(txCost).div(AMOUNT_WBNB_WEI[1]);
                const profit = profit_in_DAI.sub(txCost_in_Dai);

                if(profit.gte(web3.utils.toBN('0'))) {

                    console.log('Arb opportunity found. Borrow WBNB. Repay in DAI!');
                    console.log(`Expected profit: ${web3.utils.fromWei(profit)} Dai`);

                    const data = tx.encodeABI();
                          const txData = {
                            from: admin,
                            to: addresses.bscFlashArb1.addr,
                            data,
                            gas,
                            gasPrice
                    };

                    const receipt = await web3.eth.sendTransaction(txData);
                    console.log(`Transaction hash: ${receipt.transactionHash}`);
                }

            }

            // console.log('running...')
        } catch (error) {
            console.error(error);
        }
    })
    .on('error', error => {
        console.log(error);
    });

}
init();

I noticed that most of time the app runs well. It crashes only when there is an arbitrage opportunity (when the code in one of the main if statments runs). I can’t figure out why It happens.
I made some research about draining connections. AWS uses it a lot. If the moralis servers are hosted on AWS, maybe this errore comes frome AWS servers configurations.

from what I know DRAINING CONNECTION error should happen when the node that you are connecting to will go offline

you mean that the error comes when you try to send a transaction?

or you can not even connect to web socket at that time?

‘Whole script’ instead of “hole script”

I lose the connection at that time. It disconnects.

It happens even before I try to send the transaction. i.e., when I try to estimate the gas price and the gas cost.

ok, can you try to estimate the gas price and gas cost separately to see if it works without problems?

I tried and I got the following error:

Error: Returned error: execution reverted: Unauthorized

here is the full log:

Error: Returned error: execution reverted: Unauthorized
    at Object.ErrorResponse (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/web3-core-helpers/lib/errors.js:28:19)
    at Object.callback (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/web3-core-requestmanager/lib/index.js:302:36)
    at /home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/web3-providers-ws/lib/index.js:114:45
    at Array.forEach (<anonymous>)
    at WebsocketProvider._onMessage (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/web3-providers-ws/lib/index.js:102:69)
    at W3CWebSocket._dispatchEvent [as dispatchEvent] (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/yaeti/lib/EventTarget.js:115:12)
    at W3CWebSocket.onMessage (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/websocket/lib/W3CWebSocket.js:234:14)
    at WebSocketConnection.<anonymous> (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/websocket/lib/W3CWebSocket.js:205:19)
    at WebSocketConnection.emit (events.js:400:28)
    at WebSocketConnection.processFrame (/home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/websocket/lib/WebSocketConnection.js:554:26)
    at /home/akmb/dev/prod/portfolio_projects/bscFlashArbV0.0.1/node_modules/websocket/lib/WebSocketConnection.js:323:40
    at processTicksAndRejections (internal/process/task_queues.js:77:11) {
  data: '0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c556e617574686f72697a65640000000000000000000000000000000000000000'
}

I was able to run eth_estimateGas call for test now with different parameters, what function did you call there in particular?

In my script, I’m not using moralis SDK. I’m using just the web soket to connect the bsc.
Here is the lines I used now to estimate gas price and gas cost, separately:

const tx = BscFlashArb1.methods.startArbitrage(
                  addresses.tokens.DAI,
                  addresses.tokens.WBNB,
                  AMOUNT_DAI_WEI,
                  0
                );

                const gasPrice = await web3.eth.getGasPrice();

                const gasCost = await tx.estimateGas({from: admin});

                console.log(`gas price: ${gasPrice}, gas cost: ${gasCost}`);

this is on a lower level than what you have there, it is not Moralis SDK :slight_smile:

on what line it fails?
web3.eth.getGasPrice() or tx.estimateGas ?

It estimates gas price correctly.
It fails to estimate the gas cost and returns an error: Error: Returned error: execution reverted: Unauthorized

what kind of web socket url are you using? archive, non archive?
that Unauthorized error sounds like it is trying to run a node command that is not on a whitelist of supported commands

I’m using a non archive node.

and you are doing this on bsc, right?
if you use process.env.BSC_WSS_URL for gas estimation then it works?

I tried it now: same error! :open_mouth:
I really didn’t expect that.
I will try to make a transaction to see the actual gas cost. Then I will increase it by some percentage and hard code it in the script to see what will happen.
Thank you for your help. I’m very grateful.