Revert "Merge serializeInvoiceable with serialize (#1040)"

This reverts commit e7e7cbff0a.
This commit is contained in:
keyan 2024-04-08 15:50:39 -05:00
parent e7e7cbff0a
commit 9f79ff1f89
11 changed files with 93 additions and 111 deletions

View File

@ -1,6 +1,6 @@
import { GraphQLError } from 'graphql' import { GraphQLError } from 'graphql'
import { ensureProtocol, removeTracking, stripTrailingSlash } from '@/lib/url' import { ensureProtocol, removeTracking, stripTrailingSlash } from '@/lib/url'
import serialize from './serial' import serialize, { serializeInvoicable } from './serial'
import { decodeCursor, LIMIT, nextCursorEncoded } from '@/lib/cursor' import { decodeCursor, LIMIT, nextCursorEncoded } from '@/lib/cursor'
import { getMetadata, metadataRuleSets } from 'page-metadata-parser' import { getMetadata, metadataRuleSets } from 'page-metadata-parser'
import { ruleSet as publicationDateRuleSet } from '@/lib/timedate-scraper' import { ruleSet as publicationDateRuleSet } from '@/lib/timedate-scraper'
@ -849,9 +849,9 @@ export default {
throw new GraphQLError('you must be logged in', { extensions: { code: 'FORBIDDEN' } }) throw new GraphQLError('you must be logged in', { extensions: { code: 'FORBIDDEN' } })
} }
await serialize( await serializeInvoicable(
models.$queryRawUnsafe(`${SELECT} FROM poll_vote($1::INTEGER, $2::INTEGER) AS "Item"`, Number(id), Number(me.id)), models.$queryRawUnsafe(`${SELECT} FROM poll_vote($1::INTEGER, $2::INTEGER) AS "Item"`, Number(id), Number(me.id)),
{ models, lnd, me, hash, hmac } { me, models, lnd, hash, hmac }
) )
return id return id
@ -883,6 +883,7 @@ export default {
if (idempotent) { if (idempotent) {
await serialize( await serialize(
models,
models.$queryRaw` models.$queryRaw`
SELECT SELECT
item_act(${Number(id)}::INTEGER, ${me.id}::INTEGER, ${act}::"ItemActType", item_act(${Number(id)}::INTEGER, ${me.id}::INTEGER, ${act}::"ItemActType",
@ -890,16 +891,15 @@ export default {
FROM "ItemAct" FROM "ItemAct"
WHERE act IN ('TIP', 'FEE') WHERE act IN ('TIP', 'FEE')
AND "itemId" = ${Number(id)}::INTEGER AND "itemId" = ${Number(id)}::INTEGER
AND "userId" = ${me.id}::INTEGER)::INTEGER)`, AND "userId" = ${me.id}::INTEGER)::INTEGER)`
{ models }
) )
} else { } else {
await serialize( await serializeInvoicable(
models.$queryRaw` models.$queryRaw`
SELECT SELECT
item_act(${Number(id)}::INTEGER, item_act(${Number(id)}::INTEGER,
${me?.id || ANON_USER_ID}::INTEGER, ${act}::"ItemActType", ${Number(sats)}::INTEGER)`, ${me?.id || ANON_USER_ID}::INTEGER, ${act}::"ItemActType", ${Number(sats)}::INTEGER)`,
{ models, lnd, me, hash, hmac, fee: sats } { me, models, lnd, hash, hmac, enforceFee: sats }
) )
} }
@ -1284,10 +1284,10 @@ export const updateItem = async (parent, { sub: subName, forward, options, ...it
const uploadIds = uploadIdsFromText(item.text, { models }) const uploadIds = uploadIdsFromText(item.text, { models })
const { totalFees: imgFees } = await imageFeesInfo(uploadIds, { models, me }) const { totalFees: imgFees } = await imageFeesInfo(uploadIds, { models, me })
item = await serialize( item = await serializeInvoicable(
models.$queryRawUnsafe(`${SELECT} FROM update_item($1::JSONB, $2::JSONB, $3::JSONB, $4::INTEGER[]) AS "Item"`, models.$queryRawUnsafe(`${SELECT} FROM update_item($1::JSONB, $2::JSONB, $3::JSONB, $4::INTEGER[]) AS "Item"`,
JSON.stringify(item), JSON.stringify(fwdUsers), JSON.stringify(options), uploadIds), JSON.stringify(item), JSON.stringify(fwdUsers), JSON.stringify(options), uploadIds),
{ models, lnd, me, hash, hmac, fee: imgFees } { models, lnd, hash, hmac, me, enforceFee: imgFees }
) )
await createMentions(item, models) await createMentions(item, models)
@ -1320,22 +1320,22 @@ export const createItem = async (parent, { forward, options, ...item }, { me, mo
const uploadIds = uploadIdsFromText(item.text, { models }) const uploadIds = uploadIdsFromText(item.text, { models })
const { totalFees: imgFees } = await imageFeesInfo(uploadIds, { models, me }) const { totalFees: imgFees } = await imageFeesInfo(uploadIds, { models, me })
let fee = 0 let enforceFee = 0
if (!me) { if (!me) {
if (item.parentId) { if (item.parentId) {
fee = ANON_FEE_MULTIPLIER enforceFee = ANON_FEE_MULTIPLIER
} else { } else {
const sub = await models.sub.findUnique({ where: { name: item.subName } }) const sub = await models.sub.findUnique({ where: { name: item.subName } })
fee = sub.baseCost * ANON_FEE_MULTIPLIER + (item.boost || 0) enforceFee = sub.baseCost * ANON_FEE_MULTIPLIER + (item.boost || 0)
} }
} }
fee += imgFees enforceFee += imgFees
item = await serialize( item = await serializeInvoicable(
models.$queryRawUnsafe( models.$queryRawUnsafe(
`${SELECT} FROM create_item($1::JSONB, $2::JSONB, $3::JSONB, '${spamInterval}'::INTERVAL, $4::INTEGER[]) AS "Item"`, `${SELECT} FROM create_item($1::JSONB, $2::JSONB, $3::JSONB, '${spamInterval}'::INTERVAL, $4::INTEGER[]) AS "Item"`,
JSON.stringify(item), JSON.stringify(fwdUsers), JSON.stringify(options), uploadIds), JSON.stringify(item), JSON.stringify(fwdUsers), JSON.stringify(options), uploadIds),
{ models, lnd, me, hash, hmac, fee } { models, lnd, hash, hmac, me, enforceFee }
) )
await createMentions(item, models) await createMentions(item, models)

View File

@ -1,6 +1,6 @@
import { GraphQLError } from 'graphql' import { GraphQLError } from 'graphql'
import { amountSchema, ssValidate } from '@/lib/validate' import { amountSchema, ssValidate } from '@/lib/validate'
import serialize from './serial' import { serializeInvoicable } from './serial'
import { ANON_USER_ID } from '@/lib/constants' import { ANON_USER_ID } from '@/lib/constants'
import { getItem } from './item' import { getItem } from './item'
import { topUsers } from './user' import { topUsers } from './user'
@ -168,9 +168,9 @@ export default {
donateToRewards: async (parent, { sats, hash, hmac }, { me, models, lnd }) => { donateToRewards: async (parent, { sats, hash, hmac }, { me, models, lnd }) => {
await ssValidate(amountSchema, { amount: sats }) await ssValidate(amountSchema, { amount: sats })
await serialize( await serializeInvoicable(
models.$queryRaw`SELECT donate(${sats}::INTEGER, ${me?.id || ANON_USER_ID}::INTEGER)`, models.$queryRaw`SELECT donate(${sats}::INTEGER, ${me?.id || ANON_USER_ID}::INTEGER)`,
{ models, lnd, me, hash, hmac, fee: sats } { models, lnd, hash, hmac, me, enforceFee: sats }
) )
return sats return sats

View File

@ -1,5 +1,4 @@
import { GraphQLError } from 'graphql' import { GraphQLError } from 'graphql'
import { timingSafeEqual } from 'crypto'
import retry from 'async-retry' import retry from 'async-retry'
import Prisma from '@prisma/client' import Prisma from '@prisma/client'
import { settleHodlInvoice } from 'ln-service' import { settleHodlInvoice } from 'ln-service'
@ -7,30 +6,13 @@ import { createHmac } from './wallet'
import { msatsToSats, numWithUnits } from '@/lib/format' import { msatsToSats, numWithUnits } from '@/lib/format'
import { BALANCE_LIMIT_MSATS } from '@/lib/constants' import { BALANCE_LIMIT_MSATS } from '@/lib/constants'
export default async function serialize (trx, { models, lnd, me, hash, hmac, fee }) { export default async function serialize (models, ...calls) {
// wrap first argument in array if not array already return await retry(async bail => {
const isArray = Array.isArray(trx)
if (!isArray) trx = [trx]
// conditional queries can be added inline using && syntax
// we filter any falsy value out here
trx = trx.filter(q => !!q)
let invoice
if (hash) {
invoice = await verifyPayment(models, hash, hmac, fee)
trx = [
models.$executeRaw`SELECT confirm_invoice(${hash}, ${invoice.msatsReceived})`,
...trx
]
}
let results = await retry(async bail => {
try { try {
const [, ...results] = await models.$transaction( const [, ...result] = await models.$transaction(
[models.$executeRaw`SELECT ASSERT_SERIALIZED()`, ...trx], [models.$executeRaw`SELECT ASSERT_SERIALIZED()`, ...calls],
{ isolationLevel: Prisma.TransactionIsolationLevel.Serializable }) { isolationLevel: Prisma.TransactionIsolationLevel.Serializable })
return results return calls.length > 1 ? result : result[0]
} catch (error) { } catch (error) {
console.log(error) console.log(error)
// two cases where we get insufficient funds: // two cases where we get insufficient funds:
@ -82,20 +64,38 @@ export default async function serialize (trx, { models, lnd, me, hash, hmac, fee
maxTimeout: 100, maxTimeout: 100,
retries: 10 retries: 10
}) })
if (hash) {
if (invoice?.isHeld) {
await settleHodlInvoice({ secret: invoice.preimage, lnd })
}
// remove first element since that is the confirmed invoice
results = results.slice(1)
}
// if first argument was not an array, unwrap the result
return isArray ? results : results[0]
} }
async function verifyPayment (models, hash, hmac, fee) { export async function serializeInvoicable (query, { models, lnd, hash, hmac, me, enforceFee }) {
if (!me && !hash) {
throw new Error('you must be logged in or pay')
}
let trx = Array.isArray(query) ? query : [query]
let invoice
if (hash) {
invoice = await checkInvoice(models, hash, hmac, enforceFee)
trx = [
models.$executeRaw`SELECT confirm_invoice(${hash}, ${invoice.msatsReceived})`,
...trx
]
}
let results = await serialize(models, ...trx)
if (hash) {
if (invoice?.isHeld) { await settleHodlInvoice({ secret: invoice.preimage, lnd }) }
// remove first element since that is the confirmed invoice
[, ...results] = results
}
// if there is only one result, return it directly, else the array
results = results.flat(2)
return results.length > 1 ? results : results[0]
}
export async function checkInvoice (models, hash, hmac, fee) {
if (!hash) { if (!hash) {
throw new GraphQLError('hash required', { extensions: { code: 'BAD_INPUT' } }) throw new GraphQLError('hash required', { extensions: { code: 'BAD_INPUT' } })
} }
@ -103,7 +103,7 @@ async function verifyPayment (models, hash, hmac, fee) {
throw new GraphQLError('hmac required', { extensions: { code: 'BAD_INPUT' } }) throw new GraphQLError('hmac required', { extensions: { code: 'BAD_INPUT' } })
} }
const hmac2 = createHmac(hash) const hmac2 = createHmac(hash)
if (!timingSafeEqual(Buffer.from(hmac), Buffer.from(hmac2))) { if (hmac !== hmac2) {
throw new GraphQLError('bad hmac', { extensions: { code: 'FORBIDDEN' } }) throw new GraphQLError('bad hmac', { extensions: { code: 'FORBIDDEN' } })
} }

View File

@ -1,5 +1,5 @@
import { GraphQLError } from 'graphql' import { GraphQLError } from 'graphql'
import serialize from './serial' import { serializeInvoicable } from './serial'
import { TERRITORY_COST_MONTHLY, TERRITORY_COST_ONCE, TERRITORY_COST_YEARLY, TERRITORY_PERIOD_COST } from '@/lib/constants' import { TERRITORY_COST_MONTHLY, TERRITORY_COST_ONCE, TERRITORY_COST_YEARLY, TERRITORY_PERIOD_COST } from '@/lib/constants'
import { datePivot, whenRange } from '@/lib/time' import { datePivot, whenRange } from '@/lib/time'
import { ssValidate, territorySchema } from '@/lib/validate' import { ssValidate, territorySchema } from '@/lib/validate'
@ -246,9 +246,9 @@ export default {
return sub return sub
} }
const results = await serialize( const results = await serializeInvoicable(
queries, queries,
{ models, lnd, me, hash, hmac, fee: sub.billingCost }) { models, lnd, hash, hmac, me, enforceFee: sub.billingCost })
return results[1] return results[1]
}, },
toggleMuteSub: async (parent, { name }, { me, models }) => { toggleMuteSub: async (parent, { name }, { me, models }) => {
@ -344,9 +344,8 @@ export default {
const billPaidUntil = nextBilling(new Date(), data.billingType) const billPaidUntil = nextBilling(new Date(), data.billingType)
const cost = BigInt(1000) * BigInt(billingCost) const cost = BigInt(1000) * BigInt(billingCost)
const newSub = { ...data, billPaidUntil, billingCost, userId: me.id, status: 'ACTIVE' } const newSub = { ...data, billPaidUntil, billingCost, userId: me.id, status: 'ACTIVE' }
const isTransfer = oldSub.userId !== me.id
await serialize([ await serializeInvoicable([
models.user.update({ models.user.update({
where: { where: {
id: me.id id: me.id
@ -366,11 +365,11 @@ export default {
} }
}), }),
models.sub.update({ where: { name }, data: newSub }), models.sub.update({ where: { name }, data: newSub }),
isTransfer && models.territoryTransfer.create({ data: { subName: name, oldUserId: oldSub.userId, newUserId: me.id } }) oldSub.userId !== me.id && models.territoryTransfer.create({ data: { subName: name, oldUserId: oldSub.userId, newUserId: me.id } })
], ].filter(q => !!q),
{ models, lnd, hash, me, hmac, fee: billingCost }) { models, lnd, hash, hmac, me, enforceFee: billingCost })
if (isTransfer) notifyTerritoryTransfer({ models, sub: newSub, to: me }) if (oldSub.userId !== me.id) notifyTerritoryTransfer({ models, sub: newSub, to: me })
} }
}, },
Sub: { Sub: {
@ -418,7 +417,7 @@ async function createSub (parent, data, { me, models, lnd, hash, hmac }) {
const cost = BigInt(1000) * BigInt(billingCost) const cost = BigInt(1000) * BigInt(billingCost)
try { try {
const results = await serialize([ const results = await serializeInvoicable([
// bill 'em // bill 'em
models.user.update({ models.user.update({
where: { where: {
@ -457,7 +456,7 @@ async function createSub (parent, data, { me, models, lnd, hash, hmac }) {
subName: data.name subName: data.name
} }
}) })
], { models, lnd, me, hash, hmac, fee: billingCost }) ], { models, lnd, hash, hmac, me, enforceFee: billingCost })
return results[1] return results[1]
} catch (error) { } catch (error) {
@ -512,7 +511,7 @@ async function updateSub (parent, { oldName, ...data }, { me, models, lnd, hash,
const proratedCost = proratedBillingCost(oldSub, data.billingType) const proratedCost = proratedBillingCost(oldSub, data.billingType)
if (proratedCost > 0) { if (proratedCost > 0) {
const cost = BigInt(1000) * BigInt(proratedCost) const cost = BigInt(1000) * BigInt(proratedCost)
const results = await serialize([ const results = await serializeInvoicable([
models.user.update({ models.user.update({
where: { where: {
id: me.id id: me.id
@ -538,7 +537,7 @@ async function updateSub (parent, { oldName, ...data }, { me, models, lnd, hash,
userId: me.id userId: me.id
} }
}) })
], { models, lnd, me, hash, hmac, fee: proratedCost }) ], { models, lnd, hash, hmac, me, enforceFee: proratedCost })
return results[2] return results[2]
} }
} }

View File

@ -354,12 +354,10 @@ export default {
expires_at: expiresAt expires_at: expiresAt
}) })
const [inv] = await serialize( const [inv] = await serialize(models,
models.$queryRaw`SELECT * FROM create_invoice(${invoice.id}, ${hodlInvoice ? invoice.secret : null}::TEXT, ${invoice.request}, models.$queryRaw`SELECT * FROM create_invoice(${invoice.id}, ${hodlInvoice ? invoice.secret : null}::TEXT, ${invoice.request},
${expiresAt}::timestamp, ${amount * 1000}, ${user.id}::INTEGER, ${description}, NULL, NULL, ${expiresAt}::timestamp, ${amount * 1000}, ${user.id}::INTEGER, ${description}, NULL, NULL,
${invLimit}::INTEGER, ${balanceLimit})`, ${invLimit}::INTEGER, ${balanceLimit})`)
{ models }
)
// the HMAC is only returned during invoice creation // the HMAC is only returned during invoice creation
// this makes sure that only the person who created this invoice // this makes sure that only the person who created this invoice
@ -380,7 +378,7 @@ export default {
throw new GraphQLError('bad hmac', { extensions: { code: 'FORBIDDEN' } }) throw new GraphQLError('bad hmac', { extensions: { code: 'FORBIDDEN' } })
} }
await cancelHodlInvoice({ id: hash, lnd }) await cancelHodlInvoice({ id: hash, lnd })
const inv = await serialize( const inv = await serialize(models,
models.invoice.update({ models.invoice.update({
where: { where: {
hash hash
@ -388,9 +386,7 @@ export default {
data: { data: {
cancelled: true cancelled: true
} }
}), }))
{ models }
)
return inv return inv
}, },
dropBolt11: async (parent, { id }, { me, models, lnd }) => { dropBolt11: async (parent, { id }, { me, models, lnd }) => {
@ -664,11 +660,9 @@ export async function createWithdrawal (parent, { invoice, maxFee }, { me, model
const user = await models.user.findUnique({ where: { id: me.id } }) const user = await models.user.findUnique({ where: { id: me.id } })
// create withdrawl transactionally (id, bolt11, amount, fee) // create withdrawl transactionally (id, bolt11, amount, fee)
const [withdrawl] = await serialize( const [withdrawl] = await serialize(models,
models.$queryRaw`SELECT * FROM create_withdrawl(${decoded.id}, ${invoice}, models.$queryRaw`SELECT * FROM create_withdrawl(${decoded.id}, ${invoice},
${Number(decoded.mtokens)}, ${msatsFee}, ${user.name}, ${autoWithdraw})`, ${Number(decoded.mtokens)}, ${msatsFee}, ${user.name}, ${autoWithdraw})`)
{ models }
)
payViaPaymentRequest({ payViaPaymentRequest({
lnd, lnd,

View File

@ -80,13 +80,11 @@ export default async ({ query: { username, amount, nostr, comment, payerdata: pa
expires_at: expiresAt expires_at: expiresAt
}) })
await serialize( await serialize(models,
models.$queryRaw`SELECT * FROM create_invoice(${invoice.id}, NULL, ${invoice.request}, models.$queryRaw`SELECT * FROM create_invoice(${invoice.id}, NULL, ${invoice.request},
${expiresAt}::timestamp, ${Number(amount)}, ${user.id}::INTEGER, ${noteStr || description}, ${expiresAt}::timestamp, ${Number(amount)}, ${user.id}::INTEGER, ${noteStr || description},
${comment || null}, ${parsedPayerData || null}::JSONB, ${INV_PENDING_LIMIT}::INTEGER, ${comment || null}, ${parsedPayerData || null}::JSONB, ${INV_PENDING_LIMIT}::INTEGER,
${USER_IDS_BALANCE_NO_LIMIT.includes(Number(user.id)) ? 0 : BALANCE_LIMIT_MSATS})`, ${USER_IDS_BALANCE_NO_LIMIT.includes(Number(user.id)) ? 0 : BALANCE_LIMIT_MSATS})`)
{ models }
)
return res.status(200).json({ return res.status(200).json({
pr: invoice.request, pr: invoice.request,

View File

@ -36,10 +36,8 @@ export async function getServerSideProps ({ req, res, query: { id, error = null
try { try {
// attempt to send gift // attempt to send gift
// catch any errors and just ignore them for now // catch any errors and just ignore them for now
await serialize( await serialize(models,
models.$queryRawUnsafe('SELECT invite_drain($1::INTEGER, $2::TEXT)', session.user.id, id), models.$queryRawUnsafe('SELECT invite_drain($1::INTEGER, $2::TEXT)', session.user.id, id))
{ models }
)
const invite = await models.invite.findUnique({ where: { id } }) const invite = await models.invite.findUnique({ where: { id } })
notifyInvite(invite.userId) notifyInvite(invite.userId)
} catch (e) { } catch (e) {

View File

@ -17,6 +17,7 @@ export async function auction ({ models }) {
// for each item, run serialized auction function // for each item, run serialized auction function
items.forEach(async item => { items.forEach(async item => {
await serialize(models.$executeRaw`SELECT run_auction(${item.id}::INTEGER)`, { models }) await serialize(models,
models.$executeRaw`SELECT run_auction(${item.id}::INTEGER)`)
}) })
} }

View File

@ -79,11 +79,9 @@ export async function earn ({ name }) {
console.log('stacker', earner.userId, 'earned', earnings, 'proportion', earner.proportion, 'rank', earner.rank, 'type', earner.type) console.log('stacker', earner.userId, 'earned', earnings, 'proportion', earner.proportion, 'rank', earner.rank, 'type', earner.type)
if (earnings > 0) { if (earnings > 0) {
await serialize( await serialize(models,
models.$executeRaw`SELECT earn(${earner.userId}::INTEGER, ${earnings}, models.$executeRaw`SELECT earn(${earner.userId}::INTEGER, ${earnings},
${now}::timestamp without time zone, ${earner.type}::"EarnType", ${earner.id}::INTEGER, ${earner.rank}::INTEGER)`, ${now}::timestamp without time zone, ${earner.type}::"EarnType", ${earner.id}::INTEGER, ${earner.rank}::INTEGER)`)
{ models }
)
const userN = notifications[earner.userId] || {} const userN = notifications[earner.userId] || {}

View File

@ -34,7 +34,7 @@ export async function territoryBilling ({ data: { subName }, boss, models }) {
try { try {
const queries = paySubQueries(sub, models) const queries = paySubQueries(sub, models)
await serialize(queries, { models }) await serialize(models, ...queries)
} catch (e) { } catch (e) {
console.error(e) console.error(e)
await territoryStatusUpdate() await territoryStatusUpdate()
@ -42,7 +42,7 @@ export async function territoryBilling ({ data: { subName }, boss, models }) {
} }
export async function territoryRevenue ({ models }) { export async function territoryRevenue ({ models }) {
await serialize( await serialize(models,
models.$executeRaw` models.$executeRaw`
WITH revenue AS ( WITH revenue AS (
SELECT coalesce(sum(msats), 0) as revenue, "subName", "userId" SELECT coalesce(sum(msats), 0) as revenue, "subName", "userId"
@ -69,7 +69,6 @@ export async function territoryRevenue ({ models }) {
) )
UPDATE users SET msats = users.msats + "SubActResult".msats UPDATE users SET msats = users.msats + "SubActResult".msats
FROM "SubActResult" FROM "SubActResult"
WHERE users.id = "SubActResult"."userId"`, WHERE users.id = "SubActResult"."userId"`
{ models }
) )
} }

View File

@ -121,10 +121,10 @@ async function checkInvoice ({ data: { hash }, boss, models, lnd }) {
// ALSO: is_confirmed and is_held are mutually exclusive // ALSO: is_confirmed and is_held are mutually exclusive
// that is, a hold invoice will first be is_held but not is_confirmed // that is, a hold invoice will first be is_held but not is_confirmed
// and once it's settled it will be is_confirmed but not is_held // and once it's settled it will be is_confirmed but not is_held
const [[{ confirm_invoice: code }]] = await serialize([ const [[{ confirm_invoice: code }]] = await serialize(models,
models.$queryRaw`SELECT confirm_invoice(${inv.id}, ${Number(inv.received_mtokens)})`, models.$queryRaw`SELECT confirm_invoice(${inv.id}, ${Number(inv.received_mtokens)})`,
models.invoice.update({ where: { hash }, data: { confirmedIndex: inv.confirmed_index } }) models.invoice.update({ where: { hash }, data: { confirmedIndex: inv.confirmed_index } })
], { models }) )
// don't send notifications for JIT invoices // don't send notifications for JIT invoices
if (dbInv.preimage) return if (dbInv.preimage) return
@ -143,7 +143,7 @@ async function checkInvoice ({ data: { hash }, boss, models, lnd }) {
// and without setting the user balance // and without setting the user balance
// those will be set when the invoice is settled by user action // those will be set when the invoice is settled by user action
const expiresAt = new Date(Math.min(dbInv.expiresAt, datePivot(new Date(), { seconds: 60 }))) const expiresAt = new Date(Math.min(dbInv.expiresAt, datePivot(new Date(), { seconds: 60 })))
return await serialize([ return await serialize(models,
models.$queryRaw` models.$queryRaw`
INSERT INTO pgboss.job (name, data, retrylimit, retrybackoff, startafter) INSERT INTO pgboss.job (name, data, retrylimit, retrybackoff, startafter)
VALUES ('finalizeHodlInvoice', jsonb_build_object('hash', ${hash}), 21, true, ${expiresAt})`, VALUES ('finalizeHodlInvoice', jsonb_build_object('hash', ${hash}), 21, true, ${expiresAt})`,
@ -154,12 +154,11 @@ async function checkInvoice ({ data: { hash }, boss, models, lnd }) {
expiresAt, expiresAt,
isHeld: true isHeld: true
} }
}) }))
], { models })
} }
if (inv.is_canceled) { if (inv.is_canceled) {
return await serialize( return await serialize(models,
models.invoice.update({ models.invoice.update({
where: { where: {
hash: inv.id hash: inv.id
@ -167,8 +166,7 @@ async function checkInvoice ({ data: { hash }, boss, models, lnd }) {
data: { data: {
cancelled: true cancelled: true
} }
}), { models } }))
)
} }
} }
@ -230,10 +228,8 @@ async function checkWithdrawal ({ data: { hash }, boss, models, lnd }) {
if (wdrwl?.is_confirmed) { if (wdrwl?.is_confirmed) {
const fee = Number(wdrwl.payment.fee_mtokens) const fee = Number(wdrwl.payment.fee_mtokens)
const paid = Number(wdrwl.payment.mtokens) - fee const paid = Number(wdrwl.payment.mtokens) - fee
const [{ confirm_withdrawl: code }] = await serialize( const [{ confirm_withdrawl: code }] = await serialize(models, models.$queryRaw`
models.$queryRaw`SELECT confirm_withdrawl(${dbWdrwl.id}::INTEGER, ${paid}, ${fee})`, SELECT confirm_withdrawl(${dbWdrwl.id}::INTEGER, ${paid}, ${fee})`)
{ models }
)
if (code === 0) { if (code === 0) {
notifyWithdrawal(dbWdrwl.userId, wdrwl) notifyWithdrawal(dbWdrwl.userId, wdrwl)
} }
@ -249,10 +245,9 @@ async function checkWithdrawal ({ data: { hash }, boss, models, lnd }) {
status = 'ROUTE_NOT_FOUND' status = 'ROUTE_NOT_FOUND'
} }
await serialize( await serialize(models,
models.$executeRaw` models.$executeRaw`
SELECT reverse_withdrawl(${dbWdrwl.id}::INTEGER, ${status}::"WithdrawlStatus")`, SELECT reverse_withdrawl(${dbWdrwl.id}::INTEGER, ${status}::"WithdrawlStatus")`
{ models }
) )
} }
} }