deal with webln unlock in sendPayment
This commit is contained in:
parent
4a14e0342b
commit
b8e153a4be
|
@ -1,19 +1,21 @@
|
||||||
import QRCode from 'qrcode.react'
|
import QRCode from 'qrcode.react'
|
||||||
import { CopyInput, InputSkeleton } from './form'
|
import { CopyInput, InputSkeleton } from './form'
|
||||||
import InvoiceStatus from './invoice-status'
|
import InvoiceStatus from './invoice-status'
|
||||||
import { useEffect } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import { useWebLN } from './webln'
|
import { useWebLN } from './webln'
|
||||||
import SimpleCountdown from './countdown'
|
import SimpleCountdown from './countdown'
|
||||||
import Bolt11Info from './bolt11-info'
|
import Bolt11Info from './bolt11-info'
|
||||||
|
|
||||||
export default function Qr ({ asIs, value, webLn, statusVariant, description, status }) {
|
export default function Qr ({ asIs, value, webLn, statusVariant, description, status }) {
|
||||||
const qrValue = asIs ? value : 'lightning:' + value.toUpperCase()
|
const qrValue = asIs ? value : 'lightning:' + value.toUpperCase()
|
||||||
|
|
||||||
const provider = useWebLN()
|
const provider = useWebLN()
|
||||||
|
// XXX antipattern ... we shouldn't be getting multiple renders
|
||||||
|
const sendPayment = useRef(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function effect () {
|
async function effect () {
|
||||||
if (webLn && provider) {
|
if (webLn && provider && !sendPayment.current) {
|
||||||
|
sendPayment.current = true
|
||||||
try {
|
try {
|
||||||
await provider.sendPayment({ bolt11: value })
|
await provider.sendPayment({ bolt11: value })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -91,9 +91,6 @@ function RawWebLNProvider ({ children }) {
|
||||||
flowId: flowId || hash,
|
flowId: flowId || hash,
|
||||||
type: 'payment',
|
type: 'payment',
|
||||||
onPending: async () => {
|
onPending: async () => {
|
||||||
if (provider.status === Status.Locked) {
|
|
||||||
await provider.unlock()
|
|
||||||
}
|
|
||||||
await provider.sendPayment(bolt11)
|
await provider.sendPayment(bolt11)
|
||||||
},
|
},
|
||||||
// hash and hmac are only passed for JIT invoices
|
// hash and hmac are only passed for JIT invoices
|
||||||
|
|
|
@ -44,14 +44,57 @@ export function LNCProvider ({ children }) {
|
||||||
return await lnc.lightning.getInfo()
|
return await lnc.lightning.getInfo()
|
||||||
}, [logger, lnc])
|
}, [logger, lnc])
|
||||||
|
|
||||||
|
const unlock = useCallback(async (connect) => {
|
||||||
|
if (status === Status.Enabled) return config.password
|
||||||
|
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
const cancelAndReject = async () => {
|
||||||
|
reject(new Error('password canceled'))
|
||||||
|
}
|
||||||
|
showModal(onClose => {
|
||||||
|
return (
|
||||||
|
<Form
|
||||||
|
initial={{
|
||||||
|
password: ''
|
||||||
|
}}
|
||||||
|
onSubmit={async (values) => {
|
||||||
|
try {
|
||||||
|
lnc.credentials.password = values?.password
|
||||||
|
setStatus(Status.Enabled)
|
||||||
|
setConfig({ pairingPhrase: lnc.credentials.pairingPhrase, password: values.password })
|
||||||
|
logger.ok('wallet enabled')
|
||||||
|
onClose()
|
||||||
|
resolve(values.password)
|
||||||
|
} catch (err) {
|
||||||
|
logger.error('failed attempt to unlock wallet', err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h4 className='text-center mb-3'>Unlock LNC</h4>
|
||||||
|
<PasswordInput
|
||||||
|
label='password'
|
||||||
|
name='password'
|
||||||
|
/>
|
||||||
|
<div className='mt-5 d-flex justify-content-between'>
|
||||||
|
<CancelButton onClick={() => { onClose(); cancelAndReject() }} />
|
||||||
|
<SubmitButton variant='primary'>unlock</SubmitButton>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
)
|
||||||
|
}, { onClose: cancelAndReject })
|
||||||
|
})
|
||||||
|
}, [logger, showModal, setConfig, lnc, status])
|
||||||
|
|
||||||
const sendPayment = useCallback(async (bolt11) => {
|
const sendPayment = useCallback(async (bolt11) => {
|
||||||
const hash = bolt11Tags(bolt11).payment_hash
|
const hash = bolt11Tags(bolt11).payment_hash
|
||||||
logger.info('sending payment:', `payment_hash=${hash}`)
|
logger.info('sending payment:', `payment_hash=${hash}`)
|
||||||
|
|
||||||
return await mutex.runExclusive(async () => {
|
return await mutex.runExclusive(async () => {
|
||||||
try {
|
try {
|
||||||
|
const password = await unlock()
|
||||||
// credentials need to be decrypted before connecting after a disconnect
|
// credentials need to be decrypted before connecting after a disconnect
|
||||||
lnc.credentials.password = config?.password || XXX_DEFAULT_PASSWORD
|
lnc.credentials.password = password || XXX_DEFAULT_PASSWORD
|
||||||
await lnc.connect()
|
await lnc.connect()
|
||||||
const { paymentError, paymentPreimage: preimage } =
|
const { paymentError, paymentPreimage: preimage } =
|
||||||
await lnc.lnd.lightning.sendPaymentSync({ payment_request: bolt11 })
|
await lnc.lnd.lightning.sendPaymentSync({ payment_request: bolt11 })
|
||||||
|
@ -89,7 +132,7 @@ export function LNCProvider ({ children }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [logger, lnc, config])
|
}, [logger, lnc, unlock])
|
||||||
|
|
||||||
const saveConfig = useCallback(async config => {
|
const saveConfig = useCallback(async config => {
|
||||||
setConfig(config)
|
setConfig(config)
|
||||||
|
@ -119,46 +162,6 @@ export function LNCProvider ({ children }) {
|
||||||
logger.info('cleared config')
|
logger.info('cleared config')
|
||||||
}, [logger, lnc])
|
}, [logger, lnc])
|
||||||
|
|
||||||
const unlock = useCallback(async (connect) => {
|
|
||||||
return await new Promise((resolve, reject) => {
|
|
||||||
const cancelAndReject = async () => {
|
|
||||||
reject(new Error('password canceled'))
|
|
||||||
}
|
|
||||||
showModal(onClose => {
|
|
||||||
return (
|
|
||||||
<Form
|
|
||||||
initial={{
|
|
||||||
password: ''
|
|
||||||
}}
|
|
||||||
onSubmit={async (values) => {
|
|
||||||
try {
|
|
||||||
lnc.credentials.password = values?.password
|
|
||||||
setStatus(Status.Enabled)
|
|
||||||
setConfig({ pairingPhrase: lnc.credentials.pairingPhrase, password: values.password })
|
|
||||||
logger.ok('wallet enabled')
|
|
||||||
onClose()
|
|
||||||
resolve()
|
|
||||||
} catch (err) {
|
|
||||||
logger.error('failed attempt to unlock wallet', err)
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<h4 className='text-center mb-3'>Unlock LNC</h4>
|
|
||||||
<PasswordInput
|
|
||||||
label='password'
|
|
||||||
name='password'
|
|
||||||
/>
|
|
||||||
<div className='mt-5 d-flex justify-content-between'>
|
|
||||||
<CancelButton onClick={() => { onClose(); cancelAndReject() }} />
|
|
||||||
<SubmitButton variant='primary'>unlock</SubmitButton>
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
)
|
|
||||||
}, { onClose: cancelAndReject })
|
|
||||||
})
|
|
||||||
}, [logger, showModal, setConfig, lnc])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue