fix invoice waiting

This commit is contained in:
k00b 2024-11-07 19:55:11 -06:00
parent e9a5925c50
commit dcab8e1365
1 changed files with 42 additions and 41 deletions

View File

@ -1,4 +1,4 @@
import { useCallback, useMemo } from 'react'
import { useCallback } from 'react'
import { useMe } from './me'
import { gql, useApolloClient, useMutation } from '@apollo/client'
import { useWallet } from '@/wallets/index'
@ -60,43 +60,6 @@ export const useInvoice = () => {
return that(data.invoice)
}, [client])
const waitController = useMemo(() => {
const controller = new AbortController()
const signal = controller.signal
controller.wait = async ({ id }, waitFor = inv => inv?.actionState === 'PAID') => {
return await new Promise((resolve, reject) => {
const interval = setInterval(async () => {
try {
const paid = await isInvoice({ id }, waitFor)
if (paid) {
resolve()
clearInterval(interval)
signal.removeEventListener('abort', abort)
} else {
console.info(`invoice #${id}: waiting for payment ...`)
}
} catch (err) {
reject(err)
clearInterval(interval)
signal.removeEventListener('abort', abort)
}
}, FAST_POLL_INTERVAL)
const abort = () => {
console.info(`invoice #${id}: stopped waiting`)
resolve()
clearInterval(interval)
signal.removeEventListener('abort', abort)
}
signal.addEventListener('abort', abort)
})
}
controller.stop = () => controller.abort()
return controller
}, [isInvoice])
const cancel = useCallback(async ({ hash, hmac }) => {
if (!hash || !hmac) {
throw new Error('missing hash or hmac')
@ -107,7 +70,44 @@ export const useInvoice = () => {
return inv
}, [cancelInvoice])
return { create, waitUntilPaid: waitController.wait, stopWaiting: waitController.stop, cancel }
return { create, cancel, isInvoice }
}
const invoiceController = (id, isInvoice) => {
const controller = new AbortController()
const signal = controller.signal
controller.wait = async (waitFor = inv => inv?.actionState === 'PAID') => {
return await new Promise((resolve, reject) => {
const interval = setInterval(async () => {
try {
const paid = await isInvoice({ id }, waitFor)
if (paid) {
resolve()
clearInterval(interval)
signal.removeEventListener('abort', abort)
} else {
console.info(`invoice #${id}: waiting for payment ...`)
}
} catch (err) {
reject(err)
clearInterval(interval)
signal.removeEventListener('abort', abort)
}
}, FAST_POLL_INTERVAL)
const abort = () => {
console.info(`invoice #${id}: stopped waiting`)
resolve()
clearInterval(interval)
signal.removeEventListener('abort', abort)
}
signal.addEventListener('abort', abort)
})
}
controller.stop = () => controller.abort()
return controller
}
export const useWalletPayment = () => {
@ -118,12 +118,13 @@ export const useWalletPayment = () => {
if (!wallet) {
throw new NoAttachedWalletError()
}
const controller = invoiceController(id, invoice.isInvoice)
try {
return await new Promise((resolve, reject) => {
// can't use await here since we might pay JIT invoices and sendPaymentAsync is not supported yet.
// see https://www.webln.guide/building-lightning-apps/webln-reference/webln.sendpaymentasync
wallet.sendPayment(bolt11).catch(reject)
invoice.waitUntilPaid({ id }, waitFor)
controller.wait(waitFor)
.then(resolve)
.catch(reject)
})
@ -131,7 +132,7 @@ export const useWalletPayment = () => {
console.error('payment failed:', err)
throw err
} finally {
invoice.stopWaiting()
controller.stop()
}
}, [wallet, invoice])