Compare commits

...

1 commit

Author SHA1 Message Date
be3ac55f1d fix(wallet): stop double-deducting balance on outgoing payments
The wallet WebSocket handler assumed LNbits sends the PRE-payment balance
for outgoing payments and subtracted the amount again. LNbits actually
re-fetches the wallet AFTER the payment settles before emitting the
notification (core payments.py `_send_payment_notification_in_background`
→ "fetch balance again" → notifications.py `send_ws_payment_notification`
→ `wallet.balance`), so `wallet_balance` is already POST-payment for both
directions. The extra subtraction double-deducted: 100 sats, send 10 →
balance showed 80, then a refresh (which reads the authoritative
/api/v1/wallet balance) corrected it to 90.

Use `wallet_balance` as-is for all messages, matching the polling
fallback which already trusts the API balance directly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 00:04:02 +02:00

View file

@ -231,41 +231,21 @@ export class WalletWebSocketService extends BaseService {
this.handlePaymentNotification(data.payment)
}
// Handle wallet balance update
// Handle wallet balance update.
// `wallet_balance` is authoritative and already POST-payment for BOTH
// directions: LNbits re-fetches the wallet AFTER the payment settles
// before emitting the notification (core services/payments.py
// `_send_payment_notification_in_background` → "fetch balance again" →
// services/notifications.py `send_ws_payment_notification` →
// `wallet.balance`). Use it as-is. The previous code subtracted the
// outgoing amount on top, double-deducting (100 → send 10 → showed 80,
// refresh corrected to 90).
if (data.wallet_balance !== undefined) {
console.log('WalletWebSocketService: Processing balance update', {
newBalance: data.wallet_balance,
console.log('WalletWebSocketService: Updating balance to', data.wallet_balance, 'sats', {
hasPayment: !!data.payment,
paymentAmount: data.payment?.amount
})
let finalBalance = data.wallet_balance
// For outgoing payments, LNbits sends pre-payment balance, so we need to adjust
// For incoming payments, LNbits sends post-payment balance, so use as-is
if (data.payment && data.payment.amount < 0) {
// Outgoing payment - subtract the payment amount from the balance
const paymentSats = Math.abs(data.payment.amount) / 1000
finalBalance = data.wallet_balance - paymentSats
console.log('WalletWebSocketService: Adjusting balance for outgoing payment', {
originalBalance: data.wallet_balance,
paymentSats: paymentSats,
finalBalance: finalBalance
})
} else if (data.payment && data.payment.amount > 0) {
// Incoming payment - use balance as-is (already post-payment)
console.log('WalletWebSocketService: Using balance as-is for incoming payment', {
balance: data.wallet_balance
})
} else {
// No payment in message - use balance as-is
console.log('WalletWebSocketService: Using balance as-is (no payment)', {
balance: data.wallet_balance
})
}
console.log('WalletWebSocketService: Updating balance to', finalBalance, 'sats')
this.updateWalletBalance(finalBalance)
this.updateWalletBalance(data.wallet_balance)
}
} catch (error) {