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 { GraphQLError } from 'graphql'
|
||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
import serialize from './serial'
|
import serialize from './serial'
|
||||||
@ -8,7 +8,7 @@ import { SELECT } from './item'
|
|||||||
import { lnAddrOptions } from '../../lib/lnurl'
|
import { lnAddrOptions } from '../../lib/lnurl'
|
||||||
import { msatsToSats, msatsToSatsDecimal } from '../../lib/format'
|
import { msatsToSats, msatsToSatsDecimal } from '../../lib/format'
|
||||||
import { LNDAutowithdrawSchema, amountSchema, lnAddrAutowithdrawSchema, lnAddrSchema, ssValidate, withdrawlSchema } from '../../lib/validate'
|
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 { datePivot } from '../../lib/time'
|
||||||
import assertGofacYourself from './ofac'
|
import assertGofacYourself from './ofac'
|
||||||
import { HEX_REGEX } from '../../lib/macaroon'
|
import { HEX_REGEX } from '../../lib/macaroon'
|
||||||
@ -371,21 +371,40 @@ export default {
|
|||||||
}))
|
}))
|
||||||
return inv
|
return inv
|
||||||
},
|
},
|
||||||
dropBolt11: async (parent, { id }, { me, models }) => {
|
dropBolt11: async (parent, { id }, { me, models, lnd }) => {
|
||||||
if (!me) {
|
if (!me) {
|
||||||
throw new GraphQLError('you must be logged in', { extensions: { code: 'UNAUTHENTICATED' } })
|
throw new GraphQLError('you must be logged in', { extensions: { code: 'UNAUTHENTICATED' } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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({
|
await models.withdrawl.update({
|
||||||
where: {
|
where: { id: invoice.id },
|
||||||
userId: me.id,
|
data: { hash: invoice.hash, bolt11: invoice.bolt11 }
|
||||||
id: Number(id),
|
|
||||||
createdAt: {
|
|
||||||
lte: datePivot(new Date(), { days: -7 })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: { bolt11: null, hash: null }
|
|
||||||
})
|
})
|
||||||
|
throw new GraphQLError('failed to drop bolt11 from lnd', { extensions: { code: 'BAD_INPUT' } })
|
||||||
|
}
|
||||||
|
}
|
||||||
return { id }
|
return { id }
|
||||||
},
|
},
|
||||||
upsertWalletLND: async (parent, { settings, ...data }, { me, models }) => {
|
upsertWalletLND: async (parent, { settings, ...data }, { me, models }) => {
|
||||||
|
@ -161,11 +161,12 @@ function PrivacyOption ({ wd }) {
|
|||||||
try {
|
try {
|
||||||
await dropBolt11({ variables: { id: wd.id } })
|
await dropBolt11({ variables: { id: wd.id } })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
toaster.danger('unable to delete invoice: ' + err.message || err.toString?.())
|
||||||
toaster.danger('unable to delete invoice')
|
throw err
|
||||||
}
|
} finally {
|
||||||
}
|
|
||||||
onClose()
|
onClose()
|
||||||
|
}
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import serialize from '../api/resolvers/serial.js'
|
import serialize from '../api/resolvers/serial.js'
|
||||||
import {
|
import {
|
||||||
getInvoice, getPayment, cancelHodlInvoice,
|
getInvoice, getPayment, cancelHodlInvoice, deletePayment,
|
||||||
subscribeToInvoices, subscribeToPayments, subscribeToInvoice
|
subscribeToInvoices, subscribeToPayments, subscribeToInvoice
|
||||||
} from 'ln-service'
|
} from 'ln-service'
|
||||||
import { sendUserNotification } from '../api/webPush/index.js'
|
import { sendUserNotification } from '../api/webPush/index.js'
|
||||||
@ -253,14 +253,37 @@ async function checkWithdrawal ({ data: { hash }, boss, models, lnd }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function autoDropBolt11s ({ models }) {
|
export async function autoDropBolt11s ({ models, lnd }) {
|
||||||
await serialize(models, models.$executeRaw`
|
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"
|
UPDATE "Withdrawl"
|
||||||
SET hash = NULL, bolt11 = NULL
|
SET hash = NULL, bolt11 = NULL
|
||||||
WHERE "userId" IN (SELECT id FROM users WHERE "autoDropBolt11s")
|
FROM to_be_updated
|
||||||
AND now() > created_at + interval '${INVOICE_RETENTION_DAYS} days'
|
WHERE "Withdrawl".id = to_be_updated.id)
|
||||||
AND hash IS NOT NULL;`
|
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.
|
// The callback subscriptions above will NOT get called for HODL invoices that are already paid.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user