diff --git a/app/lnd/index.js b/app/lnd/index.js index 9f423250..b5d27014 100644 --- a/app/lnd/index.js +++ b/app/lnd/index.js @@ -1,6 +1,7 @@ import config from './config' import lightning from './lib/lightning' import walletUnlocker from './lib/walletUnlocker' +import isLndRunning from './lib/util' import subscribe from './subscribe' import methods from './methods' import walletUnlockerMethods from './walletUnlockerMethods' @@ -10,7 +11,6 @@ import { mainLog } from '../utils/log' const initLnd = () => { const lndConfig = config.lnd() const lnd = lightning(lndConfig.lightningRpc, lndConfig.lightningHost) - const lndSubscribe = mainWindow => subscribe(mainWindow, lnd, mainLog) const lndMethods = (event, msg, data) => methods(lnd, mainLog, event, msg, data) @@ -22,7 +22,6 @@ const initLnd = () => { const initWalletUnlocker = () => { const lndConfig = config.lnd() - const walletUnlockerObj = walletUnlocker(lndConfig.lightningRpc, lndConfig.lightningHost) const walletUnlockerMethodsCallback = (event, msg, data) => walletUnlockerMethods(walletUnlockerObj, mainLog, event, msg, data) @@ -32,5 +31,6 @@ const initWalletUnlocker = () => { export default { initLnd, - initWalletUnlocker + initWalletUnlocker, + isLndRunning } diff --git a/app/lnd/lib/neutrino.js b/app/lnd/lib/neutrino.js new file mode 100644 index 00000000..992a256f --- /dev/null +++ b/app/lnd/lib/neutrino.js @@ -0,0 +1,85 @@ +import split2 from 'split2' +import { spawn } from 'child_process' +import EventEmitter from 'events' +import config from '../config' +import { mainLog, lndLog, lndLogGetLevel } from '../../utils/log' + +class Neutrino extends EventEmitter { + constructor(alias, autopilot) { + super() + this.alias = alias + this.autopilot = autopilot + this.process = null + } + + start() { + if (this.process) { + throw new Error('Neutrino process with PID ${this.process.pid} already exists.') + } + + const lndConfig = config.lnd() + mainLog.info('Starting lnd in neutrino mode') + mainLog.debug(' > lndPath', lndConfig.lndPath) + mainLog.debug(' > lightningRpc:', lndConfig.lightningRpc) + mainLog.debug(' > lightningHost:', lndConfig.lightningHost) + mainLog.debug(' > cert:', lndConfig.cert) + mainLog.debug(' > macaroon:', lndConfig.macaroon) + + const neutrinoArgs = [ + `--configfile=${lndConfig.configPath}`, + `${this.autopilot ? '--autopilot.active' : ''}`, + `${this.alias ? `--alias=${this.alias}` : ''}` + ] + + this.process = spawn(lndConfig.lndPath, neutrinoArgs) + .on('error', error => this.emit('error', error)) + .on('close', code => { + this.emit('close', code) + this.process = null + }) + + // Listen for when neutrino prints odata to stderr. + this.process.stderr.pipe(split2()).on('data', line => { + if (process.env.NODE_ENV === 'development') { + lndLog[lndLogGetLevel(line)](line) + } + }) + + // Listen for when neutrino prints data to stdout. + this.process.stdout.pipe(split2()).on('data', line => { + if (process.env.NODE_ENV === 'development') { + lndLog[lndLogGetLevel(line)](line) + } + + // gRPC started. + if (line.includes('gRPC proxy started') && line.includes('password')) { + this.emit('grpc-proxy-started') + } + + // Wallet opened. + if (line.includes('gRPC proxy started') && !line.includes('password')) { + this.emit('wallet-opened') + } + + // LND is all caught up to the blockchain. + if (line.includes('Chain backend is fully synced')) { + this.emit('fully-synced') + } + + // Pass current block height progress to front end for loading state UX + if (line.includes('Caught up to height') || line.includes('Catching up block hashes')) { + this.emit('got-block-height', line) + } + }) + return this.process + } + + stop() { + if (this.process) { + this.process.kill() + this.process = null + } + } +} + +export default Neutrino diff --git a/app/lnd/lib/util.js b/app/lnd/lib/util.js new file mode 100644 index 00000000..0afe5e02 --- /dev/null +++ b/app/lnd/lib/util.js @@ -0,0 +1,28 @@ +import { lookup } from 'ps-node' +import { mainLog } from '../../utils/log' + +/** + * Check to see if an LND process is running. + * @return {Promise} Boolean indicating wether an existing lnd process was found on the host machine. + */ +const isLndRunning = () => { + return new Promise((resolve, reject) => { + mainLog.info('Looking for existing lnd process') + lookup({ command: 'lnd' }, (err, results) => { + // There was an error checking for the LND process. + if (err) { + return reject(err) + } + + if (!results.length) { + // An LND process was found, no need to start our own. + mainLog.info('Existing lnd process not found') + return resolve(false) + } + mainLog.info('Found existing lnd process') + return resolve(true) + }) + }) +} + +export default isLndRunning diff --git a/app/main.dev.js b/app/main.dev.js index a52c3d4b..7cd5e7b4 100644 --- a/app/main.dev.js +++ b/app/main.dev.js @@ -1,5 +1,3 @@ -/* eslint global-require: 1, flowtype-errors/show-errors: 0 */ - /** * This module executes inside of electron's main process. You can start * electron renderer process from here and communicate with the other processes @@ -7,369 +5,105 @@ * * When running `npm run build` or `npm run build-main`, this file is compiled to * `./app/main.prod.js` using webpack. This gives us some performance wins. - * - * */ -import { app, BrowserWindow, ipcMain, dialog, session } from 'electron' -import path from 'path' -import fs from 'fs' -import split2 from 'split2' -import { spawn } from 'child_process' -import { lookup } from 'ps-node' -import Store from 'electron-store' +import { app, BrowserWindow, session } from 'electron' +import { mainLog } from './utils/log' import MenuBuilder from './menu' +import ZapController from './zap' import lnd from './lnd' -import config from './lnd/config' -import { mainLog, lndLog, lndLogGetLevel } from './utils/log' - -let mainWindow = null - -let didFinishLoad = false - -let startedSync = false -let sentGrpcDisconnect = false - -let neutrino = null - -if (process.env.NODE_ENV === 'production') { - const sourceMapSupport = require('source-map-support') - sourceMapSupport.install() -} - -if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true') { - require('electron-debug')() - const p = path.join(__dirname, '..', 'app', 'node_modules') - require('module').globalPaths.push(p) -} - -const installExtensions = async () => { - const installer = require('electron-devtools-installer') - const forceDownload = !!process.env.UPGRADE_EXTENSIONS - const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS'] - - return Promise.all( - extensions.map(name => installer.default(installer[name], forceDownload)) - ).catch(mainLog.error) -} - -// Send the front end event letting them know the gRPC connection is disconnected -const sendGrpcDisconnected = () => { - const sendGrpcDisonnectedInterval = setInterval(() => { - if (didFinishLoad) { - clearInterval(sendGrpcDisonnectedInterval) - - if (mainWindow) { - sentGrpcDisconnect = true - mainWindow.webContents.send('grpcDisconnected') - } - } - }, 1000) -} - -// Send the front end event letting them know LND is synced to the blockchain -const sendLndSyncing = () => { - const sendLndSyncingInterval = setInterval(() => { - if (didFinishLoad) { - clearInterval(sendLndSyncingInterval) - - if (mainWindow) { - mainLog.info('SENDING SYNCING') - startedSync = true - mainWindow.webContents.send('lndSyncing') - } - } - }, 1000) -} - -const sendStartOnboarding = () => { - const sendStartOnboardingInterval = setInterval(() => { - if (didFinishLoad) { - clearInterval(sendStartOnboardingInterval) - - if (mainWindow) { - mainLog.timeEnd('Time until onboarding has started') - mainLog.info('STARTING ONBOARDING') - mainWindow.webContents.send('startOnboarding') - } - } - }, 1000) -} - -// Send the front end event letting them know the gRPC connection has started -const sendGrpcConnected = () => { - const sendGrpcConnectedInterval = setInterval(() => { - if (didFinishLoad && sentGrpcDisconnect) { - clearInterval(sendGrpcConnectedInterval) - - if (mainWindow) { - mainWindow.webContents.send('grpcConnected') - } - } - }, 1000) -} - -// Create and subscribe the grpc object -const startGrpc = () => { - mainLog.info('Starting gRPC...') - try { - const { lndSubscribe, lndMethods } = lnd.initLnd() - - // Subscribe to bi-directional streams - lndSubscribe(mainWindow) - - // Listen for all gRPC restful methods - ipcMain.on('lnd', (event, { msg, data }) => { - lndMethods(event, msg, data) - }) - sendGrpcConnected() - } catch (error) { - dialog.showMessageBox({ - type: 'error', - message: `Unable to connect to lnd. Please check your lnd node and try again: ${error}` - }) - app.quit() - } -} - -// Create and subscribe the grpc object -const startWalletUnlocker = () => { - mainLog.info('Starting wallet unlocker...') - try { - const walletUnlockerMethods = lnd.initWalletUnlocker() - - // Listen for all gRPC restful methods - ipcMain.on('walletUnlocker', (event, { msg, data }) => { - walletUnlockerMethods(event, msg, data) - }) - - mainWindow.webContents.send('walletUnlockerStarted') - } catch (error) { - dialog.showMessageBox({ - type: 'error', - message: `Unable to start lnd wallet unlocker. Please check your lnd node and try again: ${error}` - }) - app.quit() - } -} - -// Send the front end event letting them know LND is synced to the blockchain -const sendLndSynced = () => { - const sendLndSyncedInterval = setInterval(() => { - if (didFinishLoad && startedSync) { - clearInterval(sendLndSyncedInterval) - - if (mainWindow) { - mainLog.info('SENDING SYNCED') - mainWindow.webContents.send('lndSynced') - } - } - }, 1000) -} - -// Starts the LND node -const startLnd = (alias, autopilot) => { - const lndConfig = config.lnd() - mainLog.info('STARTING BUNDLED LND') - mainLog.debug(' > lndPath', lndConfig.lndPath) - mainLog.debug(' > lightningRpc:', lndConfig.lightningRpc) - mainLog.debug(' > lightningHost:', lndConfig.lightningHost) - mainLog.debug(' > cert:', lndConfig.cert) - mainLog.debug(' > macaroon:', lndConfig.macaroon) - - const neutrinoArgs = [ - `--configfile=${lndConfig.configPath}`, - `${autopilot ? '--autopilot.active' : ''}`, - `${alias ? `--alias=${alias}` : ''}` - ] - - neutrino = spawn(lndConfig.lndPath, neutrinoArgs) - .on('error', error => { - lndLog.error(`lnd error: ${error}`) - dialog.showMessageBox({ - type: 'error', - message: `lnd error: ${error}` - }) - }) - .on('close', code => { - lndLog.info(`lnd shutting down ${code}`) - app.quit() - }) - - // Listen for when neutrino prints odata to stderr. - neutrino.stderr.pipe(split2()).on('data', line => { - if (process.env.NODE_ENV === 'development') { - lndLog[lndLogGetLevel(line)](line) - } +// Set up a couple of timers to track the app startup progress. +mainLog.time('Time until app is ready') +mainLog.time('Time until lnd process lookup finished') + +// Determine wether we should start our own lnd process or connect to one that is already running. +const zapMode = lnd + .isLndRunning() + .then(res => { + mainLog.debug('lnd already running: %s', res) + mainLog.timeEnd('Time until lnd process lookup finished') + return res ? 'external' : 'internal' }) - - // Listen for when neutrino prints data to stdout. - neutrino.stdout.pipe(split2()).on('data', line => { - if (process.env.NODE_ENV === 'development') { - lndLog[lndLogGetLevel(line)](line) - } - - // If the gRPC proxy has started we can start ours - if (line.includes('gRPC proxy started')) { - const certInterval = setInterval(() => { - if (fs.existsSync(lndConfig.cert)) { - clearInterval(certInterval) - - mainLog.info('CERT EXISTS, STARTING WALLET UNLOCKER') - startWalletUnlocker() - - if (mainWindow) { - mainWindow.webContents.send('walletUnlockerStarted') - } - } - }, 1000) - } - - if (line.includes('gRPC proxy started') && !line.includes('password')) { - mainLog.info('WALLET OPENED, STARTING LIGHTNING GRPC CONNECTION') - sendLndSyncing() - startGrpc() - } - - // Pass current clock height progress to front end for loading state UX - if ( - mainWindow && - (line.includes('Caught up to height') || line.includes('Catching up block hashes to height')) - ) { - // const blockHeight = line.slice(line.indexOf('Caught up to height') + 'Caught up to height'.length).trim() - mainWindow.webContents.send('lndStdout', line) - } - - // When LND is all caught up to the blockchain - if (line.includes('Chain backend is fully synced')) { - // Log that LND is caught up to the current block height - mainLog.info('NEUTRINO IS SYNCED') - - // Let the front end know we have stopped syncing LND - sendLndSynced() - } - }) -} + .catch(mainLog.error) /** - * Add event listeners... + * Initialize Zap as soon as electron is ready. */ +app.on('ready', () => { + mainLog.timeEnd('Time until app is ready') -app.on('window-all-closed', () => { - // Respect the OSX convention of having the application in memory even - // after all windows have been closed - if (process.platform !== 'darwin') { - app.quit() - } -}) - -app.on('ready', async () => { + // Start a couple more timers to track the app loading time. mainLog.time('Time until app is visible') mainLog.time('Time until onboarding has started') - if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true') { - await installExtensions() - } - - mainWindow = new BrowserWindow({ + // Create the electron browser window. + const mainWindow = new BrowserWindow({ show: false, titleBarStyle: 'hidden', width: 950, height: 600, minWidth: 950, - minHeight: 425 + minHeight: 425, + backgroundColor: '#1c1e26' }) - if (process.env.HOT) { - const port = process.env.PORT || 1212 - mainWindow.loadURL(`http://localhost:${port}/dist/index.html`) - } else { - mainWindow.loadURL(`file://${__dirname}/dist/index.html`) + // Initialise the application. + const zap = new ZapController(mainWindow, zapMode) + zap.init() + + // Initialise the application menus. + const menuBuilder = new MenuBuilder(mainWindow) + menuBuilder.buildMenu() + + /** + * In production mode, enable source map support. + */ + if (process.env.NODE_ENV === 'production') { + const sourceMapSupport = require('source-map-support') // eslint-disable-line global-require + sourceMapSupport.install() } + /** + * In development mode or when DEBUG_PROD is set, enable debugging tools. + */ if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true') { + // eslint-disable global-require + require('electron-debug')() + const installer = require('electron-devtools-installer') + const forceDownload = !!process.env.UPGRADE_EXTENSIONS + const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS'] + + Promise.all(extensions.map(name => installer.default(installer[name], forceDownload))).catch( + mainLog.error + ) + mainWindow.webContents.once('dom-ready', () => { mainWindow.openDevTools() }) } - // @TODO: Use 'ready-to-show' event - // https://github.com/electron/electron/blob/master/docs/api/browser-window.md#using-ready-to-show-event - mainWindow.webContents.on('did-finish-load', () => { - if (!mainWindow) { - throw new Error('"mainWindow" is not defined') + /** + * Add application event listener: + * - Kill lnd process is killed when the app quits. + */ + app.on('quit', () => { + mainLog.debug('app.quit') + if (zap.neutrino) { + zap.neutrino.stop() } - mainLog.timeEnd('Time until app is visible') - mainWindow.show() - mainWindow.focus() - - // now sync and grpc events can be fired to the front end - didFinishLoad = true }) - mainWindow.on('closed', () => { - mainWindow = null - - // shut down zap when a user closes the window - app.quit() - }) - - const menuBuilder = new MenuBuilder(mainWindow) - menuBuilder.buildMenu() - - sendGrpcDisconnected() - - mainLog.info('LOOKING FOR EXISTING LND PROCESS') - // Check to see if an LND process is running. - lookup({ command: 'lnd' }, (err, results) => { - // There was an error checking for the LND process. - if (err) { - throw new Error(err) - } - - if (!results.length) { - // An LND process was found, no need to start our own. - mainLog.info('EXISTING LND PROCESS NOT FOUND') - // Let the application know onboarding has started. - sendStartOnboarding() - } else { - // An LND process was found, no need to start our own. - mainLog.info('FOUND EXISTING LND PROCESS') - startGrpc() - mainWindow.webContents.send('successfullyCreatedWallet') - } - }) - - // Start LND - // once the onboarding has enough information, start or connect to LND. - ipcMain.on('startLnd', (event, options = {}) => { - const store = new Store({ name: 'connection' }) - store.store = { - type: options.connectionType, - host: options.connectionHost, - cert: options.connectionCert, - macaroon: options.connectionMacaroon, - alias: options.alias, - autopilot: options.autopilot - } - - mainLog.info('GOT LND CONFIG') - mainLog.debug(' > connectionType:', options.connectionType) - mainLog.debug(' > connectionHost:', options.connectionHost) - mainLog.debug(' > connectionCert:', options.connectionCert) - mainLog.debug(' > connectionMacaroon:', options.connectionMacaroon) - mainLog.debug(' > alias:', options.alias) - mainLog.debug(' > autopilot:', options.autopilot) - - mainLog.info('SAVED LND CONFIG TO:', store.path) - - if (options.connectionType === 'local') { - startLnd(options.alias, options.autopilot) - } else { - mainLog.info('CONNECTING TO CUSTOM LND INSTANCE') - startGrpc() - mainWindow.webContents.send('successfullyCreatedWallet') - } + /** + * Add application event listener: + * - Open zap payment form when lightning url is opened + */ + app.setAsDefaultProtocolClient('lightning') + app.on('open-url', (event, url) => { + mainLog.debug('open-url') + event.preventDefault() + const payreq = url.split(':')[1] + zap.sendMessage('lightningPaymentUri', { payreq }) + mainWindow.show() }) // HACK: patch webrequest to fix devtools incompatibility with electron 2.x. @@ -386,27 +120,16 @@ app.on('ready', async () => { callback({ cancel: false }) } }) -}) - -app.setAsDefaultProtocolClient('lightning') - -app.on('open-url', (event, url) => { - event.preventDefault() - if (!mainWindow) { - throw new Error('"mainWindow" is not defined') - } - - const payreq = url.split(':')[1] - mainWindow.webContents.send('lightningPaymentUri', { payreq }) - mainWindow.show() -}) - -// Ensure lnd process is killed when the app quits. -app.on('quit', () => { - if (neutrino) { - neutrino.kill() - } + /** + * Add application event listener: + * - quit app when window is closed + */ + app.on('window-all-closed', () => { + mainLog.debug('app.window-all-closed') + // Respect the OSX convention of having the application in memory even after all windows have been closed + if (process.platform !== 'darwin') { + app.quit() + } + }) }) - -export default { startLnd } diff --git a/app/reducers/lnd.js b/app/reducers/lnd.js index 7c45858c..e63a8bd6 100644 --- a/app/reducers/lnd.js +++ b/app/reducers/lnd.js @@ -113,7 +113,7 @@ const ACTION_HANDLERS = { // ------------------------------------ const initialState = { syncing: false, - grpcStarted: true, + grpcStarted: false, fetchingBlockHeight: false, lines: [], blockHeight: 0, diff --git a/app/zap.js b/app/zap.js new file mode 100644 index 00000000..f5600643 --- /dev/null +++ b/app/zap.js @@ -0,0 +1,217 @@ +import { app, ipcMain, dialog } from 'electron' +import Store from 'electron-store' +import lnd from './lnd' +import Neutrino from './lnd/lib/neutrino' +import { mainLog } from './utils/log' + +/** + * @class ZapController + * + * The ZapController class coordinates actions between the the main nand renderer processes. + */ +class ZapController { + /** + * Create a new ZapController instance. + * @param {BrowserWindow} mainWindow BrowserWindow instance to interact with + * @param {String|Promise} mode String or Promise that resolves to the desired run mode. Valid options are: + * - 'internal': start a new lnd process. + * - 'external': connect to an existing lnd process. + */ + constructor(mainWindow, mode) { + this.mode = mode + + // Variable to hold the main window instance. + this.mainWindow = mainWindow + + // Keep a reference any neutrino process started by us. + this.neutrino = null + + // Time for the splash screen to remain visible. + this.splashScreenTime = 500 + } + + /** + * Initialize the application. + */ + init() { + if (process.env.HOT) { + const port = process.env.PORT || 1212 + this.mainWindow.loadURL(`http://localhost:${port}/dist/index.html`) + } else { + this.mainWindow.loadURL(`file://${__dirname}/dist/index.html`) + } + + // Register IPC listeners so that we can react to instructions coming from the app. + this._registerIpcListeners() + + // Show the window as soon as the application has finished loading. + this.mainWindow.webContents.on('did-finish-load', async () => { + this.mainWindow.show() + this.mainWindow.focus() + mainLog.timeEnd('Time until app is visible') + mainLog.time('Time until we know the run mode') + + Promise.resolve(this.mode) + .then(mode => { + const timeUntilWeKnowTheRunMode = mainLog.timeEnd('Time until we know the run mode') + return setTimeout(() => { + if (mode === 'external') { + // If lnd is already running, create and subscribe to the Lightning grpc object. + this.startGrpc() + this.sendMessage('successfullyCreatedWallet') + } else { + // Otherwise, start the onboarding process. + this.sendMessage('startOnboarding') + mainLog.timeEnd('Time until onboarding has started') + } + }, timeUntilWeKnowTheRunMode < this.splashScreenTime ? this.splashScreenTime : 0) + }) + .catch(mainLog.error) + }) + + this.mainWindow.on('closed', () => { + this.mainWindow = null + + // shut down zap when a user closes the window + app.quit() + }) + } + + /** + * Send a message to the main window. + * @param {string} msg message to send. + * @param {[type]} data additional data to acompany the message. + */ + sendMessage(msg, data) { + mainLog.info('Sending message to renderer process: %o', { msg, data }) + this.mainWindow.webContents.send(msg, data) + } + + /** + * Create and subscribe to the Lightning grpc object. + */ + startGrpc() { + mainLog.info('Starting gRPC...') + try { + const { lndSubscribe, lndMethods } = lnd.initLnd() + + // Subscribe to bi-directional streams + lndSubscribe(this.mainWindow) + + // Listen for all gRPC restful methods + ipcMain.on('lnd', (event, { msg, data }) => { + lndMethods(event, msg, data) + }) + + this.sendMessage('grpcConnected') + } catch (error) { + dialog.showMessageBox({ + type: 'error', + message: `Unable to connect to lnd. Please check your lnd node and try again: ${error}` + }) + app.quit() + } + } + + /** + * Create and subscribe to the WalletUnlocker grpc object. + */ + startWalletUnlocker() { + mainLog.info('Starting wallet unlocker...') + try { + const walletUnlockerMethods = lnd.initWalletUnlocker() + + // Listen for all gRPC restful methods + ipcMain.on('walletUnlocker', (event, { msg, data }) => { + walletUnlockerMethods(event, msg, data) + }) + + this.sendMessage('walletUnlockerStarted') + } catch (error) { + dialog.showMessageBox({ + type: 'error', + message: `Unable to start lnd wallet unlocker. Please check your lnd node and try again: ${error}` + }) + app.quit() + } + } + + /** + * Starts the LND node and attach event listeners. + * @param {string} alias Alias to assign to the lnd node. + * @param {boolean} autopilot True if autopilot should be enabled. + * @return {Neutrino} Neutrino instance. + */ + startLnd(alias, autopilot) { + this.neutrino = new Neutrino(alias, autopilot) + + this.neutrino.on('error', error => { + mainLog.error(`Got error from lnd process: ${error})`) + dialog.showMessageBox({ + type: 'error', + message: `lnd error: ${error}` + }) + }) + + this.neutrino.on('close', code => { + mainLog.info(`Lnd process has shut down (code ${code})`) + app.quit() + }) + + this.neutrino.on('grpc-proxy-started', () => { + mainLog.info('gRPC proxy started') + this.startWalletUnlocker() + }) + + this.neutrino.on('wallet-opened', () => { + mainLog.info('Wallet opened') + this.startGrpc() + this.sendMessage('lndSyncing') + }) + + this.neutrino.on('fully-synced', () => { + mainLog.info('Neutrino fully synced') + this.sendMessage('lndSynced') + }) + + this.neutrino.on('got-block-height', line => { + this.sendMessage('lndStdout', line) + }) + + this.neutrino.start() + } + + /** + * Add IPC event listeners... + */ + _registerIpcListeners() { + ipcMain.on('startLnd', (event, options = {}) => { + const store = new Store({ name: 'connection' }) + store.store = { + type: options.connectionType, + host: options.connectionHost, + cert: options.connectionCert, + macaroon: options.connectionMacaroon, + alias: options.alias, + autopilot: options.autopilot + } + mainLog.info('Saved lnd config to:', store.path) + + if (options.connectionType === 'local') { + mainLog.info('Starting new lnd instance') + mainLog.debug(' > alias:', options.alias) + mainLog.debug(' > autopilot:', options.autopilot) + this.startLnd(options.alias, options.autopilot) + } else { + mainLog.info('Connecting to custom lnd instance') + mainLog.debug(' > connectionHost:', options.connectionHost) + mainLog.debug(' > connectionCert:', options.connectionCert) + mainLog.debug(' > connectionMacaroon:', options.connectionMacaroon) + this.startGrpc() + this.sendMessage('successfullyCreatedWallet') + } + }) + } +} + +export default ZapController