@atomiqlabs/chain-evm
Version:
EVM specific base implementation
92 lines (91 loc) • 4.12 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReconnectingWebSocketProvider = void 0;
const SocketProvider_1 = require("./SocketProvider");
const Utils_1 = require("../../utils/Utils");
const logger = (0, Utils_1.getLogger)("ReconnectingWebSocketProvider: ");
class ReconnectingWebSocketProvider extends SocketProvider_1.SocketProvider {
constructor(url, network, options) {
super(network, options);
this.requestTimeoutSeconds = 10;
this.reconnectSeconds = 5;
this.pingIntervalSeconds = 30;
this.connectionTimeout = 10;
this.wsCtor = typeof (url) === "string" ? () => new WebSocket(url) : url;
this.connect();
}
connect() {
this.websocket = this.wsCtor();
this.websocket.onopen = () => {
this._connected();
this._start();
clearTimeout(this.connectTimer);
this.connectTimer = null;
this.pingInterval = setInterval(() => {
this._send({ method: "eth_chainId", params: [], id: 1000000000, jsonrpc: "2.0" }).catch(e => {
//Error
if (e.code === "NETWORK_ERROR") {
logger.error("connect(): pingInterval: Websocket ping error: ", e);
if (this.websocket != null) {
this.websocket.close();
this.disconnectedAndScheduleReconnect();
}
}
});
}, this.pingIntervalSeconds * 1000);
logger.info("connect(): Websocket connected!");
};
this.websocket.onerror = (err) => {
logger.error(`connect(): onerror: Websocket connection error: `, err.error ?? err);
this.disconnectedAndScheduleReconnect();
};
this.websocket.onmessage = (message) => {
this._processMessage(message.data);
};
this.websocket.onclose = (event) => {
logger.error(`connect(): onclose: Websocket connection closed: `, event);
this.disconnectedAndScheduleReconnect();
};
this.connectTimer = setTimeout(() => {
logger.warn("connect(): Websocket connection taking too long, (above " + this.connectionTimeout + " seconds!), closing and re-attempting connection");
this.websocket.close();
this.disconnectedAndScheduleReconnect();
}, this.connectionTimeout * 1000);
}
disconnectedAndScheduleReconnect() {
if (this.destroyed)
return;
if (this.websocket == null)
return;
this.websocket.onclose = null;
//Register dummy handler, otherwise we get unhandled `error` event which crashes the whole thing
this.websocket.onerror = (err) => logger.error("disconnectedAndScheduleReconnect(): Post-close onerror: ", err.error ?? err);
this.websocket.onmessage = null;
this.websocket.onopen = null;
this.websocket = null;
if (this.pingInterval != null)
clearInterval(this.pingInterval);
if (this.connectTimer != null)
clearInterval(this.connectTimer);
this._disconnected();
logger.info(`disconnectedAndScheduleReconnect(): Retrying in ${this.reconnectSeconds} seconds...`);
this.reconnectTimer = setTimeout(() => this.connect(), this.reconnectSeconds * 1000);
}
async _write(message) {
this.websocket.send(message);
}
async destroy() {
if (this.websocket != null) {
this.websocket.close();
this.websocket = null;
}
if (this.reconnectTimer != null)
clearTimeout(this.reconnectTimer);
if (this.pingInterval != null)
clearInterval(this.pingInterval);
if (this.connectTimer != null)
clearInterval(this.connectTimer);
super.destroy();
}
}
exports.ReconnectingWebSocketProvider = ReconnectingWebSocketProvider;