80 lines
2.9 KiB
JavaScript
80 lines
2.9 KiB
JavaScript
|
import { msatsToSats, satsToMsats } from '@/lib/format'
|
||
|
|
||
|
export const anonable = false
|
||
|
export const supportsPessimism = false
|
||
|
export const supportsOptimism = true
|
||
|
|
||
|
export async function getCost ({ sats }) {
|
||
|
return satsToMsats(sats)
|
||
|
}
|
||
|
|
||
|
export async function perform ({ invoiceId, sats, id: itemId }, { me, cost, tx }) {
|
||
|
itemId = parseInt(itemId)
|
||
|
|
||
|
let invoiceData = {}
|
||
|
if (invoiceId) {
|
||
|
invoiceData = { invoiceId, invoiceActionState: 'PENDING' }
|
||
|
// store a reference to the item in the invoice
|
||
|
await tx.invoice.update({
|
||
|
where: { id: invoiceId },
|
||
|
data: { actionId: itemId }
|
||
|
})
|
||
|
}
|
||
|
|
||
|
const itemAct = await tx.itemAct.create({
|
||
|
data: { msats: cost, itemId, userId: me.id, act: 'DONT_LIKE_THIS', ...invoiceData }
|
||
|
})
|
||
|
|
||
|
const [{ path }] = await tx.$queryRaw`SELECT ltree2text(path) as path FROM "Item" WHERE id = ${itemId}::INTEGER`
|
||
|
return { id: itemId, sats, act: 'DONT_LIKE_THIS', path, actId: itemAct.id }
|
||
|
}
|
||
|
|
||
|
export async function retry ({ invoiceId, newInvoiceId }, { tx, cost }) {
|
||
|
await tx.itemAct.updateMany({ where: { invoiceId }, data: { invoiceId: newInvoiceId, invoiceActionState: 'PENDING' } })
|
||
|
const [{ id, path }] = await tx.$queryRaw`
|
||
|
SELECT "Item".id, ltree2text(path) as path
|
||
|
FROM "Item"
|
||
|
JOIN "ItemAct" ON "Item".id = "ItemAct"."itemId"
|
||
|
WHERE "ItemAct"."invoiceId" = ${newInvoiceId}::INTEGER`
|
||
|
return { id, sats: msatsToSats(cost), act: 'DONT_LIKE_THIS', path }
|
||
|
}
|
||
|
|
||
|
export async function onPaid ({ invoice, actId }, { tx }) {
|
||
|
let itemAct
|
||
|
if (invoice) {
|
||
|
await tx.itemAct.updateMany({ where: { invoiceId: invoice.id }, data: { invoiceActionState: 'PAID' } })
|
||
|
itemAct = await tx.itemAct.findFirst({ where: { invoiceId: invoice.id } })
|
||
|
} else if (actId) {
|
||
|
itemAct = await tx.itemAct.findUnique({ where: { id: actId } })
|
||
|
} else {
|
||
|
throw new Error('No invoice or actId')
|
||
|
}
|
||
|
|
||
|
const msats = BigInt(itemAct.msats)
|
||
|
const sats = msatsToSats(msats)
|
||
|
|
||
|
// denormalize downzaps
|
||
|
await tx.$executeRaw`
|
||
|
WITH zapper AS (
|
||
|
SELECT trust FROM users WHERE id = ${itemAct.userId}::INTEGER
|
||
|
), zap AS (
|
||
|
INSERT INTO "ItemUserAgg" ("userId", "itemId", "downZapSats")
|
||
|
VALUES (${itemAct.userId}::INTEGER, ${itemAct.itemId}::INTEGER, ${sats}::INTEGER)
|
||
|
ON CONFLICT ("itemId", "userId") DO UPDATE
|
||
|
SET "downZapSats" = "ItemUserAgg"."downZapSats" + ${sats}::INTEGER, updated_at = now()
|
||
|
RETURNING LOG("downZapSats" / GREATEST("downZapSats" - ${sats}::INTEGER, 1)::FLOAT) AS log_sats
|
||
|
)
|
||
|
UPDATE "Item"
|
||
|
SET "weightedDownVotes" = "weightedDownVotes" + (zapper.trust * zap.log_sats)
|
||
|
FROM zap, zapper
|
||
|
WHERE "Item".id = ${itemAct.itemId}::INTEGER`
|
||
|
}
|
||
|
|
||
|
export async function onFail ({ invoice }, { tx }) {
|
||
|
await tx.itemAct.updateMany({ where: { invoiceId: invoice.id }, data: { invoiceActionState: 'FAILED' } })
|
||
|
}
|
||
|
|
||
|
export async function describe ({ itemId, sats }, { cost, actionId }) {
|
||
|
return `SN: downzap of ${sats ?? msatsToSats(cost)} sats to #${itemId ?? actionId}`
|
||
|
}
|