diff --git a/stores/NostrWalletConnectStore.ts b/stores/NostrWalletConnectStore.ts index c6d047e35..d23b6cf49 100644 --- a/stores/NostrWalletConnectStore.ts +++ b/stores/NostrWalletConnectStore.ts @@ -1390,11 +1390,14 @@ export default class NostrWalletConnectStore { */ private async reconcileAllPendingPayInvoiceActivities(): Promise { try { - await Promise.all( + const changed = await Promise.all( this.activeConnections.map((connection) => this.reconcilePendingPayInvoiceActivities(connection) ) ); + if (changed.some(Boolean)) { + this.scheduleSave(); + } } catch (error) { console.error('NWC: pending payment reconciliation failed:', error); } @@ -1734,7 +1737,8 @@ export default class NostrWalletConnectStore { const result = await NostrConnectUtils.lookupInvoiceTransaction({ request, isCashu: this.isCashuConfigured, - cashuInvoices: this.cashuStore.invoices || [], + getCashuInvoices: () => + Promise.resolve(this.cashuStore.invoices || []), getCashuPayments: () => Promise.resolve(this.cashuStore.payments || []), getLightningPayments: () => this.getPaymentsForLookup() @@ -1766,7 +1770,11 @@ export default class NostrWalletConnectStore { let nip47Transactions: Nip47Transaction[] = []; if (connection.hasPaymentPermissions()) { - await this.reconcilePendingPayInvoiceActivities(connection); + const reconciled = + await this.reconcilePendingPayInvoiceActivities(connection); + if (reconciled) { + this.scheduleSave(); + } nip47Transactions = connection.activity .map((activity) => NostrConnectUtils.convertConnectionActivityToNip47Transaction( @@ -2282,19 +2290,20 @@ export default class NostrWalletConnectStore { */ private async reconcilePendingPayInvoiceActivities( connection: NWCConnection - ): Promise { + ): Promise { const lightningPending = connection.activity.filter( (activity) => activity.type === 'pay_invoice' && activity.status === 'pending' && activity.payment_source !== 'cashu' ); - if (lightningPending.length === 0) return; + if (lightningPending.length === 0) return false; const payments = await this.getPaymentsForPendingPayInvoiceRefresh( connection.id, lightningPending ); + let changed = false; for (const activity of lightningPending) { const payment = payments.find( (p) => @@ -2304,6 +2313,7 @@ export default class NostrWalletConnectStore { ); if (!payment) continue; + changed = true; runInAction(() => { activity.payment = new Payment(payment); if (!payment.isIncomplete) { @@ -2319,6 +2329,10 @@ export default class NostrWalletConnectStore { } }); } + if (changed) { + this.lookupPaymentsCache = null; + } + return changed; } private async getPaymentsForPendingPayInvoiceRefresh( @@ -2673,6 +2687,8 @@ export default class NostrWalletConnectStore { this.findAndUpdateConnection(connection); }); + this.lookupPaymentsCache = null; + this.scheduleSave(); } private async recordFailedPayment({ diff --git a/utils/NostrConnectUtils.test.ts b/utils/NostrConnectUtils.test.ts index 52de96519..bc55209ae 100644 --- a/utils/NostrConnectUtils.test.ts +++ b/utils/NostrConnectUtils.test.ts @@ -1049,6 +1049,8 @@ describe('NostrConnectUtils', () => { jest.fn().mockResolvedValue(payments); const getCashuPayments = (payments: CashuPayment[] = []) => jest.fn().mockResolvedValue(payments); + const getCashuInvoices = (invoices: CashuInvoice[] = []) => + jest.fn().mockResolvedValue(invoices); it('finds a Lightning invoice from the node by payment hash', async () => { (BackendUtils as any).lookupInvoice = jest.fn().mockResolvedValue({ @@ -1064,7 +1066,7 @@ describe('NostrConnectUtils', () => { const tx = await NostrConnectUtils.lookupInvoiceTransaction({ request: { payment_hash: HASH_A }, isCashu: false, - cashuInvoices: [], + getCashuInvoices: getCashuInvoices(), getCashuPayments: getCashuPayments(), getLightningPayments: getPayments }); @@ -1089,7 +1091,7 @@ describe('NostrConnectUtils', () => { const tx = await NostrConnectUtils.lookupInvoiceTransaction({ request: { payment_hash: HASH_A }, isCashu: false, - cashuInvoices: [], + getCashuInvoices: getCashuInvoices(), getCashuPayments: getCashuPayments(), getLightningPayments: getPayments }); @@ -1116,7 +1118,7 @@ describe('NostrConnectUtils', () => { const tx = await NostrConnectUtils.lookupInvoiceTransaction({ request: { invoice: BOLT11 }, isCashu: false, - cashuInvoices: [], + getCashuInvoices: getCashuInvoices(), getCashuPayments: getCashuPayments(), getLightningPayments: getPayments }); diff --git a/utils/NostrConnectUtils.ts b/utils/NostrConnectUtils.ts index a59838c71..396978313 100644 --- a/utils/NostrConnectUtils.ts +++ b/utils/NostrConnectUtils.ts @@ -111,7 +111,7 @@ export const DEFAULT_INVOICE_EXPIRY_SECONDS = 3600; export interface Nip47LookupInvoiceContext { request: Nip47LookupInvoiceRequest; isCashu: boolean; - cashuInvoices: CashuInvoice[]; + getCashuInvoices: () => Promise; getCashuPayments: () => Promise; getLightningPayments: () => Promise; } @@ -857,7 +857,7 @@ export default class NostrConnectUtils { const { request } = ctx; const cashuInvoice = await NostrConnectUtils.findCashuInvoiceByLookupRequest( - ctx.cashuInvoices, + await ctx.getCashuInvoices(), request ); if (cashuInvoice) {