fix invoice waiting
This commit is contained in:
		
							parent
							
								
									e9a5925c50
								
							
						
					
					
						commit
						dcab8e1365
					
				@ -1,4 +1,4 @@
 | 
				
			|||||||
import { useCallback, useMemo } from 'react'
 | 
					import { useCallback } from 'react'
 | 
				
			||||||
import { useMe } from './me'
 | 
					import { useMe } from './me'
 | 
				
			||||||
import { gql, useApolloClient, useMutation } from '@apollo/client'
 | 
					import { gql, useApolloClient, useMutation } from '@apollo/client'
 | 
				
			||||||
import { useWallet } from '@/wallets/index'
 | 
					import { useWallet } from '@/wallets/index'
 | 
				
			||||||
@ -60,43 +60,6 @@ export const useInvoice = () => {
 | 
				
			|||||||
    return that(data.invoice)
 | 
					    return that(data.invoice)
 | 
				
			||||||
  }, [client])
 | 
					  }, [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 }) => {
 | 
					  const cancel = useCallback(async ({ hash, hmac }) => {
 | 
				
			||||||
    if (!hash || !hmac) {
 | 
					    if (!hash || !hmac) {
 | 
				
			||||||
      throw new Error('missing hash or hmac')
 | 
					      throw new Error('missing hash or hmac')
 | 
				
			||||||
@ -107,7 +70,44 @@ export const useInvoice = () => {
 | 
				
			|||||||
    return inv
 | 
					    return inv
 | 
				
			||||||
  }, [cancelInvoice])
 | 
					  }, [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 = () => {
 | 
					export const useWalletPayment = () => {
 | 
				
			||||||
@ -118,12 +118,13 @@ export const useWalletPayment = () => {
 | 
				
			|||||||
    if (!wallet) {
 | 
					    if (!wallet) {
 | 
				
			||||||
      throw new NoAttachedWalletError()
 | 
					      throw new NoAttachedWalletError()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    const controller = invoiceController(id, invoice.isInvoice)
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      return await new Promise((resolve, reject) => {
 | 
					      return await new Promise((resolve, reject) => {
 | 
				
			||||||
        // can't use await here since we might pay JIT invoices and sendPaymentAsync is not supported yet.
 | 
					        // 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
 | 
					        // see https://www.webln.guide/building-lightning-apps/webln-reference/webln.sendpaymentasync
 | 
				
			||||||
        wallet.sendPayment(bolt11).catch(reject)
 | 
					        wallet.sendPayment(bolt11).catch(reject)
 | 
				
			||||||
        invoice.waitUntilPaid({ id }, waitFor)
 | 
					        controller.wait(waitFor)
 | 
				
			||||||
          .then(resolve)
 | 
					          .then(resolve)
 | 
				
			||||||
          .catch(reject)
 | 
					          .catch(reject)
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
@ -131,7 +132,7 @@ export const useWalletPayment = () => {
 | 
				
			|||||||
      console.error('payment failed:', err)
 | 
					      console.error('payment failed:', err)
 | 
				
			||||||
      throw err
 | 
					      throw err
 | 
				
			||||||
    } finally {
 | 
					    } finally {
 | 
				
			||||||
      invoice.stopWaiting()
 | 
					      controller.stop()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }, [wallet, invoice])
 | 
					  }, [wallet, invoice])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user