diff --git a/models/Transaction.ts b/models/Transaction.ts index 50f8634fa..96ace706c 100644 --- a/models/Transaction.ts +++ b/models/Transaction.ts @@ -91,7 +91,7 @@ export default class Transaction extends BaseModel { return this.num_confirmations > 0 || this.status === 'confirmed'; } - @computed public get getAmount(): number | string { + @computed public get getAmount(): string { const amount = this.value || this.amount || 0; const fee = this.getFee; diff --git a/stores/ActivityStore.ts b/stores/ActivityStore.ts index a5b069600..a02919847 100644 --- a/stores/ActivityStore.ts +++ b/stores/ActivityStore.ts @@ -25,6 +25,7 @@ export interface Filter { received: boolean; unpaid: boolean; inTransit: boolean; + unconfirmed: boolean; zeusPay: boolean; minimumAmount: number; startDate?: Date; @@ -38,6 +39,7 @@ export const DEFAULT_FILTERS = { received: true, unpaid: true, inTransit: false, + unconfirmed: true, zeusPay: true, minimumAmount: 0, startDate: undefined, @@ -88,6 +90,7 @@ export default class ActivityStore { received: true, unpaid: false, inTransit: false, + unconfirmed: true, zeusPay: true, minimumAmount: 0, startDate: undefined, diff --git a/utils/ActivityFilterUtils.test.ts b/utils/ActivityFilterUtils.test.ts index 656719f56..9749649a3 100644 --- a/utils/ActivityFilterUtils.test.ts +++ b/utils/ActivityFilterUtils.test.ts @@ -120,6 +120,65 @@ describe('ActivityFilterUtils', () => { ]); }); + it('supports filtering unconfirmed transactions', () => { + const activities: any[] = [ + new Transaction({ + amount: 1, + time_stamp: ( + new Date(2000, 1, 1, 3, 4, 5).getTime() / 1000 + ).toString(), + num_confirmations: 1 + }), + new Transaction({ + amount: 2, + time_stamp: ( + new Date(2000, 1, 2, 3, 4, 4).getTime() / 1000 + ).toString(), + num_confirmations: 0 + }), + new Transaction({ + amount: 3, + time_stamp: ( + new Date(2000, 1, 2, 3, 4, 4).getTime() / 1000 + ).toString(), + status: 'confirmed' + }), + new Transaction({ + amount: 4, + time_stamp: ( + new Date(2000, 1, 2, 3, 4, 4).getTime() / 1000 + ).toString(), + status: 'unconfirmed' + }), + new Invoice({ + value: '5', + creation_date: ( + new Date(2000, 1, 1, 3, 4, 5).getTime() / 1000 + ).toString() + }), + new Payment({ + value: '6', + creation_date: ( + new Date(2000, 1, 1, 3, 4, 5).getTime() / 1000 + ).toString() + }) + ]; + const filter = getDefaultFilter(); + filter.unconfirmed = false; + + const filteredActivities = ActivityFilterUtils.filterActivities( + activities, + filter + ); + + expect(filteredActivities.map((a) => a.getAmount)).toEqual([ + '1', + '3', + 5, + '6' + ]); + }); + const getDefaultFilter = () => ({ lightning: true, @@ -127,6 +186,7 @@ describe('ActivityFilterUtils', () => { sent: true, received: true, unpaid: true, + unconfirmed: true, minimumAmount: 0 } as Filter); }); diff --git a/utils/ActivityFilterUtils.ts b/utils/ActivityFilterUtils.ts index 3ca6010c2..8fe38ac5b 100644 --- a/utils/ActivityFilterUtils.ts +++ b/utils/ActivityFilterUtils.ts @@ -13,71 +13,63 @@ class ActivityFilterUtils { let filteredActivity = activities; if (filter.lightning == false) { filteredActivity = filteredActivity.filter( - (activity: any) => + (activity) => !( - activity.model === - localeString('views.Invoice.title') || - activity.model === localeString('views.Payment.title') + activity instanceof Invoice || + activity instanceof Payment ) ); } if (filter.onChain == false) { filteredActivity = filteredActivity.filter( - (activity: any) => + (activity) => !( - activity.model === - localeString('general.transaction') && - activity.getAmount != 0 + activity instanceof Transaction && + Number(activity.getAmount) != 0 ) ); } if (filter.sent == false) { filteredActivity = filteredActivity.filter( - (activity: any) => + (activity) => !( - (activity.model === - localeString('general.transaction') && - activity.getAmount < 0) || - activity.model === localeString('views.Payment.title') + (activity instanceof Transaction && + Number(activity.getAmount) < 0) || + activity instanceof Payment ) ); } if (filter.received == false) { filteredActivity = filteredActivity.filter( - (activity: any) => + (activity) => !( - (activity.model === - localeString('general.transaction') && - activity.getAmount > 0) || - (activity.model === - localeString('views.Invoice.title') && - activity.isPaid) + (activity instanceof Transaction && + Number(activity.getAmount) > 0) || + (activity instanceof Invoice && activity.isPaid) ) ); } if (filter.unpaid == false) { filteredActivity = filteredActivity.filter( - (activity: any) => - !( - activity.model === - localeString('views.Invoice.title') && - !activity.isPaid - ) + (activity) => !(activity instanceof Invoice && !activity.isPaid) ); } if (filter.inTransit == false) { filteredActivity = filteredActivity.filter( - (activity: any) => - !( - activity.model === - localeString('views.Payment.title') && - activity.isInTransit - ) + (activity) => + !(activity instanceof Payment && activity.isInTransit) + ); + } + + if (filter.unconfirmed == false) { + filteredActivity = filteredActivity.filter( + (activity) => + !(activity instanceof Transaction) || activity.isConfirmed ); } @@ -94,8 +86,8 @@ class ActivityFilterUtils { if (filter.minimumAmount > 0) { filteredActivity = filteredActivity.filter( - (activity: any) => - Math.abs(activity.getAmount) >= filter.minimumAmount + (activity) => + Math.abs(Number(activity.getAmount)) >= filter.minimumAmount ); } diff --git a/views/Activity/ActivityFilter.tsx b/views/Activity/ActivityFilter.tsx index 9199856ea..72487f060 100644 --- a/views/Activity/ActivityFilter.tsx +++ b/views/Activity/ActivityFilter.tsx @@ -6,6 +6,7 @@ import { isEqual } from 'lodash'; import DatePicker from 'react-native-date-picker'; +import BackendUtils from '../../utils/BackendUtils'; import { localeString } from '../../utils/LocaleUtils'; import { themeColor } from '../../utils/ThemeUtils'; @@ -74,6 +75,7 @@ export default class ActivityFilter extends React.Component< received, unpaid, inTransit, + unconfirmed, zeusPay, minimumAmount, startDate, @@ -206,6 +208,13 @@ export default class ActivityFilter extends React.Component< type: 'Toggle', condition: SettingsStore.settings.lightningAddress.enabled }, + { + label: localeString('general.unconfirmed'), + value: unconfirmed, + var: 'unconfirmed', + type: 'Toggle', + condition: BackendUtils.supportsOnchainReceiving() + }, { label: localeString('views.ActivityFilter.minimumAmount'), value: minimumAmount,