import { IpcMain } from 'electron' ; import { debug } from 'electron-log' ; import createLndRpc , * as LND from '@radar/lnrpc' ; import { DefaultsKey , ipcChannels , withDefaults } from '../../src/shared' ; import { LndNode } from '../../src/shared/types' ; /**
 * mapping of node name <-> LnRpc to cache these objects. The createLndRpc function
 * reads from disk, so this gives us a small bit of performance improvement
 */ let rpcCache = { } ; /**
 * Helper function to lookup a node by name in the cache or create it if
 * it doesn't exist
 */ const getRpc = async ( node ) : Promise < LND . LnRpc > => { const { name , ports , paths , networkId } = node ; const id = `n${ networkId }-${ name }` ; if ( ! rpcCache [ id ] ) { const config = { server : `127.0.0.1:${ ports . grpc }` , tls : paths . tlsCert , macaroonPath : paths . adminMacaroon , } ; rpcCache [ id ] = await createLndRpc ( config ) ; } return rpcCache [ id ] ; } ; const getInfo = async ( args ) : Promise < LND . GetInfoResponse > => { const rpc = await getRpc ( args . node ) ; return await rpc . getInfo ( ) ; } ; const walletBalance = async ( args ) : Promise < LND . WalletBalanceResponse > => { const rpc = await getRpc ( args . node ) ; return await rpc . walletBalance ( ) ; } ; const newAddress = async ( args ) : Promise < LND . NewAddressResponse > => { const rpc = await getRpc ( args . node ) ; return await rpc . newAddress ( ) ; } ; const listPeers = async ( args ) : Promise < LND . ListPeersResponse > => { const rpc = await getRpc ( args . node ) ; return await rpc . listPeers ( ) ; } ; const connectPeer = async ( args ) : Promise < void > => { const rpc = await getRpc ( args . node ) ; await rpc . connectPeer ( args . req ) ; } ; const openChannel = async ( args ) : Promise < LND . ChannelPoint > => { const rpc = await getRpc ( args . node ) ; return await rpc . openChannelSync ( args . req ) ; } ; const closeChannel = async ( args ) : Promise < any > => { const rpc = await getRpc ( args . node ) ; rpc . closeChannel ( args . req ) ; } ; const listChannels = async ( args ) : Promise < LND . ListChannelsResponse > => { const rpc = await getRpc ( args . node ) ; return await rpc . listChannels ( args . req ) ; } ; const pendingChannels = async ( args ) : Promise < LND . PendingChannelsResponse > => { const rpc = await getRpc ( args . node ) ; return await rpc . pendingChannels ( ) ; } ; const createInvoice = async ( args ) : Promise < LND . AddInvoiceResponse > => { const rpc = await getRpc ( args . node ) ; return await rpc . addInvoice ( args . req ) ; } ; const payInvoice = async ( args ) : Promise < LND . SendResponse > => { const rpc = await getRpc ( args . node ) ; return await rpc . sendPaymentSync ( args . req ) ; } ; const decodeInvoice = async ( args ) : Promise < LND . PayReq > => { const rpc = await getRpc ( args . node ) ; return await rpc . decodePayReq ( args . req ) ; } ; /**
 * A mapping of electron IPC channel names to the functions to execute when
 * messages are received
 */ const listeners = { [ ipcChannels . getInfo ] : getInfo , [ ipcChannels . walletBalance ] : walletBalance , [ ipcChannels . newAddress ] : newAddress , [ ipcChannels . listPeers ] : listPeers , [ ipcChannels . connectPeer ] : connectPeer , [ ipcChannels . openChannel ] : openChannel , [ ipcChannels . closeChannel ] : closeChannel , [ ipcChannels . listChannels ] : listChannels , [ ipcChannels . pendingChannels ] : pendingChannels , [ ipcChannels . createInvoice ] : createInvoice , [ ipcChannels . payInvoice ] : payInvoice , [ ipcChannels . decodeInvoice ] : decodeInvoice , } ; param ipc export const initLndProxy = ( ipc ) => { debug ( 'LndProxyServer: initialize' ) ; Object . entries ( listeners ) . forEach ( ( [ channel , func ] ) => { const requestChan = `lnd-${ channel }-request` ; const responseChan = `lnd-${ channel }-response` ; debug ( `LndProxyServer: listening for ipc command "${ channel }"` ) ; ipc . on ( requestChan , async ( event , ... args ) => { debug ( `LndProxyServer: received request "${ requestChan }"` , JSON . stringify ( args , null , 2 ) ) ; let uniqueChan = responseChan ; if ( args && args [ 0 ] && args [ 0 ] . replyTo ) { uniqueChan = args [ 0 ] . replyTo ; } try { let result = await func ( ... args ) ; debug ( `LndProxyServer: send response "${ uniqueChan }"` , JSON . stringify ( result , null , 2 ) ) ; result = withDefaults ( result , channel as DefaultsKey ) ; event . reply ( uniqueChan , result ) ; } catch ( err ) { debug ( `LndProxyServer: send error "${ uniqueChan }"` , JSON . stringify ( err , null , 2 ) ) ; event . reply ( uniqueChan , { err : err . message } ) ; } } ) ; } ) ; } ; /**
 * Clears the cached rpc instances
 */ export const clearProxyCache = ( ) => { rpcCache = { } ; } ;