@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
106 lines • 3.9 kB
JavaScript
// Copied from https://github.com/LedgerHQ/eth-dapp-browser/blob/main/src/DAPPBrowserV2/SmartWebsocket.ts
import EventEmitter from "events";
const DEFAULT_RECONNECT = false;
const DEFAULT_RECONNECT_DELAY = 5000;
const DEFAULT_RECONNECT_MAX_ATTEMPTS = 3;
function logger(message, ...args) {
// eslint-disable-next-line no-console
console.log(`%c[WEBSOCKET] ${message}`, "background: #eee; color: #F70", ...args);
}
export class SmartWebsocket extends EventEmitter {
ws = null;
url;
reconnectAttempts = 0;
_connected = false;
reconnect;
reconnectMaxAttempts;
reconnectDelay;
logger;
constructor(url, options) {
super();
this.url = url;
this.logger = options?.logger || logger;
this.reconnect = options?.reconnect || DEFAULT_RECONNECT;
this.reconnectMaxAttempts = options?.reconnectMaxAttempts || DEFAULT_RECONNECT_MAX_ATTEMPTS;
this.reconnectDelay = options?.reconnectDelay || DEFAULT_RECONNECT_DELAY;
}
async connect() {
if (this._connected) {
return this._connected;
}
if (this.reconnectAttempts) {
this.emit("reconnecting");
this.logger(`reconnecting (${this.reconnectAttempts}/${this.reconnectMaxAttempts})`);
}
else {
this.emit("connecting");
this.logger(`connecting to ${this.url}`);
}
this._connected = new Promise((resolve, reject) => {
try {
const ws = new WebSocket(this.url);
ws.onopen = () => {
this.emit("connected");
this.logger("connected");
resolve(ws);
this.reconnectAttempts = 0;
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
this.emit("message", message);
this.logger("message", message);
};
ws.onclose = event => {
this.ws = null;
this._connected = false;
this.logger("disconnected", event);
this.emit("disconnected");
if (this.reconnect && !event.wasClean) {
if (this.reconnectAttempts < this.reconnectMaxAttempts) {
this.reconnectAttempts++;
this.logger("will reconnect in 5s");
setTimeout(() => {
this.connect().then(resolve).catch(reject);
}, this.reconnectDelay);
}
else {
reject(new Error(`Max reconnect attempts reached (${this.reconnectMaxAttempts})`));
this.logger(`Max reconnect attempts reached (${this.reconnectMaxAttempts})`);
this.reconnectAttempts = 0;
}
}
else {
reject();
}
};
this.ws = ws;
}
catch (error) {
reject(error);
}
});
return this._connected;
}
async connected() {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
return this.ws;
}
else if (this._connected) {
return this._connected;
}
return this.connect();
}
async send(message) {
const ws = await this.connected();
ws.send(JSON.stringify(message));
this.logger("sent", message);
}
close() {
if (this.ws) {
this.logger("closing");
this.ws.close(1000, "terminated");
}
this._connected = false;
}
}
//# sourceMappingURL=SmartWebsocket.js.map