stacker.news/worker/autowithdraw.js

47 lines
1.6 KiB
JavaScript

import { msatsToSats, satsToMsats } from '@/lib/format'
import { createWithdrawal } from '@/api/resolvers/wallet'
import { createInvoice } from 'wallets/server'
export async function autoWithdraw ({ data: { id }, models, lnd }) {
const user = await models.user.findUnique({ where: { id } })
if (user.autoWithdrawThreshold === null || user.autoWithdrawMaxFeePercent === null) return
const threshold = satsToMsats(user.autoWithdrawThreshold)
const excess = Number(user.msats - threshold)
// excess must be greater than 10% of threshold
if (excess < Number(threshold) * 0.1) return
const maxFeeMsats = Math.ceil(excess * (user.autoWithdrawMaxFeePercent / 100.0))
const msats = excess - maxFeeMsats
// must be >= 1 sat
if (msats < 1000) return
// maxFee is expected to be in sats, ie "msatsFeePaying" is always divisible by 1000
const maxFee = msatsToSats(maxFeeMsats)
// check that
// 1. the user doesn't have an autowithdraw pending
// 2. we have not already attempted to autowithdraw this fee recently
const [pendingOrFailed] = await models.$queryRaw`
SELECT EXISTS(
SELECT *
FROM "Withdrawl"
WHERE "userId" = ${id} AND "autoWithdraw"
AND (status IS NULL
OR (
status <> 'CONFIRMED' AND
now() < created_at + interval '1 hour' AND
"msatsFeePaying" >= ${satsToMsats(maxFee)}
))
)`
if (pendingOrFailed.exists) return
const { invoice, wallet } = await createInvoice(id, { msats, description: 'SN: autowithdrawal', expiry: 360 }, { models })
return await createWithdrawal(null,
{ invoice, maxFee },
{ me: { id }, models, lnd, walletId: wallet.id })
}