diff --git a/app/lib/zap/controller.js b/app/lib/zap/controller.js index 6f3ba3ab..52a15afc 100644 --- a/app/lib/zap/controller.js +++ b/app/lib/zap/controller.js @@ -105,9 +105,6 @@ class ZapController { 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', () => { this.mainWindow.show() @@ -130,8 +127,31 @@ class ZapController { // FSM Callbacks // ------------------------------------ + onOnboarding() { + mainLog.debug('[FSM] onOnboarding...') + + // Deregister IPC listeners so that we can start fresh. + this._removeIpcListeners() + + // Ensure wallet is disconnected. + this.disconnectLightningWallet() + + // If Neutrino is running, kill it. + if (this.neutrino) { + this.neutrino.stop() + } + + // Give the grpc connections a chance to be properly closed out. + return new Promise(resolve => setTimeout(resolve, 200)) + } + onStartOnboarding() { mainLog.debug('[FSM] onStartOnboarding...') + + // Register IPC listeners so that we can react to instructions coming from the app. + this._registerIpcListeners() + + // Notify the app to start the onboarding process. this.sendMessage('startOnboarding', this.lndConfig) } @@ -255,6 +275,9 @@ class ZapController { * Create and subscribe to the Lightning service. */ async startLightningWallet() { + if (this.lightningGrpcConnected) { + return + } mainLog.info('Starting lightning wallet...') this.lightning = new Lightning() @@ -284,7 +307,7 @@ class ZapController { mainLog.info('Disconnecting lightning Wallet...') // Disconnect streams. - this.lightning.unsubscribe() + this.lightning.disconnect() // Update our internal state. this.lightningGrpcConnected = false @@ -397,11 +420,20 @@ class ZapController { _registerIpcListeners() { ipcMain.on('startLnd', (event, options: onboardingOptions) => this.finishOnboarding(options)) } + + /** + * Add IPC event listeners... + */ + _removeIpcListeners() { + ipcMain.removeAllListeners('startLnd') + ipcMain.removeAllListeners('walletUnlocker') + ipcMain.removeAllListeners('lnd') + } } StateMachine.factory(ZapController, { transitions: [ - { name: 'startOnboarding', from: 'none', to: 'onboarding' }, + { name: 'startOnboarding', from: '*', to: 'onboarding' }, { name: 'startLnd', from: 'onboarding', to: 'running' }, { name: 'connectLnd', from: 'onboarding', to: 'connected' }, { name: 'terminate', from: '*', to: 'terminated' } diff --git a/test/unit/lnd/neutrino.spec.js b/test/unit/lnd/neutrino.spec.js index bb6a4800..71827a27 100644 --- a/test/unit/lnd/neutrino.spec.js +++ b/test/unit/lnd/neutrino.spec.js @@ -162,4 +162,33 @@ describe('Neutrino', function() { }) }) }) + + describe('.start', () => { + describe('called when neutrino is already running', () => { + beforeEach(() => { + this.neutrino = new Neutrino() + this.neutrino.process = 123 + }) + it('should throw an error', () => { + expect(() => { + this.neutrino.start() + }).toThrow() + }) + }) + }) + + describe('.stop', () => { + describe('called when neutrino is already running', () => { + beforeEach(() => { + this.neutrino = new Neutrino() + this.neutrino.process = { + kill: jest.fn() + } + this.neutrino.stop() + }) + it('should kill the neutrino process', () => { + expect(this.neutrino.process).toBeNull() + }) + }) + }) })