auto canceling bolt11s from lnd when auto dropped from DB (#793)
* auto canceling bolt11s from lnd when auto dropped from DB * auto canceling bolt11s from lnd when auto dropped from DB * removed semicolon for lint * changed cancleHodlInvoic to deletePayment function * updated code to account for failed LND deletes * linter fixes * updated to only remove hashes and bolt11's from model when successfully deleted from LND * updated to revert unsuccessful deletes from LND and add those values back into the db * linter fix and renaming for clarity * updated WITH query * added if statement to account for invoices not returning from db * fixed linter * reverted docker-compose.yml * made it dry * made it dry * added a comment because the query might be confusing * made query moar dry * Query formatting * Fix query returns number of rows instead of rows * updated to * fixed linter * removed lnbits dir * removed gitignore and docker-compose.yml from pr * added deleting from LND in wallet resolver * linter + added missing import * fixed merge conflict * refine invoice deletion --------- Co-authored-by: ekzyis <ek@stacker.news> Co-authored-by: keyan <keyan.kousha+huumn@gmail.com>
This commit is contained in:
parent
1444ff476e
commit
35d212573e
|
@ -1,4 +1,4 @@
|
|||
import { getIdentity, createHodlInvoice, createInvoice, decodePaymentRequest, payViaPaymentRequest, cancelHodlInvoice, getInvoice as getInvoiceFromLnd, getNode, authenticatedLndGrpc } from 'ln-service'
|
||||
import { getIdentity, createHodlInvoice, createInvoice, decodePaymentRequest, payViaPaymentRequest, cancelHodlInvoice, getInvoice as getInvoiceFromLnd, getNode, authenticatedLndGrpc, deletePayment } from 'ln-service'
|
||||
import { GraphQLError } from 'graphql'
|
||||
import crypto from 'crypto'
|
||||
import serialize from './serial'
|
||||
|
@ -8,7 +8,7 @@ import { SELECT } from './item'
|
|||
import { lnAddrOptions } from '../../lib/lnurl'
|
||||
import { msatsToSats, msatsToSatsDecimal } from '../../lib/format'
|
||||
import { LNDAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema } from '../../lib/validate'
|
||||
import { ANON_BALANCE_LIMIT_MSATS, ANON_INV_PENDING_LIMIT, ANON_USER_ID, BALANCE_LIMIT_MSATS, INV_PENDING_LIMIT, USER_IDS_BALANCE_NO_LIMIT } from '../../lib/constants'
|
||||
import { ANON_BALANCE_LIMIT_MSATS, ANON_INV_PENDING_LIMIT, ANON_USER_ID, BALANCE_LIMIT_MSATS, INVOICE_RETENTION_DAYS, INV_PENDING_LIMIT, USER_IDS_BALANCE_NO_LIMIT } from '../../lib/constants'
|
||||
import { datePivot } from '../../lib/time'
|
||||
import assertGofacYourself from './ofac'
|
||||
import { HEX_REGEX } from '../../lib/macaroon'
|
||||
|
@ -371,21 +371,40 @@ export default {
|
|||
}))
|
||||
return inv
|
||||
},
|
||||
dropBolt11: async (parent, { id }, { me, models }) => {
|
||||
dropBolt11: async (parent, { id }, { me, models, lnd }) => {
|
||||
if (!me) {
|
||||
throw new GraphQLError('you must be logged in', { extensions: { code: 'UNAUTHENTICATED' } })
|
||||
}
|
||||
|
||||
await models.withdrawl.update({
|
||||
where: {
|
||||
userId: me.id,
|
||||
id: Number(id),
|
||||
createdAt: {
|
||||
lte: datePivot(new Date(), { days: -7 })
|
||||
}
|
||||
},
|
||||
data: { bolt11: null, hash: null }
|
||||
})
|
||||
const retention = `${INVOICE_RETENTION_DAYS} days`
|
||||
|
||||
const [invoice] = await models.$queryRaw`
|
||||
WITH to_be_updated AS (
|
||||
SELECT id, hash, bolt11
|
||||
FROM "Withdrawl"
|
||||
WHERE "userId" = ${me.id}
|
||||
AND id = ${Number(id)}
|
||||
AND now() > created_at + interval '${retention}'
|
||||
AND hash IS NOT NULL
|
||||
), updated_rows AS (
|
||||
UPDATE "Withdrawl"
|
||||
SET hash = NULL, bolt11 = NULL
|
||||
FROM to_be_updated
|
||||
WHERE "Withdrawl".id = to_be_updated.id)
|
||||
SELECT * FROM to_be_updated;`
|
||||
|
||||
if (invoice) {
|
||||
try {
|
||||
await deletePayment({ id: invoice.hash, lnd })
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
await models.withdrawl.update({
|
||||
where: { id: invoice.id },
|
||||
data: { hash: invoice.hash, bolt11: invoice.bolt11 }
|
||||
})
|
||||
throw new GraphQLError('failed to drop bolt11 from lnd', { extensions: { code: 'BAD_INPUT' } })
|
||||
}
|
||||
}
|
||||
return { id }
|
||||
},
|
||||
upsertWalletLND: async (parent, { settings, ...data }, { me, models }) => {
|
||||
|
|
|
@ -161,11 +161,12 @@ function PrivacyOption ({ wd }) {
|
|||
try {
|
||||
await dropBolt11({ variables: { id: wd.id } })
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
toaster.danger('unable to delete invoice')
|
||||
toaster.danger('unable to delete invoice: ' + err.message || err.toString?.())
|
||||
throw err
|
||||
} finally {
|
||||
onClose()
|
||||
}
|
||||
}
|
||||
onClose()
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import serialize from '../api/resolvers/serial.js'
|
||||
import {
|
||||
getInvoice, getPayment, cancelHodlInvoice,
|
||||
getInvoice, getPayment, cancelHodlInvoice, deletePayment,
|
||||
subscribeToInvoices, subscribeToPayments, subscribeToInvoice
|
||||
} from 'ln-service'
|
||||
import { sendUserNotification } from '../api/webPush/index.js'
|
||||
|
@ -253,14 +253,37 @@ async function checkWithdrawal ({ data: { hash }, boss, models, lnd }) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function autoDropBolt11s ({ models }) {
|
||||
await serialize(models, models.$executeRaw`
|
||||
UPDATE "Withdrawl"
|
||||
SET hash = NULL, bolt11 = NULL
|
||||
WHERE "userId" IN (SELECT id FROM users WHERE "autoDropBolt11s")
|
||||
AND now() > created_at + interval '${INVOICE_RETENTION_DAYS} days'
|
||||
AND hash IS NOT NULL;`
|
||||
)
|
||||
export async function autoDropBolt11s ({ models, lnd }) {
|
||||
const retention = `${INVOICE_RETENTION_DAYS} days`
|
||||
|
||||
// This query will update the withdrawls and return what the hash and bol11 values were before the update
|
||||
const invoices = await models.$queryRaw`
|
||||
WITH to_be_updated AS (
|
||||
SELECT id, hash, bolt11
|
||||
FROM "Withdrawl"
|
||||
WHERE "userId" IN (SELECT id FROM users WHERE "autoDropBolt11s")
|
||||
AND now() > created_at + interval '${retention}'
|
||||
AND hash IS NOT NULL
|
||||
), updated_rows AS (
|
||||
UPDATE "Withdrawl"
|
||||
SET hash = NULL, bolt11 = NULL
|
||||
FROM to_be_updated
|
||||
WHERE "Withdrawl".id = to_be_updated.id)
|
||||
SELECT * FROM to_be_updated;`
|
||||
|
||||
if (invoices.length > 0) {
|
||||
for (const invoice of invoices) {
|
||||
try {
|
||||
await deletePayment({ id: invoice.hash, lnd })
|
||||
} catch (error) {
|
||||
console.error(`Error removing invoice with hash ${invoice.hash}:`, error)
|
||||
await models.withdrawl.update({
|
||||
where: { id: invoice.id },
|
||||
data: { hash: invoice.hash, bolt11: invoice.bolt11 }
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The callback subscriptions above will NOT get called for HODL invoices that are already paid.
|
||||
|
|
Loading…
Reference in New Issue