64 lines
2.0 KiB
JavaScript
64 lines
2.0 KiB
JavaScript
|
import { lnAddrOptions } from './lnurl'
|
||
|
import { lnAddrSchema, ssValidate } from './validate'
|
||
|
|
||
|
export async function fetchLnAddrInvoice ({ addr, amount, maxFee, comment, ...payer },
|
||
|
{
|
||
|
me, models, lnd, autoWithdraw = false,
|
||
|
lnService: { decodePaymentRequest, getIdentity }
|
||
|
}) {
|
||
|
const options = await lnAddrOptions(addr)
|
||
|
await ssValidate(lnAddrSchema, { addr, amount, maxFee, comment, ...payer }, options)
|
||
|
|
||
|
if (payer) {
|
||
|
payer = {
|
||
|
...payer,
|
||
|
identifier: payer.identifier ? `${me.name}@stacker.news` : undefined
|
||
|
}
|
||
|
payer = Object.fromEntries(
|
||
|
Object.entries(payer).filter(([, value]) => !!value)
|
||
|
)
|
||
|
}
|
||
|
|
||
|
const milliamount = 1000 * amount
|
||
|
const callback = new URL(options.callback)
|
||
|
callback.searchParams.append('amount', milliamount)
|
||
|
|
||
|
if (comment?.length) {
|
||
|
callback.searchParams.append('comment', comment)
|
||
|
}
|
||
|
|
||
|
let stringifiedPayerData = ''
|
||
|
if (payer && Object.entries(payer).length) {
|
||
|
stringifiedPayerData = JSON.stringify(payer)
|
||
|
callback.searchParams.append('payerdata', stringifiedPayerData)
|
||
|
}
|
||
|
|
||
|
// call callback with amount and conditionally comment
|
||
|
const res = await (await fetch(callback.toString())).json()
|
||
|
if (res.status === 'ERROR') {
|
||
|
throw new Error(res.reason)
|
||
|
}
|
||
|
|
||
|
// decode invoice
|
||
|
try {
|
||
|
const decoded = await decodePaymentRequest({ lnd, request: res.pr })
|
||
|
const ourPubkey = (await getIdentity({ lnd })).public_key
|
||
|
if (autoWithdraw && decoded.destination === ourPubkey && process.env.NODE_ENV === 'production') {
|
||
|
// unset lnaddr so we don't trigger another withdrawal with same destination
|
||
|
await models.wallet.deleteMany({
|
||
|
// TODO: replace hardcoded 'LIGHTNING_ADDRESS' with wallet.type
|
||
|
where: { userId: me.id, type: 'LIGHTNING_ADDRESS' }
|
||
|
})
|
||
|
throw new Error('automated withdrawals to other stackers are not allowed')
|
||
|
}
|
||
|
if (!decoded.mtokens || BigInt(decoded.mtokens) !== BigInt(milliamount)) {
|
||
|
throw new Error('invoice has incorrect amount')
|
||
|
}
|
||
|
} catch (e) {
|
||
|
console.log(e)
|
||
|
throw e
|
||
|
}
|
||
|
|
||
|
return res
|
||
|
}
|