diff --git a/src/action/index.js b/src/action/index.js index 0bc6474ec..57894a8c5 100644 --- a/src/action/index.js +++ b/src/action/index.js @@ -36,7 +36,7 @@ export const grpc = new GrpcAction(store, ipc); export const notify = new NotificationAction(store, nav); export const wallet = new WalletAction(store, grpc, db, nav, notify); export const info = new InfoAction(store, grpc, nav, notify); -export const transaction = new TransactionAction(store, grpc, nav); +export const transaction = new TransactionAction(store, grpc, nav, notify); export const channel = new ChannelAction(store, grpc, nav, notify); export const invoice = new InvoiceAction(store, grpc, nav, notify, Clipboard); export const payment = new PaymentAction(store, grpc, nav, notify); diff --git a/src/action/transaction.js b/src/action/transaction.js index 703e8ca3d..f70ca3d8b 100644 --- a/src/action/transaction.js +++ b/src/action/transaction.js @@ -7,10 +7,11 @@ import * as log from './log'; import { parseDate, parseSat, toHex } from '../helper'; class TransactionAction { - constructor(store, grpc, nav) { + constructor(store, grpc, nav, notification) { this._store = store; this._grpc = grpc; this._nav = nav; + this._notification = notification; } /** @@ -133,12 +134,29 @@ class TransactionAction { async subscribeInvoices() { const stream = this._grpc.sendStreamCommand('subscribeInvoices'); await new Promise((resolve, reject) => { - stream.on('data', () => this.update()); + stream.on('data', invoice => this._receiveInvoice(invoice)); stream.on('end', resolve); stream.on('error', reject); stream.on('status', status => log.info(`Invoices update: ${status}`)); }); } + + // + // Helper functions + // + + async _receiveInvoice(invoice) { + await this.update(); + if (!invoice.settled) return; + const { computedTransactions, unitLabel } = this._store; + let inv = computedTransactions.find(tx => tx.id === toHex(invoice.r_hash)); + this._notification.display({ + type: 'success', + msg: `Invoice success: received ${inv.amountLabel} ${unitLabel}`, + handler: () => this.select({ item: inv }), + handlerLbl: 'View details', + }); + } } export default TransactionAction; diff --git a/stories/screen-story.js b/stories/screen-story.js index 689b31a1b..db1ab112f 100644 --- a/stories/screen-story.js +++ b/stories/screen-story.js @@ -67,7 +67,7 @@ sinon.stub(wallet, 'checkSeed'); sinon.stub(wallet, 'checkNewPassword'); sinon.stub(wallet, 'checkPassword'); sinon.stub(wallet, 'getExchangeRate'); -const transaction = new TransactionAction(store, grpc, nav); +const transaction = new TransactionAction(store, grpc, nav, notify); sinon.stub(transaction, 'update'); const invoice = new InvoiceAction(store, grpc, nav, notify, Clipboard); sinon.stub(invoice, 'generateUri'); diff --git a/test/integration/action/action-integration.spec.js b/test/integration/action/action-integration.spec.js index b2347c06e..281594c77 100644 --- a/test/integration/action/action-integration.spec.js +++ b/test/integration/action/action-integration.spec.js @@ -149,7 +149,7 @@ describe('Action Integration Tests', function() { grpc1 = new GrpcAction(store1, ipc1); info1 = new InfoAction(store1, grpc1, nav1, notify1); wallet1 = new WalletAction(store1, grpc1, db1, nav1, notify1); - transactions1 = new TransactionAction(store1, grpc1, nav1); + transactions1 = new TransactionAction(store1, grpc1, nav1, notify1); channels1 = new ChannelAction(store1, grpc1, nav1, notify1); invoice1 = new InvoiceAction(store1, grpc1, nav1, notify1); payments1 = new PaymentAction(store1, grpc1, nav1, notify1); @@ -161,7 +161,7 @@ describe('Action Integration Tests', function() { grpc2 = new GrpcAction(store2, ipc2); info2 = new InfoAction(store2, grpc2, nav2, notify2); wallet2 = new WalletAction(store2, grpc2, db2, nav2, notify2); - transactions2 = new TransactionAction(store2, grpc2, nav2); + transactions2 = new TransactionAction(store2, grpc2, nav2, notify2); channels2 = new ChannelAction(store2, grpc2, nav2, notify2); invoice2 = new InvoiceAction(store2, grpc2, nav2, notify2); payments2 = new PaymentAction(store2, grpc2, nav2, notify2); diff --git a/test/unit/action/transaction.spec.js b/test/unit/action/transaction.spec.js index c71bef776..6821710fd 100644 --- a/test/unit/action/transaction.spec.js +++ b/test/unit/action/transaction.spec.js @@ -2,6 +2,7 @@ import { Store } from '../../../src/store'; import GrpcAction from '../../../src/action/grpc'; import TransactionAction from '../../../src/action/transaction'; import NavAction from '../../../src/action/nav'; +import NotificationAction from '../../../src/action/notification'; import * as logger from '../../../src/action/log'; describe('Action Transactions Unit Tests', () => { @@ -9,6 +10,7 @@ describe('Action Transactions Unit Tests', () => { let sandbox; let grpc; let nav; + let notification; let transaction; beforeEach(() => { @@ -18,7 +20,8 @@ describe('Action Transactions Unit Tests', () => { require('../../../src/config').RETRY_DELAY = 1; grpc = sinon.createStubInstance(GrpcAction); nav = sinon.createStubInstance(NavAction); - transaction = new TransactionAction(store, grpc, nav); + notification = sinon.createStubInstance(NotificationAction); + transaction = new TransactionAction(store, grpc, nav, notification); }); afterEach(() => { @@ -210,13 +213,38 @@ describe('Action Transactions Unit Tests', () => { }); it('should update invoices on data event', async () => { - onStub.withArgs('data').yields(); + onStub.withArgs('data').yields({}); + onStub.withArgs('end').yields(); + grpc.sendStreamCommand + .withArgs('subscribeInvoices') + .returns({ on: onStub }); + await transaction.subscribeInvoices(); + expect(transaction.update, 'was called once'); + }); + + it('should notify the user on settled invoice', async () => { + store.computedTransactions = [{ id: 'cdab' }]; + onStub.withArgs('data').yields({ + settled: true, + r_hash: Buffer.from('cdab', 'hex'), + }); + onStub.withArgs('end').yields(); + grpc.sendStreamCommand + .withArgs('subscribeInvoices') + .returns({ on: onStub }); + await transaction.subscribeInvoices(); + expect(notification.display, 'was called once'); + }); + + it('should not notify the user on an unsettled invoice', async () => { + onStub.withArgs('data').yields({ settled: false }); onStub.withArgs('end').yields(); grpc.sendStreamCommand .withArgs('subscribeInvoices') .returns({ on: onStub }); await transaction.subscribeInvoices(); expect(transaction.update, 'was called once'); + expect(notification.display, 'was not called'); }); it('should reject in case of error', async () => {