Skip to content

Conversation

@jvsena42
Copy link
Member

@jvsena42 jvsena42 commented Jan 16, 2026

Fixes #354

Description

This PR implement the balance validation of #354

Preview

zero-balance-scan-zero-amount-invoice.webm
zero-balance-sance-ln-amount-invoice.webm
invalid.webm
network-mismatch.webm
insufficient-savingsbalance-uniffied.webm

QA Notes

@jvsena42 jvsena42 self-assigned this Jan 16, 2026
@jvsena42 jvsena42 marked this pull request as ready for review January 16, 2026 16:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements balance validation for Bitcoin and Lightning invoice payments to address issue #354. The changes ensure users receive appropriate error messages when attempting to pay invoices with insufficient balance, invalid addresses, or network mismatches.

Changes:

  • Added network validation logic to detect and reject addresses from incompatible Bitcoin networks (mainnet/testnet/regtest)
  • Implemented balance validation for both on-chain and Lightning invoices with specific error messages showing the shortfall amount
  • Added debounced address validation with immediate user feedback via toast messages

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
NetworkValidationHelper.kt New utility class for detecting Bitcoin network from address prefixes and validating network compatibility
NetworkValidationHelperTest.kt Comprehensive unit tests covering address network detection and mismatch validation scenarios
AppViewModel.kt Integrated address validation with debouncing, balance checks, and user feedback for both input and scan flows
strings.xml Added new error message string for insufficient spending balance on Lightning invoices

jvsena42 and others added 2 commits January 16, 2026 13:39
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jvsena42
Copy link
Member Author

@piotr-iohk needs an update from E2E

@claude
Copy link

claude bot commented Jan 16, 2026

Code Review

Found 2 ULong underflow bugs in AppViewModel.kt that need to be fixed.

Bug 1: Line 735 in validateLightningInvoice()

The raw ULong subtraction invoice.amountSatoshis - maxSendLightning can underflow when canSend() returns false but maxSendLightning is greater than invoice.amountSatoshis.

Scenario:

  • User has an invoice for 50,000 sats
  • Cached balance shows maxSendLightningSats = 100,000 (stale data)
  • canSend(50000) returns false because channels are temporarily unavailable (not because of insufficient balance)
  • Calculation: 50,000 - 100,000 = ULong underflow = 18,446,744,073,709,501,616

This would show the user an error claiming they need billions of satoshis more to pay a small invoice.

CLAUDE.md violation: "ALWAYS wrap ULong numbers with USat in arithmetic operations, to guard against overflows"

See:

@JvmInline
value class USat(val value: ULong) : Comparable<USat> {
override fun compareTo(other: USat): Int = value.compareTo(other.value)
/** Saturating subtraction: returns 0 if result would be negative. */

val maxSendLightning = walletRepo.balanceState.value.maxSendLightningSats
if (maxSendLightning == 0uL || !lightningRepo.canSend(invoice.amountSatoshis)) {
val shortfall = invoice.amountSatoshis - maxSendLightning
showAddressValidationError(
titleRes = R.string.other__pay_insufficient_spending,

Fix: Use invoice.amountSatoshis.safe() - maxSendLightning.safe() or add an explicit guard.


Bug 2: Line 1125 in onScanLightning()

Same issue - raw ULong subtraction invoice.amountSatoshis - maxSendLightning can underflow.

if (!lightningRepo.canSend(invoice.amountSatoshis)) {
val maxSendLightning = walletRepo.balanceState.value.maxSendLightningSats
val shortfall = invoice.amountSatoshis - maxSendLightning
toast(
type = Toast.ToastType.ERROR,

Fix: Use invoice.amountSatoshis.safe() - maxSendLightning.safe() or add an explicit guard.


Note: Both issues occur because canSend() can return false for reasons other than insufficient balance (e.g., channels unavailable), while the cached maxSendLightningSats might still show a higher value than the invoice amount.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Address/balance validation on 'Send Bitcoin'

3 participants