From 824e98f0074e2724c5462f373edfac8c8a5e4517 Mon Sep 17 00:00:00 2001 From: boufni95 Date: Thu, 18 Dec 2025 20:45:47 +0000 Subject: [PATCH] fixes and cleanup --- proto/autogenerated/client.md | 2 +- proto/autogenerated/go/types.go | 4 +- proto/autogenerated/ts/types.ts | 10 ++-- proto/service/structs.proto | 2 +- src/services/lnd/lnd.ts | 12 ++--- src/services/main/appUserManager.ts | 4 +- src/services/main/applicationManager.ts | 8 +-- src/services/main/liquidityProvider.ts | 13 +++-- src/services/main/paymentManager.ts | 41 +++++---------- src/services/main/settings.ts | 66 ++++--------------------- src/services/main/settingsManager.ts | 2 +- 11 files changed, 52 insertions(+), 112 deletions(-) diff --git a/proto/autogenerated/client.md b/proto/autogenerated/client.md index abd101e9..553049fd 100644 --- a/proto/autogenerated/client.md +++ b/proto/autogenerated/client.md @@ -1169,8 +1169,8 @@ The nostr server will send back a message response, and inside the body there wi - __invitation_link__: _string_ ### CumulativeFees - - __outboundFeeFloor__: _number_ - __serviceFeeBps__: _number_ + - __serviceFeeFloor__: _number_ ### DebitAuthorization - __authorized__: _boolean_ diff --git a/proto/autogenerated/go/types.go b/proto/autogenerated/go/types.go index a4ac016b..a8398d95 100644 --- a/proto/autogenerated/go/types.go +++ b/proto/autogenerated/go/types.go @@ -230,8 +230,8 @@ type CreateOneTimeInviteLinkResponse struct { Invitation_link string `json:"invitation_link"` } type CumulativeFees struct { - Outboundfeefloor int64 `json:"outboundFeeFloor"` - Servicefeebps int64 `json:"serviceFeeBps"` + Servicefeebps int64 `json:"serviceFeeBps"` + Servicefeefloor int64 `json:"serviceFeeFloor"` } type DebitAuthorization struct { Authorized bool `json:"authorized"` diff --git a/proto/autogenerated/ts/types.ts b/proto/autogenerated/ts/types.ts index 7e72d13d..271c9f34 100644 --- a/proto/autogenerated/ts/types.ts +++ b/proto/autogenerated/ts/types.ts @@ -1303,25 +1303,25 @@ export const CreateOneTimeInviteLinkResponseValidate = (o?: CreateOneTimeInviteL } export type CumulativeFees = { - outboundFeeFloor: number serviceFeeBps: number + serviceFeeFloor: number } export const CumulativeFeesOptionalFields: [] = [] export type CumulativeFeesOptions = OptionsBaseMessage & { checkOptionalsAreSet?: [] - outboundFeeFloor_CustomCheck?: (v: number) => boolean serviceFeeBps_CustomCheck?: (v: number) => boolean + serviceFeeFloor_CustomCheck?: (v: number) => boolean } export const CumulativeFeesValidate = (o?: CumulativeFees, opts: CumulativeFeesOptions = {}, path: string = 'CumulativeFees::root.'): Error | null => { if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message') if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null') - if (typeof o.outboundFeeFloor !== 'number') return new Error(`${path}.outboundFeeFloor: is not a number`) - if (opts.outboundFeeFloor_CustomCheck && !opts.outboundFeeFloor_CustomCheck(o.outboundFeeFloor)) return new Error(`${path}.outboundFeeFloor: custom check failed`) - if (typeof o.serviceFeeBps !== 'number') return new Error(`${path}.serviceFeeBps: is not a number`) if (opts.serviceFeeBps_CustomCheck && !opts.serviceFeeBps_CustomCheck(o.serviceFeeBps)) return new Error(`${path}.serviceFeeBps: custom check failed`) + if (typeof o.serviceFeeFloor !== 'number') return new Error(`${path}.serviceFeeFloor: is not a number`) + if (opts.serviceFeeFloor_CustomCheck && !opts.serviceFeeFloor_CustomCheck(o.serviceFeeFloor)) return new Error(`${path}.serviceFeeFloor: custom check failed`) + return null } diff --git a/proto/service/structs.proto b/proto/service/structs.proto index f2aa653b..186475dc 100644 --- a/proto/service/structs.proto +++ b/proto/service/structs.proto @@ -857,7 +857,7 @@ message SwapsList { } message CumulativeFees { - int64 outboundFeeFloor = 2; + int64 serviceFeeFloor = 2; int64 serviceFeeBps = 3; } diff --git a/src/services/lnd/lnd.ts b/src/services/lnd/lnd.ts index 323cda3d..e3a5fe2f 100644 --- a/src/services/lnd/lnd.ts +++ b/src/services/lnd/lnd.ts @@ -63,7 +63,7 @@ export default class { this.htlcCb = htlcCb this.channelEventCb = channelEventCb this.liquidProvider = liquidProvider - + // Skip LND client initialization if using only liquidity provider if (liquidProvider.getSettings().useOnlyLiquidityProvider) { this.log("USE_ONLY_LIQUIDITY_PROVIDER enabled, skipping LND client initialization") @@ -79,7 +79,7 @@ export default class { this.walletKit = new WalletKitClient(dummyTransport) return } - + const { lndAddr, lndCertPath, lndMacaroonPath } = this.getSettings().lndNodeSettings const lndCert = fs.readFileSync(lndCertPath); const macaroon = fs.readFileSync(lndMacaroonPath).toString('hex'); @@ -392,7 +392,7 @@ export default class { const decoded = decodeBolt11(paymentRequest) let numSatoshis = 0 let paymentHash = '' - + for (const section of decoded.sections) { if (section.name === 'amount') { // Amount is in millisatoshis @@ -401,11 +401,11 @@ export default class { paymentHash = section.value as string } } - + if (!paymentHash) { throw new Error("Payment hash not found in invoice") } - + return { numSatoshis, paymentHash } } catch (err: any) { throw new Error(`Failed to decode invoice: ${err.message}`) @@ -434,7 +434,7 @@ export default class { // Force use of provider when bypass is enabled const mustUseProvider = this.liquidProvider.getSettings().useOnlyLiquidityProvider || useProvider if (mustUseProvider) { - const res = await this.liquidProvider.PayInvoice(invoice, decodedAmount, from) + const res = await this.liquidProvider.PayInvoice(invoice, decodedAmount, from, feeLimit) const providerDst = this.liquidProvider.GetProviderDestination() return { feeSat: res.service_fee, valueSat: res.amount_paid, paymentPreimage: res.preimage, providerDst } } diff --git a/src/services/main/appUserManager.ts b/src/services/main/appUserManager.ts index b8b1dc1d..9db8b5e6 100644 --- a/src/services/main/appUserManager.ts +++ b/src/services/main/appUserManager.ts @@ -69,14 +69,14 @@ export default class { throw new Error(`app user ${ctx.user_id} not found`) // TODO: fix logs doxing } const nostrSettings = this.settings.getSettings().nostrRelaySettings - const { max, outboundFeeFloor, serviceFeeBps } = this.applicationManager.paymentManager.GetMaxPayableInvoice(user.balance_sats) + const { max, serviceFeeFloor, serviceFeeBps } = this.applicationManager.paymentManager.GetMaxPayableInvoice(user.balance_sats) return { userId: ctx.user_id, balance: user.balance_sats, max_withdrawable: max, user_identifier: appUser.identifier, network_max_fee_bps: 0, - network_max_fee_fixed: outboundFeeFloor, + network_max_fee_fixed: serviceFeeFloor, service_fee_bps: serviceFeeBps, noffer: nofferEncode({ pubkey: app.nostr_public_key!, offer: appUser.identifier, priceType: OfferPriceType.Spontaneous, relay: nostrSettings.relays[0] }), ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: appUser.identifier, relay: nostrSettings.relays[0] }), diff --git a/src/services/main/applicationManager.ts b/src/services/main/applicationManager.ts index 6f671457..b9752403 100644 --- a/src/services/main/applicationManager.ts +++ b/src/services/main/applicationManager.ts @@ -154,7 +154,7 @@ export default class { const ndebitString = ndebitEncode({ pubkey: app.nostr_public_key!, pointer: u.identifier, relay: nostrSettings.relays[0] }) log("🔗 [DEBUG] Generated ndebit for user", { userId: u.user.user_id, ndebit: ndebitString }) - const { max, outboundFeeFloor, serviceFeeBps } = this.paymentManager.GetMaxPayableInvoice(u.user.balance_sats) + const { max, serviceFeeFloor, serviceFeeBps } = this.paymentManager.GetMaxPayableInvoice(u.user.balance_sats) return { identifier: u.identifier, info: { @@ -163,7 +163,7 @@ export default class { max_withdrawable: max, user_identifier: u.identifier, network_max_fee_bps: 0, - network_max_fee_fixed: outboundFeeFloor, + network_max_fee_fixed: serviceFeeFloor, service_fee_bps: serviceFeeBps, noffer: nofferEncode({ pubkey: app.nostr_public_key!, offer: u.identifier, priceType: OfferPriceType.Spontaneous, relay: nostrSettings.relays[0] }), ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: u.identifier, relay: nostrSettings.relays[0] }), @@ -214,14 +214,14 @@ export default class { const app = await this.storage.applicationStorage.GetApplication(appId) const user = await this.storage.applicationStorage.GetApplicationUser(app, req.user_identifier) const nostrSettings = this.settings.getSettings().nostrRelaySettings - const { max, outboundFeeFloor, serviceFeeBps } = this.paymentManager.GetMaxPayableInvoice(user.user.balance_sats) + const { max, serviceFeeFloor, serviceFeeBps } = this.paymentManager.GetMaxPayableInvoice(user.user.balance_sats) return { max_withdrawable: max, identifier: req.user_identifier, info: { userId: user.user.user_id, balance: user.user.balance_sats, max_withdrawable: max, user_identifier: user.identifier, network_max_fee_bps: 0, - network_max_fee_fixed: outboundFeeFloor, + network_max_fee_fixed: serviceFeeFloor, service_fee_bps: serviceFeeBps, noffer: nofferEncode({ pubkey: app.nostr_public_key!, offer: user.identifier, priceType: OfferPriceType.Spontaneous, relay: nostrSettings.relays[0] }), ndebit: ndebitEncode({ pubkey: app.nostr_public_key!, pointer: user.identifier, relay: nostrSettings.relays[0] }), diff --git a/src/services/main/liquidityProvider.ts b/src/services/main/liquidityProvider.ts index 9bf92f6c..aaca888c 100644 --- a/src/services/main/liquidityProvider.ts +++ b/src/services/main/liquidityProvider.ts @@ -130,7 +130,7 @@ export class LiquidityProvider { return res } this.feesCache = { - outboundFeeFloor: res.network_max_fee_fixed, + serviceFeeFloor: res.network_max_fee_fixed, serviceFeeBps: res.service_fee_bps } this.latestReceivedBalance = res.balance @@ -151,11 +151,11 @@ export class LiquidityProvider { return 0 } const balance = this.latestReceivedBalance - const { outboundFeeFloor, serviceFeeBps } = this.feesCache + const { serviceFeeFloor, serviceFeeBps } = this.feesCache const div = 1 + (serviceFeeBps / 10000) const maxWithoutFixed = Math.floor(balance / div) const fee = balance - maxWithoutFixed - return balance - Math.max(fee, outboundFeeFloor) + return balance - Math.max(fee, serviceFeeFloor) } GetLatestBalance = () => { @@ -173,7 +173,7 @@ export class LiquidityProvider { const fees = f ? f : this.GetFees() const serviceFeeRate = fees.serviceFeeBps / 10000 const serviceFee = Math.ceil(serviceFeeRate * amount) - return Math.max(serviceFee, fees.outboundFeeFloor) + return Math.max(serviceFee, fees.serviceFeeFloor) } CanProviderPay = async (amount: number, localServiceFee: number): Promise => { @@ -215,13 +215,16 @@ export class LiquidityProvider { } - PayInvoice = async (invoice: string, decodedAmount: number, from: 'user' | 'system') => { + PayInvoice = async (invoice: string, decodedAmount: number, from: 'user' | 'system', feeLimit?: number) => { try { if (!this.IsReady()) { throw new Error("liquidity provider is not ready yet, disabled or unreachable") } const fees = this.GetFees() const providerServiceFee = this.GetServiceFee(decodedAmount, fees) + if (feeLimit && providerServiceFee > feeLimit) { + throw new Error("provider service fee is greater than the fee limit") + } this.pendingPayments[invoice] = decodedAmount + providerServiceFee const timeout = setTimeout(() => { if (!this.pendingPaymentsAck[invoice]) { diff --git a/src/services/main/paymentManager.ts b/src/services/main/paymentManager.ts index 5defcbb0..e902078c 100644 --- a/src/services/main/paymentManager.ts +++ b/src/services/main/paymentManager.ts @@ -173,7 +173,7 @@ export default class { getReceiveServiceFee = (action: Types.UserOperationType, amount: number, managedUser: boolean): number => { switch (action) { case Types.UserOperationType.INCOMING_TX: - return Math.ceil(this.settings.getSettings().serviceFeeSettings.incomingTxFee * amount) + return 0 case Types.UserOperationType.INCOMING_INVOICE: // Incoming invoice fees are always 0 (not configurable) return 0 @@ -197,18 +197,14 @@ export default class { getSendServiceFee = (action: Types.UserOperationType, amount: number, managedUser: boolean): number => { switch (action) { case Types.UserOperationType.OUTGOING_TX: - // Internal address payment, treat like user-to-user - if (managedUser) { - return Math.ceil(this.settings.getSettings().serviceFeeSettings.userToUserFee * amount) - } - return Math.ceil(this.settings.getSettings().serviceFeeSettings.rootToUserFee * amount) + throw new Error("OUTGOING_TX is not a valid send service fee action") case Types.UserOperationType.OUTGOING_INVOICE: const fee = this.getInvoicePaymentServiceFee(amount, managedUser) // Only managed users pay the service fee floor if (!managedUser) { return 0 } - return Math.max(fee, this.settings.getSettings().lndSettings.serviceFeeFloor) + return Math.max(fee, this.settings.getSettings().serviceFeeSettings.serviceFeeFloor) case Types.UserOperationType.OUTGOING_USER_TO_USER: if (managedUser) { return Math.ceil(this.settings.getSettings().serviceFeeSettings.userToUserFee * amount) @@ -272,18 +268,17 @@ export default class { } GetFees = (): Types.CumulativeFees => { - const { serviceFeeBps } = this.settings.getSettings().serviceFeeSettings - const { serviceFeeFloor } = this.settings.getSettings().lndSettings - return { outboundFeeFloor: serviceFeeFloor, serviceFeeBps: serviceFeeBps } + const { serviceFeeBps, serviceFeeFloor } = this.settings.getSettings().serviceFeeSettings + return { serviceFeeFloor, serviceFeeBps } } GetMaxPayableInvoice(balance: number): Types.CumulativeFees & { max: number } { - const { outboundFeeFloor, serviceFeeBps } = this.GetFees() + const { serviceFeeFloor, serviceFeeBps } = this.GetFees() const div = 1 + (serviceFeeBps / 10000) const maxWithoutFixed = Math.floor(balance / div) const fee = balance - maxWithoutFixed - const max = balance - Math.max(fee, outboundFeeFloor) - return { max, outboundFeeFloor, serviceFeeBps } + const max = balance - Math.max(fee, serviceFeeFloor) + return { max, serviceFeeFloor, serviceFeeBps } } async DecodeInvoice(req: Types.DecodeInvoiceRequest): Promise { const decoded = await this.lnd.DecodeInvoice(req.invoice) @@ -299,10 +294,10 @@ export default class { throw new Error("user is banned, cannot send payment") } if (req.expected_fees) { - const { outboundFeeFloor, serviceFeeBps } = req.expected_fees - const serviceFixed = this.settings.getSettings().lndSettings.serviceFeeFloor + const { serviceFeeFloor, serviceFeeBps } = req.expected_fees + const serviceFixed = this.settings.getSettings().serviceFeeSettings.serviceFeeFloor const serviceBps = this.settings.getSettings().serviceFeeSettings.serviceFeeBps - if (serviceFixed !== outboundFeeFloor || serviceBps !== serviceFeeBps) { + if (serviceFixed !== serviceFeeFloor || serviceBps !== serviceFeeBps) { throw new Error("fees do not match the expected fees") } } @@ -522,21 +517,11 @@ export default class { this.swaps.reverseSwaps.SubscribeToTransactionSwap(data, result => { swapResult = result }) - // Validate that the invoice amount matches what was quoted - const decoded = await this.lnd.DecodeInvoice(txSwap.invoice) - if (decoded.numSatoshis !== txSwap.invoice_amount) { - throw new Error("swap invoice amount does not match quote") - } - const fees = this.GetFees() let payment: Types.PayInvoiceResponse try { payment = await this.PayInvoice(ctx.user_id, { amount: 0, - invoice: txSwap.invoice, - expected_fees: { - outboundFeeFloor: fees.outboundFeeFloor, - serviceFeeBps: fees.serviceFeeBps - } + invoice: txSwap.invoice }, app, { swapOperationId: req.swap_operation_id }) if (!swapResult.ok) { this.log("invoice payment successful, but swap failed") @@ -572,7 +557,7 @@ export default class { const { blockHeight } = await this.lnd.GetInfo() const app = await this.storage.applicationStorage.GetApplication(ctx.app_id) const isManagedUser = ctx.user_id !== app.owner.user_id - const serviceFee = this.getSendServiceFee(Types.UserOperationType.OUTGOING_TX, req.amoutSats, isManagedUser) + const serviceFee = this.getSendServiceFee(Types.UserOperationType.OUTGOING_USER_TO_USER, req.amoutSats, isManagedUser) const txId = crypto.randomBytes(32).toString("hex") const addressData = `${req.address}:${txId}` diff --git a/src/services/main/settings.ts b/src/services/main/settings.ts index c1f09c5b..fbd03d4d 100644 --- a/src/services/main/settings.ts +++ b/src/services/main/settings.ts @@ -3,38 +3,22 @@ import os from 'os' import path from 'path' export type ServiceFeeSettings = { - incomingTxFee: number serviceFee: number serviceFeeBps: number + serviceFeeFloor: number userToUserFee: number rootToUserFee: number } export const LoadServiceFeeSettingsFromEnv = (dbEnv: Record, addToDb?: EnvCacher): ServiceFeeSettings => { - // Support both old and new env var names for backward compatibility (new name takes precedence) - // Check if new name exists first (in process.env or dbEnv) - const newExists = process.env["SERVICE_FEE_BPS"] !== undefined || dbEnv["SERVICE_FEE_BPS"] !== undefined - let serviceFeeBps: number - if (newExists) { - // New name exists, use it - serviceFeeBps = chooseEnvInt("SERVICE_FEE_BPS", dbEnv, 60, addToDb) - } else { - // New name doesn't exist, check old name for backward compatibility - const oldExists = process.env["OUTGOING_INVOICE_FEE_USER_BPS"] !== undefined || dbEnv["OUTGOING_INVOICE_FEE_USER_BPS"] !== undefined - if (oldExists) { - // Old name exists, use it and migrate to new name in DB - const oldValue = chooseEnvInt("OUTGOING_INVOICE_FEE_USER_BPS", dbEnv, 60) // Don't add old name to DB - serviceFeeBps = oldValue - if (addToDb) addToDb("SERVICE_FEE_BPS", oldValue.toString()) // Migrate to new name - } else { - // Neither exists, use default with new name - serviceFeeBps = chooseEnvInt("SERVICE_FEE_BPS", dbEnv, 60, addToDb) - } - } + const oldServiceFeeBps = chooseEnvInt("OUTGOING_INVOICE_FEE_USER_BPS", dbEnv, 60, addToDb) + const serviceFeeBps = chooseEnvInt("SERVICE_FEE_BPS", dbEnv, oldServiceFeeBps, addToDb) + const oldRoutingFeeFloor = chooseEnvInt('OUTBOUND_MAX_FEE_EXTRA_SATS', dbEnv, 10, addToDb) + const serviceFeeFloor = chooseEnvInt("SERVICE_FEE_FLOOR_SATS", dbEnv, oldRoutingFeeFloor, addToDb) return { - incomingTxFee: 0, // Not configurable, always 0 - serviceFeeBps: serviceFeeBps, + serviceFeeBps, serviceFee: serviceFeeBps / 10000, + serviceFeeFloor, userToUserFee: chooseEnvInt("TX_FEE_INTERNAL_USER_BPS", dbEnv, 0, addToDb) / 10000, rootToUserFee: chooseEnvInt("TX_FEE_INTERNAL_ROOT_BPS", dbEnv, 0, addToDb) / 10000, } @@ -91,7 +75,6 @@ const networks = ['mainnet', 'testnet', 'regtest'] as const export type BTCNetwork = (typeof networks)[number] export type LndSettings = { lndLogDir: string - serviceFeeFloor: number routingFeeLimitBps: number routingFeeFloor: number mockLnd: boolean @@ -125,42 +108,11 @@ export const LoadLndNodeSettingsFromEnv = (dbEnv: Record, addToDb?: EnvCacher): LndSettings => { const network = chooseEnv('BTC_NETWORK', dbEnv, 'mainnet', addToDb) as BTCNetwork - - // Routing fee floor: new name takes precedence, fall back to old name for backward compatibility - const routingFeeFloorNewExists = process.env['ROUTING_FEE_FLOOR_SATS'] !== undefined || dbEnv['ROUTING_FEE_FLOOR_SATS'] !== undefined - let routingFeeFloor: number - if (routingFeeFloorNewExists) { - routingFeeFloor = chooseEnvInt('ROUTING_FEE_FLOOR_SATS', dbEnv, 5, addToDb) - } else { - const routingFeeFloorOldExists = process.env['OUTBOUND_MAX_FEE_EXTRA_SATS'] !== undefined || dbEnv['OUTBOUND_MAX_FEE_EXTRA_SATS'] !== undefined - if (routingFeeFloorOldExists) { - const oldValue = chooseEnvInt('OUTBOUND_MAX_FEE_EXTRA_SATS', dbEnv, 5) // Don't add old name to DB - routingFeeFloor = oldValue - if (addToDb) addToDb('ROUTING_FEE_FLOOR_SATS', oldValue.toString()) // Migrate to new name - } else { - routingFeeFloor = chooseEnvInt('ROUTING_FEE_FLOOR_SATS', dbEnv, 5, addToDb) - } - } - - // Service fee floor: new name takes precedence, fall back to old name for backward compatibility - const serviceFeeFloorNewExists = process.env['SERVICE_FEE_FLOOR_SATS'] !== undefined || dbEnv['SERVICE_FEE_FLOOR_SATS'] !== undefined - let serviceFeeFloor: number - if (serviceFeeFloorNewExists) { - serviceFeeFloor = chooseEnvInt('SERVICE_FEE_FLOOR_SATS', dbEnv, 10, addToDb) - } else { - const serviceFeeFloorOldExists = process.env['OUTBOUND_MAX_FEE_EXTRA_SATS'] !== undefined || dbEnv['OUTBOUND_MAX_FEE_EXTRA_SATS'] !== undefined - if (serviceFeeFloorOldExists) { - const oldValue = chooseEnvInt('OUTBOUND_MAX_FEE_EXTRA_SATS', dbEnv, 10) // Don't add old name to DB - serviceFeeFloor = oldValue - if (addToDb) addToDb('SERVICE_FEE_FLOOR_SATS', oldValue.toString()) // Migrate to new name - } else { - serviceFeeFloor = chooseEnvInt('SERVICE_FEE_FLOOR_SATS', dbEnv, 10, addToDb) - } - } + const oldRoutingFeeFloor = chooseEnvInt('OUTBOUND_MAX_FEE_EXTRA_SATS', dbEnv, 5, addToDb) + const routingFeeFloor = chooseEnvInt('ROUTING_FEE_FLOOR_SATS', dbEnv, oldRoutingFeeFloor, addToDb) const routingFeeLimitBps = chooseEnvInt('ROUTING_FEE_LIMIT_BPS', dbEnv, 50, addToDb) return { lndLogDir: chooseEnv('LND_LOG_DIR', dbEnv, resolveHome("/.lnd/logs/bitcoin/mainnet/lnd.log"), addToDb), - serviceFeeFloor, routingFeeLimitBps, routingFeeFloor, mockLnd: false, diff --git a/src/services/main/settingsManager.ts b/src/services/main/settingsManager.ts index e1f125bc..f32fba93 100644 --- a/src/services/main/settingsManager.ts +++ b/src/services/main/settingsManager.ts @@ -59,7 +59,7 @@ export default class SettingsManager { const { serviceFeeSettings, lndSettings } = settings const serviceFeeBps = serviceFeeSettings.serviceFeeBps const routingFeeLimitBps = lndSettings.routingFeeLimitBps - const serviceFeeFloor = lndSettings.serviceFeeFloor + const serviceFeeFloor = serviceFeeSettings.serviceFeeFloor const routingFeeFloor = lndSettings.routingFeeFloor if (routingFeeLimitBps > serviceFeeBps) {