Return latest state of paid or failed invoice
This commit is contained in:
parent
68513559e4
commit
9cfc18d655
|
@ -1,6 +1,6 @@
|
|||
import { useCallback } from 'react'
|
||||
import { gql, useApolloClient, useMutation } from '@apollo/client'
|
||||
import { INVOICE } from '@/fragments/wallet'
|
||||
import { useApolloClient, useMutation } from '@apollo/client'
|
||||
import { CANCEL_INVOICE, INVOICE } from '@/fragments/wallet'
|
||||
import Invoice from '@/components/invoice'
|
||||
import { useShowModal } from './modal'
|
||||
import { InvoiceCanceledError, InvoiceExpiredError } from '@/wallets/errors'
|
||||
|
@ -10,13 +10,7 @@ export const useInvoice = () => {
|
|||
const client = useApolloClient()
|
||||
const [retryPaidAction] = useMutation(RETRY_PAID_ACTION)
|
||||
|
||||
const [cancelInvoice] = useMutation(gql`
|
||||
mutation cancelInvoice($hash: String!, $hmac: String!) {
|
||||
cancelInvoice(hash: $hash, hmac: $hmac) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`)
|
||||
const [cancelInvoice] = useMutation(CANCEL_INVOICE)
|
||||
|
||||
const isInvoice = useCallback(async ({ id }, that) => {
|
||||
const { data, error } = await client.query({ query: INVOICE, fetchPolicy: 'network-only', variables: { id } })
|
||||
|
@ -40,7 +34,7 @@ export const useInvoice = () => {
|
|||
client.writeQuery({ query: INVOICE, variables: { id }, data: { invoice: data.invoice } })
|
||||
}
|
||||
|
||||
return that(data.invoice)
|
||||
return { invoice: data.invoice, check: that(data.invoice) }
|
||||
}, [client])
|
||||
|
||||
const cancel = useCallback(async ({ hash, hmac }) => {
|
||||
|
@ -49,8 +43,8 @@ export const useInvoice = () => {
|
|||
}
|
||||
|
||||
console.log('canceling invoice:', hash)
|
||||
const inv = await cancelInvoice({ variables: { hash, hmac } })
|
||||
return inv
|
||||
const { data } = await cancelInvoice({ variables: { hash, hmac } })
|
||||
return data.cancelInvoice
|
||||
}, [cancelInvoice])
|
||||
|
||||
const retry = useCallback(async ({ id, hash, hmac }) => {
|
||||
|
@ -83,8 +77,8 @@ export const useQrPayment = () => {
|
|||
let paid
|
||||
const cancelAndReject = async (onClose) => {
|
||||
if (!paid && cancelOnClose) {
|
||||
await invoice.cancel(inv).catch(console.error)
|
||||
reject(new InvoiceCanceledError(inv))
|
||||
const updatedInv = await invoice.cancel(inv).catch(console.error)
|
||||
reject(new InvoiceCanceledError(updatedInv))
|
||||
}
|
||||
resolve(inv)
|
||||
}
|
||||
|
@ -99,7 +93,7 @@ export const useQrPayment = () => {
|
|||
waitFor={waitFor}
|
||||
onExpired={inv => reject(new InvoiceExpiredError(inv))}
|
||||
onCanceled={inv => { onClose(); reject(new InvoiceCanceledError(inv, inv?.actionError)) }}
|
||||
onPayment={() => { paid = true; onClose(); resolve(inv) }}
|
||||
onPayment={(inv) => { paid = true; onClose(); resolve(inv) }}
|
||||
poll
|
||||
/>,
|
||||
{ keepOpen, persistOnNavigate, onClose: cancelAndReject })
|
||||
|
|
|
@ -98,26 +98,30 @@ export function usePaidMutation (mutation,
|
|||
error: e instanceof InvoiceCanceledError && e.actionError ? e : undefined
|
||||
})
|
||||
|
||||
const dataKey = Object.keys(data)[0]
|
||||
|
||||
// should we wait for the invoice to be paid?
|
||||
if (response?.paymentMethod === 'OPTIMISTIC' && !forceWaitForPayment) {
|
||||
// onCompleted is called before the invoice is paid for optimistic updates
|
||||
ourOnCompleted?.(data)
|
||||
// don't wait to pay the invoice
|
||||
waitForPayment(invoice, { persistOnNavigate, waitFor }).then(() => {
|
||||
waitForPayment(invoice, { persistOnNavigate, waitFor }).then((invoice) => {
|
||||
// invoice might have been retried during payment
|
||||
data = {
|
||||
[dataKey]: {
|
||||
...data[dataKey],
|
||||
invoice
|
||||
}
|
||||
}
|
||||
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()
|
||||
}
|
||||
[dataKey]: {
|
||||
...data[dataKey],
|
||||
invoice
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +142,7 @@ export function usePaidMutation (mutation,
|
|||
// create new data object
|
||||
// ( hmac is only returned on invoice creation so we need to add it back to the data )
|
||||
data = {
|
||||
[Object.keys(data)[0]]: {
|
||||
[dataKey]: {
|
||||
...paidAction,
|
||||
invoice: { ...paidAction.invoice, hmac: invoice.hmac }
|
||||
}
|
||||
|
|
|
@ -221,3 +221,12 @@ export const SET_WALLET_PRIORITY = gql`
|
|||
setWalletPriority(id: $id, priority: $priority)
|
||||
}
|
||||
`
|
||||
|
||||
export const CANCEL_INVOICE = gql`
|
||||
${INVOICE_FIELDS}
|
||||
mutation cancelInvoice($hash: String!, $hmac: String!) {
|
||||
cancelInvoice(hash: $hash, hmac: $hmac) {
|
||||
...InvoiceFields
|
||||
}
|
||||
}
|
||||
`
|
||||
|
|
|
@ -113,11 +113,12 @@ const invoiceController = (inv, isInvoice) => {
|
|||
const signal = controller.signal
|
||||
controller.wait = async (waitFor = inv => inv?.actionState === 'PAID') => {
|
||||
return await new Promise((resolve, reject) => {
|
||||
let updatedInvoice, paid
|
||||
const interval = setInterval(async () => {
|
||||
try {
|
||||
const paid = await isInvoice(inv, waitFor)
|
||||
({ invoice: updatedInvoice, check: paid } = await isInvoice(inv, waitFor))
|
||||
if (paid) {
|
||||
resolve(inv)
|
||||
resolve(updatedInvoice)
|
||||
clearInterval(interval)
|
||||
signal.removeEventListener('abort', abort)
|
||||
} else {
|
||||
|
@ -132,7 +133,7 @@ const invoiceController = (inv, isInvoice) => {
|
|||
|
||||
const abort = () => {
|
||||
console.info(`invoice #${inv.id}: stopped waiting`)
|
||||
resolve(inv)
|
||||
resolve(updatedInvoice)
|
||||
clearInterval(interval)
|
||||
signal.removeEventListener('abort', abort)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue