Add max base fee setting

This commit is contained in:
ekzyis 2024-10-18 18:15:53 +02:00
parent f5ebd573d6
commit 596d67fc68
10 changed files with 54 additions and 7 deletions

View File

@ -647,14 +647,21 @@ async function upsertWallet (
} }
const { id, ...walletData } = data const { id, ...walletData } = data
const { autoWithdrawThreshold, autoWithdrawMaxFeePercent, enabled, priority } = settings const {
autoWithdrawThreshold,
autoWithdrawMaxFeePercent,
autoWithdrawMaxBaseFee,
enabled,
priority
} = settings
const txs = [ const txs = [
models.user.update({ models.user.update({
where: { id: me.id }, where: { id: me.id },
data: { data: {
autoWithdrawMaxFeePercent, autoWithdrawMaxFeePercent,
autoWithdrawThreshold autoWithdrawThreshold,
autoWithdrawMaxBaseFee
} }
}) })
] ]

View File

@ -182,6 +182,7 @@ export default gql`
withdrawMaxFeeDefault: Int! withdrawMaxFeeDefault: Int!
autoWithdrawThreshold: Int autoWithdrawThreshold: Int
autoWithdrawMaxFeePercent: Float autoWithdrawMaxFeePercent: Float
autoWithdrawMaxBaseFee: Int
} }
type UserOptional { type UserOptional {

View File

@ -91,6 +91,7 @@ const typeDefs = `
input AutowithdrawSettings { input AutowithdrawSettings {
autoWithdrawThreshold: Int! autoWithdrawThreshold: Int!
autoWithdrawMaxFeePercent: Float! autoWithdrawMaxFeePercent: Float!
autoWithdrawMaxBaseFee: Int!
priority: Int priority: Int
enabled: Boolean enabled: Boolean
} }

View File

@ -4,6 +4,7 @@ import { useMe } from './me'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { isNumber } from '@/lib/validate' import { isNumber } from '@/lib/validate'
import { useIsClient } from './use-client' import { useIsClient } from './use-client'
import Link from 'next/link'
function autoWithdrawThreshold ({ me }) { function autoWithdrawThreshold ({ me }) {
return isNumber(me?.privates?.autoWithdrawThreshold) ? me?.privates?.autoWithdrawThreshold : 10000 return isNumber(me?.privates?.autoWithdrawThreshold) ? me?.privates?.autoWithdrawThreshold : 10000
@ -12,7 +13,8 @@ function autoWithdrawThreshold ({ me }) {
export function autowithdrawInitial ({ me }) { export function autowithdrawInitial ({ me }) {
return { return {
autoWithdrawThreshold: autoWithdrawThreshold({ me }), autoWithdrawThreshold: autoWithdrawThreshold({ me }),
autoWithdrawMaxFeePercent: isNumber(me?.privates?.autoWithdrawMaxFeePercent) ? me?.privates?.autoWithdrawMaxFeePercent : 1 autoWithdrawMaxFeePercent: isNumber(me?.privates?.autoWithdrawMaxFeePercent) ? me?.privates?.autoWithdrawMaxFeePercent : 1,
autoWithdrawMaxBaseFee: isNumber(me?.privates?.autoWithdrawMaxBaseFee) ? me?.privates?.autoWithdrawMaxBaseFee : 1
} }
} }
@ -51,13 +53,30 @@ export function AutowithdrawSettings ({ wallet }) {
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>} append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
required required
/> />
<h3 className='text-center text-muted pt-3'>network fees</h3>
<h6 className='text-center pb-3'>
the setting that allows a higher max fee will be used during{' '}
<Link
target='_blank'
href='https://docs.lightning.engineering/the-lightning-network/pathfinding'
rel='noreferrer'
>pathfinding
</Link>
</h6>
<Input <Input
label='max fee' label='max fee rate'
name='autoWithdrawMaxFeePercent' name='autoWithdrawMaxFeePercent'
hint='max fee as percent of withdrawal amount' hint='max fee as percent of withdrawal amount'
append={<InputGroup.Text>%</InputGroup.Text>} append={<InputGroup.Text>%</InputGroup.Text>}
required required
/> />
<Input
label='max base fee'
name='autoWithdrawMaxBaseFee'
hint='max fee for any withdrawal amount'
append={<InputGroup.Text className='text-monospace'>sats</InputGroup.Text>}
required
/>
</div> </div>
</div> </div>
</> </>

View File

@ -27,6 +27,7 @@ ${STREAK_FIELDS}
noReferralLinks noReferralLinks
fiatCurrency fiatCurrency
autoWithdrawMaxFeePercent autoWithdrawMaxFeePercent
autoWithdrawMaxBaseFee
autoWithdrawThreshold autoWithdrawThreshold
withdrawMaxFeeDefault withdrawMaxFeeDefault
satsFilter satsFilter

View File

@ -366,7 +366,8 @@ export function advSchema (args) {
export const autowithdrawSchemaMembers = { export const autowithdrawSchemaMembers = {
enabled: boolean(), enabled: boolean(),
autoWithdrawThreshold: intValidator.required('required').min(0, 'must be at least 0').max(msatsToSats(BALANCE_LIMIT_MSATS), `must be at most ${abbrNum(msatsToSats(BALANCE_LIMIT_MSATS))}`), autoWithdrawThreshold: intValidator.required('required').min(0, 'must be at least 0').max(msatsToSats(BALANCE_LIMIT_MSATS), `must be at most ${abbrNum(msatsToSats(BALANCE_LIMIT_MSATS))}`),
autoWithdrawMaxFeePercent: floatValidator.required('required').min(0, 'must be at least 0').max(50, 'must not exceed 50') autoWithdrawMaxFeePercent: floatValidator.required('required').min(0, 'must be at least 0').max(50, 'must not exceed 50'),
autoWithdrawMaxBaseFee: intValidator.required('required').min(0, 'must be at least 0').max(1_000, 'must not exceed 1000')
} }
export const lnAddrAutowithdrawSchema = object({ export const lnAddrAutowithdrawSchema = object({

View File

@ -0,0 +1,8 @@
-- AlterTable
ALTER TABLE "users" ADD COLUMN "autoWithdrawMaxBaseFee" INTEGER;
-- set max_base_fee for users with autowithdrawals enabled to not interfere with them.
-- we set it to 0 instead of 1 because that preserves old behavior.
UPDATE "users"
SET "autoWithdrawMaxBaseFee" = 0
WHERE "autoWithdrawMaxFeePercent" IS NOT NULL;

View File

@ -118,6 +118,7 @@ model User {
lnAddr String? lnAddr String?
autoWithdrawMaxFeePercent Float? autoWithdrawMaxFeePercent Float?
autoWithdrawThreshold Int? autoWithdrawThreshold Int?
autoWithdrawMaxBaseFee Int?
muters Mute[] @relation("muter") muters Mute[] @relation("muter")
muteds Mute[] @relation("muted") muteds Mute[] @relation("muted")
ArcOut Arc[] @relation("fromUser") ArcOut Arc[] @relation("fromUser")

View File

@ -296,6 +296,7 @@ function useServerConfig (wallet) {
const saveConfig = useCallback(async ({ const saveConfig = useCallback(async ({
autoWithdrawThreshold, autoWithdrawThreshold,
autoWithdrawMaxFeePercent, autoWithdrawMaxFeePercent,
autoWithdrawMaxBaseFee,
priority, priority,
enabled, enabled,
...config ...config
@ -310,6 +311,7 @@ function useServerConfig (wallet) {
settings: { settings: {
autoWithdrawThreshold: Number(autoWithdrawThreshold), autoWithdrawThreshold: Number(autoWithdrawThreshold),
autoWithdrawMaxFeePercent: Number(autoWithdrawMaxFeePercent), autoWithdrawMaxFeePercent: Number(autoWithdrawMaxFeePercent),
autoWithdrawMaxBaseFee: Number(autoWithdrawMaxBaseFee),
priority, priority,
enabled enabled
}, },

View File

@ -4,7 +4,10 @@ import { createInvoice } from 'wallets/server'
export async function autoWithdraw ({ data: { id }, models, lnd }) { export async function autoWithdraw ({ data: { id }, models, lnd }) {
const user = await models.user.findUnique({ where: { id } }) const user = await models.user.findUnique({ where: { id } })
if (user.autoWithdrawThreshold === null || user.autoWithdrawMaxFeePercent === null) return if (
user.autoWithdrawThreshold === null ||
user.autoWithdrawMaxFeePercent === null ||
user.autoWithdrawMaxBaseFee === null) return
const threshold = satsToMsats(user.autoWithdrawThreshold) const threshold = satsToMsats(user.autoWithdrawThreshold)
const excess = Number(user.msats - threshold) const excess = Number(user.msats - threshold)
@ -13,7 +16,10 @@ export async function autoWithdraw ({ data: { id }, models, lnd }) {
if (excess < Number(threshold) * 0.1) return if (excess < Number(threshold) * 0.1) return
// floor fee to nearest sat but still denominated in msats // floor fee to nearest sat but still denominated in msats
const maxFeeMsats = msatsSatsFloor(Math.ceil(excess * (user.autoWithdrawMaxFeePercent / 100.0))) const maxFeeMsats = msatsSatsFloor(Math.max(
Math.ceil(excess * (user.autoWithdrawMaxFeePercent / 100.0)),
Number(satsToMsats(user.autoWithdrawMaxBaseFee))
))
// msats will be floored by createInvoice if it needs to be // msats will be floored by createInvoice if it needs to be
const msats = BigInt(excess) - maxFeeMsats const msats = BigInt(excess) - maxFeeMsats