Ride-The-Lightning-RTL/backend/controllers/cln/webSocketClient.js
ShahanaFarooqui e2eeb8b919 CLN Forwarding history filter and lint fixes
CLN Forwarding history filter and lint fixes
2022-08-17 15:48:04 -07:00

118 lines
6.6 KiB
JavaScript

import * as fs from 'fs';
import { join } from 'path';
import WebSocket from 'ws';
import { Logger } from '../../utils/logger.js';
import { Common } from '../../utils/common.js';
import { WSServer } from '../../utils/webSocketServer.js';
export class CLWebSocketClient {
constructor() {
this.logger = Logger;
this.common = Common;
this.wsServer = WSServer;
this.webSocketClients = [];
this.reconnectTimeOut = null;
this.waitTime = 0.5;
this.reconnet = (clWsClt) => {
if (this.reconnectTimeOut) {
return;
}
this.waitTime = (this.waitTime >= 64) ? 64 : (this.waitTime * 2);
this.reconnectTimeOut = setTimeout(() => {
if (clWsClt.selectedNode) {
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Reconnecting to the Core Lightning\'s Websocket Server..' });
this.connect(clWsClt.selectedNode);
}
this.reconnectTimeOut = null;
}, this.waitTime * 1000);
};
this.connect = (selectedNode) => {
try {
const clientExists = this.webSocketClients.find((wsc) => wsc.selectedNode.index === selectedNode.index);
if (!clientExists) {
if (selectedNode.ln_server_url) {
const newWebSocketClient = { selectedNode: selectedNode, reConnect: true, webSocketClient: null };
this.connectWithClient(newWebSocketClient);
this.webSocketClients.push(newWebSocketClient);
}
}
else {
if ((!clientExists.webSocketClient || clientExists.webSocketClient.readyState !== WebSocket.OPEN) && selectedNode.ln_server_url) {
clientExists.reConnect = true;
this.connectWithClient(clientExists);
}
}
}
catch (err) {
throw new Error(err);
}
};
this.connectWithClient = (clWsClt) => {
var _a;
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Connecting to the Core Lightning\'s Websocket Server..' });
const WS_LINK = ((_a = (clWsClt.selectedNode.ln_server_url)) === null || _a === void 0 ? void 0 : _a.replace(/^http/, 'ws')) + '/v1/ws';
const mcrnHexEncoded = Buffer.from(fs.readFileSync(join(clWsClt.selectedNode.macaroon_path, 'access.macaroon'))).toString('hex');
clWsClt.webSocketClient = new WebSocket(WS_LINK, [mcrnHexEncoded, 'hex'], { rejectUnauthorized: false });
clWsClt.webSocketClient.onopen = () => {
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Connected to the Core Lightning\'s Websocket Server..' });
this.waitTime = 0.5;
};
clWsClt.webSocketClient.onclose = (e) => {
if (clWsClt && clWsClt.selectedNode && clWsClt.selectedNode.ln_implementation === 'CLN') {
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Web socket disconnected, will reconnect again...' });
clWsClt.webSocketClient.close();
if (clWsClt.reConnect) {
this.reconnet(clWsClt);
}
}
};
clWsClt.webSocketClient.onmessage = (msg) => {
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'DEBUG', fileName: 'CLWebSocket', msg: 'Received message from the server..', data: msg.data });
msg = (typeof msg.data === 'string') ? JSON.parse(msg.data) : msg.data;
msg['source'] = 'CLN';
const msgStr = JSON.stringify(msg);
this.wsServer.sendEventsToAllLNClients(msgStr, clWsClt.selectedNode);
};
clWsClt.webSocketClient.onerror = (err) => {
if (clWsClt.selectedNode.api_version === '' || !clWsClt.selectedNode.api_version || this.common.isVersionCompatible(clWsClt.selectedNode.api_version, '0.6.0')) {
this.logger.log({ selectedNode: clWsClt.selectedNode, level: 'ERROR', fileName: 'CLWebSocket', msg: 'Web socket error', error: err });
const errStr = ((typeof err === 'object' && err.message) ? JSON.stringify({ error: err.message }) : (typeof err === 'object') ? JSON.stringify({ error: err }) : ('{ "error": ' + err + ' }'));
this.wsServer.sendErrorToAllLNClients(errStr, clWsClt.selectedNode);
clWsClt.webSocketClient.close();
if (clWsClt.reConnect) {
this.reconnet(clWsClt);
}
}
else {
clWsClt.reConnect = false;
}
};
};
this.disconnect = (selectedNode) => {
const clientExists = this.webSocketClients.find((wsc) => wsc.selectedNode.index === selectedNode.index);
if (clientExists && clientExists.webSocketClient && clientExists.webSocketClient.readyState === WebSocket.OPEN) {
this.logger.log({ selectedNode: clientExists.selectedNode, level: 'INFO', fileName: 'CLWebSocket', msg: 'Disconnecting from the Core Lightning\'s Websocket Server..' });
clientExists.reConnect = false;
clientExists.webSocketClient.close();
const clientIdx = this.webSocketClients.findIndex((wsc) => wsc.selectedNode.index === selectedNode.index);
this.webSocketClients.splice(clientIdx, 1);
}
};
this.updateSelectedNode = (newSelectedNode) => {
const clientIdx = this.webSocketClients.findIndex((wsc) => +wsc.selectedNode.index === +newSelectedNode.index);
let newClient = this.webSocketClients[clientIdx];
if (!newClient) {
newClient = { selectedNode: null, reConnect: true, webSocketClient: null };
}
newClient.selectedNode = JSON.parse(JSON.stringify(newSelectedNode));
this.webSocketClients[clientIdx] = newClient;
};
this.wsServer.eventEmitterCLN.on('CONNECT', (nodeIndex) => {
this.connect(this.common.findNode(+nodeIndex));
});
this.wsServer.eventEmitterCLN.on('DISCONNECT', (nodeIndex) => {
this.disconnect(this.common.findNode(+nodeIndex));
});
}
}
export const CLWSClient = new CLWebSocketClient();