Fix missing item invoice update for optimistic actions

This commit is contained in:
ekzyis 2024-11-27 18:31:20 +01:00
parent 0051c82415
commit a4144d4fcc
4 changed files with 27 additions and 11 deletions

View File

@ -24,15 +24,15 @@ export const useInvoice = () => {
throw error
}
const { hash, cancelled, cancelledAt, actionError, actionState, expiresAt } = data.invoice
const { cancelled, cancelledAt, actionError, actionState, expiresAt } = data.invoice
const expired = cancelledAt && new Date(expiresAt) < new Date(cancelledAt)
if (expired) {
throw new InvoiceExpiredError(hash)
throw new InvoiceExpiredError(data.invoice)
}
if (cancelled || actionError) {
throw new InvoiceCanceledError(hash, actionError)
throw new InvoiceCanceledError(data.invoice, actionError)
}
// write to cache if paid
@ -84,7 +84,7 @@ export const useQrPayment = () => {
const cancelAndReject = async (onClose) => {
if (!paid && cancelOnClose) {
await invoice.cancel(inv).catch(console.error)
reject(new InvoiceCanceledError(inv?.hash))
reject(new InvoiceCanceledError(inv))
}
resolve(inv)
}
@ -97,8 +97,8 @@ export const useQrPayment = () => {
successVerb='received'
walletError={walletError}
waitFor={waitFor}
onExpired={inv => reject(new InvoiceExpiredError(inv?.hash))}
onCanceled={inv => { onClose(); reject(new InvoiceCanceledError(inv?.hash, inv?.actionError)) }}
onExpired={inv => reject(new InvoiceExpiredError(inv))}
onCanceled={inv => { onClose(); reject(new InvoiceCanceledError(inv, inv?.actionError)) }}
onPayment={() => { paid = true; onClose(); resolve(inv) }}
poll
/>,

View File

@ -107,6 +107,20 @@ export function usePaidMutation (mutation,
onPaid?.(client.cache, { data })
}).catch(e => {
console.error('usePaidMutation: failed to pay invoice', e)
if (e.invoice) {
// update the failed invoice for the Apollo cache update
data = {
[Object.keys(data)[0]]: {
...data,
invoice: {
...e.invoice,
actionState: 'FAILED',
cancelled: true,
cancelledAt: new Date()
}
}
}
}
// onPayError is called after the invoice fails to pay
// useful for updating invoiceActionState to FAILED
onPayError?.(e, client.cache, { data })

View File

@ -1,16 +1,17 @@
export class InvoiceCanceledError extends Error {
constructor (hash, actionError) {
super(actionError ?? `invoice canceled: ${hash}`)
constructor (invoice, actionError) {
super(actionError ?? `invoice canceled: ${invoice.hash}`)
this.name = 'InvoiceCanceledError'
this.hash = hash
this.invoice = invoice
this.actionError = actionError
}
}
export class InvoiceExpiredError extends Error {
constructor (hash) {
super(`invoice expired: ${hash}`)
constructor (invoice) {
super(`invoice expired: ${invoice.hash}`)
this.name = 'InvoiceExpiredError'
this.invoice = invoice
}
}

View File

@ -25,6 +25,7 @@ export async function sendPayment (bolt11, credentials, { logger }) {
return preimage
} catch (err) {
const msg = err.message || err.toString?.()
// TODO: pass full invoice
if (msg.includes('invoice expired')) throw new InvoiceExpiredError(hash)
if (msg.includes('canceled')) throw new InvoiceCanceledError(hash)
throw err