Add error handling
This commit is contained in:
parent
f0d0d07bad
commit
85162b6d33
123
lib/anonymous.js
123
lib/anonymous.js
|
@ -9,8 +9,54 @@ import { useMe } from '../components/me'
|
||||||
import { msatsToSats } from './format'
|
import { msatsToSats } from './format'
|
||||||
import FundError from '../components/fund-error'
|
import FundError from '../components/fund-error'
|
||||||
import { INVOICE } from '../fragments/wallet'
|
import { INVOICE } from '../fragments/wallet'
|
||||||
|
import InvoiceStatus from '../components/invoice-status'
|
||||||
|
import { sleep } from './time'
|
||||||
|
import { Button } from 'react-bootstrap'
|
||||||
|
import { CopyInput } from '../components/form'
|
||||||
|
|
||||||
const Invoice = ({ id, ...props }) => {
|
const Contacts = ({ invoiceHash }) => {
|
||||||
|
const subject = `Support request for payment hash: ${invoiceHash}`
|
||||||
|
const body = 'Hi, I successfully paid for <insert action> but the action did not work.'
|
||||||
|
return (
|
||||||
|
<div className='d-flex flex-column justify-content-center'>
|
||||||
|
<span>Payment hash</span>
|
||||||
|
<div className='w-100'>
|
||||||
|
<CopyInput type='text' placeholder={invoiceHash} readOnly noForm />
|
||||||
|
</div>
|
||||||
|
<div className='d-flex flex-row justify-content-center'>
|
||||||
|
<a
|
||||||
|
href={`mailto:kk@stacker.news?subject=${subject}&body=${body}`} className='nav-link p-0 d-inline-flex'
|
||||||
|
target='_blank' rel='noreferrer'
|
||||||
|
>
|
||||||
|
e-mail
|
||||||
|
</a>
|
||||||
|
<span className='mx-2 text-muted'> \ </span>
|
||||||
|
<a
|
||||||
|
href='https://tribes.sphinx.chat/t/stackerzchat' className='nav-link p-0 d-inline-flex'
|
||||||
|
target='_blank' rel='noreferrer'
|
||||||
|
>
|
||||||
|
sphinx
|
||||||
|
</a>
|
||||||
|
<span className='mx-2 text-muted'> \ </span>
|
||||||
|
<a
|
||||||
|
href='https://t.me/k00bideh' className='nav-link p-0 d-inline-flex'
|
||||||
|
target='_blank' rel='noreferrer'
|
||||||
|
>
|
||||||
|
telegram
|
||||||
|
</a>
|
||||||
|
<span className='mx-2 text-muted'> \ </span>
|
||||||
|
<a
|
||||||
|
href='https://simplex.chat/contact#/?v=1-2&smp=smp%3A%2F%2F6iIcWT_dF2zN_w5xzZEY7HI2Prbh3ldP07YTyDexPjE%3D%40smp10.simplex.im%2FebLYaEFGjsD3uK4fpE326c5QI1RZSxau%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAV086Oj5yCsavWzIbRMCVuF6jq793Tt__rWvCec__viI%253D%26srv%3Drb2pbttocvnbrngnwziclp2f4ckjq65kebafws6g4hy22cdaiv5dwjqd.onion&data=%7B%22type%22%3A%22group%22%2C%22groupLinkId%22%3A%22cZwSGoQhyOUulzp7rwCdWQ%3D%3D%22%7D' className='nav-link p-0 d-inline-flex'
|
||||||
|
target='_blank' rel='noreferrer'
|
||||||
|
>
|
||||||
|
simplex
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Invoice = ({ id, hash, errorCount, repeat, ...props }) => {
|
||||||
const { data, loading, error } = useQuery(INVOICE, {
|
const { data, loading, error } = useQuery(INVOICE, {
|
||||||
pollInterval: 1000,
|
pollInterval: 1000,
|
||||||
variables: { id }
|
variables: { id }
|
||||||
|
@ -22,7 +68,26 @@ const Invoice = ({ id, ...props }) => {
|
||||||
if (!data || loading) {
|
if (!data || loading) {
|
||||||
return <QrSkeleton status='loading' />
|
return <QrSkeleton status='loading' />
|
||||||
}
|
}
|
||||||
return <QrInvoice invoice={data.invoice} {...props} />
|
|
||||||
|
let errorStatus = 'Something went wrong. Please try again.'
|
||||||
|
if (errorCount > 1) {
|
||||||
|
errorStatus = 'Something still went wrong.\nPlease contact admins for support or to request a refund.'
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<QrInvoice invoice={data.invoice} {...props} />
|
||||||
|
{errorCount > 0
|
||||||
|
? (
|
||||||
|
<>
|
||||||
|
<InvoiceStatus variant='failed' status={errorStatus} />
|
||||||
|
{errorCount === 1
|
||||||
|
? <div className='d-flex flex-row mt-3 justify-content-center'><Button variant='info' onClick={repeat}>Retry</Button></div>
|
||||||
|
: <Contacts invoiceHash={hash} />}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
: null}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
|
@ -40,25 +105,51 @@ export const useAnonymous = (fn, options = defaultOptions) => {
|
||||||
const showModal = useShowModal()
|
const showModal = useShowModal()
|
||||||
const [fnArgs, setFnArgs] = useState()
|
const [fnArgs, setFnArgs] = useState()
|
||||||
|
|
||||||
|
// fix for bug where `showModal` runs the code for two modals and thus executes `onConfirmation` twice
|
||||||
|
let called = false
|
||||||
|
let errorCount = 0
|
||||||
|
const onConfirmation = useCallback(
|
||||||
|
onClose => {
|
||||||
|
called = false
|
||||||
|
return async ({ id, satsReceived, hash }) => {
|
||||||
|
if (called) return
|
||||||
|
called = true
|
||||||
|
await sleep(2000)
|
||||||
|
const repeat = () =>
|
||||||
|
fn(satsReceived, ...fnArgs, hash)
|
||||||
|
.then(onClose)
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error)
|
||||||
|
errorCount++
|
||||||
|
onClose()
|
||||||
|
showModal(onClose => (
|
||||||
|
<Invoice
|
||||||
|
id={id}
|
||||||
|
hash={hash}
|
||||||
|
onConfirmation={onConfirmation(onClose)}
|
||||||
|
successVerb='received'
|
||||||
|
errorCount={errorCount}
|
||||||
|
repeat={repeat}
|
||||||
|
/>
|
||||||
|
), { keepOpen: true })
|
||||||
|
})
|
||||||
|
// prevents infinite loop of calling `onConfirmation`
|
||||||
|
if (errorCount === 0) await repeat()
|
||||||
|
}
|
||||||
|
}, [fn, fnArgs]
|
||||||
|
)
|
||||||
|
|
||||||
const invoice = data?.createInvoice
|
const invoice = data?.createInvoice
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (invoice) {
|
if (invoice) {
|
||||||
// fix for bug where `showModal` runs the code for two modals and thus executes `onSuccess` twice
|
showModal(onClose => (
|
||||||
let called = false
|
|
||||||
showModal(onClose =>
|
|
||||||
<Invoice
|
<Invoice
|
||||||
id={invoice.id}
|
id={invoice.id}
|
||||||
onConfirmation={
|
hash={invoice.hash}
|
||||||
async ({ satsReceived }) => {
|
onConfirmation={onConfirmation(onClose)}
|
||||||
setTimeout(async () => {
|
successVerb='received'
|
||||||
if (called) return
|
/>
|
||||||
called = true
|
), { keepOpen: true }
|
||||||
await fn(satsReceived, ...fnArgs, invoice.hash)
|
|
||||||
onClose()
|
|
||||||
}, 2000)
|
|
||||||
}
|
|
||||||
} successVerb='received'
|
|
||||||
/>, { keepOpen: true }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}, [invoice?.id])
|
}, [invoice?.id])
|
||||||
|
|
|
@ -45,3 +45,5 @@ export function timeLeft (timeStamp) {
|
||||||
return parseInt(secondsPast / (3600 * 24)) + ' days'
|
return parseInt(secondsPast / (3600 * 24)) + ' days'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const sleep = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms))
|
||||||
|
|
Loading…
Reference in New Issue