Merge pull request #778 from stackernews/faster-expiry-after-payment

Finalize hodl invoices after payment within 60 seconds
This commit is contained in:
Keyan 2024-02-01 11:04:02 -06:00 committed by GitHub
commit dbde163c74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 15 deletions

View File

@ -19,7 +19,11 @@ export function Invoice ({ invoice, modal, onPayment, info, successVerb }) {
let variant = 'default'
let status = 'waiting for you'
let webLn = true
if (invoice.confirmedAt || (invoice.isHeld && invoice.satsReceived && !expired)) {
if (invoice.cancelled) {
variant = 'failed'
status = 'cancelled'
webLn = false
} else if (invoice.confirmedAt || (invoice.isHeld && invoice.satsReceived && !expired)) {
variant = 'confirmed'
status = `${numWithUnits(invoice.satsReceived, { abbreviate: false })} ${successVerb || 'deposited'}`
webLn = false
@ -27,10 +31,6 @@ export function Invoice ({ invoice, modal, onPayment, info, successVerb }) {
variant = 'failed'
status = 'expired'
webLn = false
} else if (invoice.cancelled) {
variant = 'failed'
status = 'cancelled'
webLn = false
}
useEffect(() => {

View File

@ -6,7 +6,7 @@ import {
import { sendUserNotification } from '../api/webPush/index.js'
import { msatsToSats, numWithUnits, satsToMsats } from '../lib/format'
import { INVOICE_RETENTION_DAYS } from '../lib/constants'
import { sleep } from '../lib/time.js'
import { datePivot, sleep } from '../lib/time.js'
import { sendToLnAddr } from '../api/resolvers/wallet.js'
import retry from 'async-retry'
import { isNumber } from '../lib/validate.js'
@ -142,13 +142,22 @@ async function checkInvoice ({ data: { hash }, boss, models, lnd }) {
}
if (inv.is_held) {
// this is basically confirm_invoice without setting confirmed_at
// First query makes sure that after payment, HODL invoices are settled
// within 60 seconds or they will be canceled to minimize risk of
// force closures or wallets banning us.
// Second query is basically confirm_invoice without setting confirmed_at
// and without setting the user balance
// those will be set when the invoice is settled by user action
return await serialize(models, models.invoice.update({
const expiresAt = new Date(Math.min(dbInv.expiresAt, datePivot(new Date(), { seconds: 60 })))
return await serialize(models,
models.$queryRaw`
INSERT INTO pgboss.job (name, data, retrylimit, retrybackoff, startafter)
VALUES ('finalizeHodlInvoice', jsonb_build_object('hash', ${hash}), 21, true, ${expiresAt})`,
models.invoice.update({
where: { hash },
data: {
msatsReceived: Number(inv.received_mtokens),
expiresAt,
isHeld: true
}
}))
@ -258,13 +267,16 @@ export async function autoDropBolt11s ({ models }) {
// The callback subscriptions above will NOT get called for HODL invoices that are already paid.
// So we manually cancel the HODL invoice here if it wasn't settled by user action
export async function finalizeHodlInvoice ({ data: { hash }, models, lnd }) {
export async function finalizeHodlInvoice ({ data: { hash }, models, lnd, ...args }) {
const inv = await getInvoice({ id: hash, lnd })
if (inv.is_confirmed) {
return
}
await cancelHodlInvoice({ id: hash, lnd })
// sync LND invoice status with invoice status in database
await checkInvoice({ data: { hash }, models, lnd, ...args })
}
export async function checkPendingDeposits (args) {