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