2023-12-05 20:32:05 -08:00
import socketIOClient from 'socket.io-client' ;
2021-12-29 18:08:41 -05:00
import { Logger , LoggerService } from '../../utils/logger.js' ;
import { Common , CommonService } from '../../utils/common.js' ;
import { WSServer } from '../../utils/webSocketServer.js' ;
2024-06-10 12:40:37 -07:00
import { SelectedNode } from '../../models/config.model.js' ;
2021-12-29 18:08:41 -05:00
export class CLWebSocketClient {
public logger : LoggerService = Logger ;
public common : CommonService = Common ;
public wsServer = WSServer ;
2024-06-10 12:40:37 -07:00
public webSocketClients : Array < { selectedNode : SelectedNode , reConnect : boolean , webSocketClient : any } > = [ ] ;
2021-12-29 18:08:41 -05:00
public reconnectTimeOut = null ;
public waitTime = 0.5 ;
constructor ( ) {
2022-05-01 13:35:20 -04:00
this . wsServer . eventEmitterCLN . on ( 'CONNECT' , ( nodeIndex ) = > {
2021-12-29 18:08:41 -05:00
this . connect ( this . common . findNode ( + nodeIndex ) ) ;
} ) ;
2022-05-01 13:35:20 -04:00
this . wsServer . eventEmitterCLN . on ( 'DISCONNECT' , ( nodeIndex ) = > {
2021-12-29 18:08:41 -05:00
this . disconnect ( this . common . findNode ( + nodeIndex ) ) ;
} ) ;
}
2023-12-05 20:32:05 -08:00
public reconnect = ( clWsClt ) = > {
2021-12-29 18:08:41 -05:00
if ( this . reconnectTimeOut ) { return ; }
this . waitTime = ( this . waitTime >= 64 ) ? 64 : ( this . waitTime * 2 ) ;
this . reconnectTimeOut = setTimeout ( ( ) = > {
if ( clWsClt . selectedNode ) {
2022-05-01 13:35:20 -04:00
this . logger . log ( { selectedNode : clWsClt.selectedNode , level : 'INFO' , fileName : 'CLWebSocket' , msg : 'Reconnecting to the Core Lightning\'s Websocket Server..' } ) ;
2021-12-29 18:08:41 -05:00
this . connect ( clWsClt . selectedNode ) ;
}
this . reconnectTimeOut = null ;
} , this . waitTime * 1000 ) ;
} ;
2024-06-10 12:40:37 -07:00
public connect = ( selectedNode : SelectedNode ) = > {
2021-12-29 18:08:41 -05:00
try {
const clientExists = this . webSocketClients . find ( ( wsc ) = > wsc . selectedNode . index === selectedNode . index ) ;
if ( ! clientExists ) {
2024-06-10 12:40:37 -07:00
if ( selectedNode . settings . lnServerUrl ) {
2021-12-29 18:08:41 -05:00
const newWebSocketClient = { selectedNode : selectedNode , reConnect : true , webSocketClient : null } ;
this . connectWithClient ( newWebSocketClient ) ;
this . webSocketClients . push ( newWebSocketClient ) ;
}
} else {
2024-06-10 12:40:37 -07:00
if ( ( ! clientExists . webSocketClient || ! clientExists . webSocketClient . connected ) && selectedNode . settings . lnServerUrl ) {
2021-12-29 18:08:41 -05:00
clientExists . reConnect = true ;
this . connectWithClient ( clientExists ) ;
}
}
2022-12-27 18:05:42 -08:00
} catch ( err : any ) {
2021-12-29 18:08:41 -05:00
throw new Error ( err ) ;
}
} ;
public connectWithClient = ( clWsClt ) = > {
2022-05-01 13:35:20 -04:00
this . logger . log ( { selectedNode : clWsClt.selectedNode , level : 'INFO' , fileName : 'CLWebSocket' , msg : 'Connecting to the Core Lightning\'s Websocket Server..' } ) ;
2023-12-05 20:32:05 -08:00
try {
2024-06-10 12:40:37 -07:00
if ( ! clWsClt . selectedNode . authentication . runeValue ) {
clWsClt . selectedNode . authentication . runeValue = this . common . getRuneValue ( clWsClt . selectedNode . authentication . runePath ) ;
2023-12-05 20:32:05 -08:00
}
2024-06-10 12:40:37 -07:00
clWsClt . webSocketClient = socketIOClient ( clWsClt . selectedNode . settings . lnServerUrl , {
extraHeaders : { rune : clWsClt.selectedNode.authentication.runeValue } ,
2023-12-05 20:32:05 -08:00
transports : [ 'websocket' ] ,
secure : true ,
rejectUnauthorized : false
} ) ;
} catch ( err ) {
throw new Error ( err ) ;
}
2021-12-29 18:08:41 -05:00
2023-12-05 20:32:05 -08:00
clWsClt . webSocketClient . on ( 'connect' , ( ) = > {
2022-05-01 13:35:20 -04:00
this . logger . log ( { selectedNode : clWsClt.selectedNode , level : 'INFO' , fileName : 'CLWebSocket' , msg : 'Connected to the Core Lightning\'s Websocket Server..' } ) ;
2021-12-29 18:08:41 -05:00
this . waitTime = 0.5 ;
2023-12-05 20:32:05 -08:00
} ) ;
2021-12-29 18:08:41 -05:00
2023-12-05 20:32:05 -08:00
clWsClt . webSocketClient . on ( 'disconnect' , ( reason ) = > {
2024-06-10 12:40:37 -07:00
if ( clWsClt && clWsClt . selectedNode && clWsClt . selectedNode . lnImplementation === 'CLN' ) {
2023-12-05 20:32:05 -08:00
this . logger . log ( { selectedNode : clWsClt.selectedNode , level : 'INFO' , fileName : 'CLWebSocket' , msg : 'Web socket disconnected, will reconnect again...' , data : reason } ) ;
2021-12-29 18:08:41 -05:00
clWsClt . webSocketClient . close ( ) ;
2023-12-05 20:32:05 -08:00
if ( clWsClt . reConnect ) { this . reconnect ( clWsClt ) ; }
2021-12-29 18:08:41 -05:00
}
2023-12-05 20:32:05 -08:00
} ) ;
2021-12-29 18:08:41 -05:00
2023-12-05 20:32:05 -08:00
clWsClt . webSocketClient . on ( 'message' , ( msg ) = > {
2022-01-16 15:55:50 -05:00
this . logger . log ( { selectedNode : clWsClt.selectedNode , level : 'DEBUG' , fileName : 'CLWebSocket' , msg : 'Received message from the server..' , data : msg.data } ) ;
2023-12-05 20:32:05 -08:00
this . wsServer . sendEventsToAllLNClients ( JSON . stringify ( { source : 'CLN' , data : msg } ) , clWsClt . selectedNode ) ;
} ) ;
2021-12-29 18:08:41 -05:00
2023-12-05 20:32:05 -08:00
clWsClt . webSocketClient . on ( 'error' , ( err ) = > {
2023-05-29 12:27:28 -07:00
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 ( ) ;
2023-12-05 20:32:05 -08:00
if ( clWsClt . reConnect ) { this . reconnect ( clWsClt ) ; }
} ) ;
2021-12-29 18:08:41 -05:00
} ;
2024-06-10 12:40:37 -07:00
public disconnect = ( selectedNode : SelectedNode ) = > {
2021-12-29 18:08:41 -05:00
const clientExists = this . webSocketClients . find ( ( wsc ) = > wsc . selectedNode . index === selectedNode . index ) ;
2023-12-05 20:32:05 -08:00
if ( clientExists && clientExists . webSocketClient && clientExists . webSocketClient . connected ) {
2022-05-01 13:35:20 -04:00
this . logger . log ( { selectedNode : clientExists.selectedNode , level : 'INFO' , fileName : 'CLWebSocket' , msg : 'Disconnecting from the Core Lightning\'s Websocket Server..' } ) ;
2021-12-29 18:08:41 -05:00
clientExists . reConnect = false ;
clientExists . webSocketClient . close ( ) ;
const clientIdx = this . webSocketClients . findIndex ( ( wsc ) = > wsc . selectedNode . index === selectedNode . index ) ;
this . webSocketClients . splice ( clientIdx , 1 ) ;
}
} ;
2024-06-10 12:40:37 -07:00
public updateSelectedNode = ( newSelectedNode : SelectedNode ) = > {
2021-12-29 18:08:41 -05:00
const clientIdx = this . webSocketClients . findIndex ( ( wsc ) = > + wsc . selectedNode . index === + newSelectedNode . index ) ;
2022-01-16 15:55:50 -05:00
let newClient = this . webSocketClients [ clientIdx ] ;
if ( ! newClient ) { newClient = { selectedNode : null , reConnect : true , webSocketClient : null } ; }
2021-12-29 18:08:41 -05:00
newClient . selectedNode = JSON . parse ( JSON . stringify ( newSelectedNode ) ) ;
this . webSocketClients [ clientIdx ] = newClient ;
2022-08-11 02:17:43 -07:00
} ;
2021-12-29 18:08:41 -05:00
}
export const CLWSClient = new CLWebSocketClient ( ) ;