Skip to content

fix: avoid msat truncation when paying invoices with built-in amounts#879

Open
ben-kaufman wants to merge 2 commits intomasterfrom
fix/msat-invoice-precision
Open

fix: avoid msat truncation when paying invoices with built-in amounts#879
ben-kaufman wants to merge 2 commits intomasterfrom
fix/msat-invoice-precision

Conversation

@ben-kaufman
Copy link
Copy Markdown
Contributor

Summary

  • Bump bitkit-core from 0.1.38 to v0.1.56 which rounds up sub-satoshi invoice amounts (ceiling division instead of floor)
  • Stop overriding the amount for invoices that already have one — pass null so LDK uses the invoice's native msat precision instead of our truncated sats value converted back to msat
  • Only pass the amount for zero-amount invoices where the user specifies it

Test plan

  • E2E: pay invoices created with lnd.addInvoice({ valueMsat }) using amounts 222538, 222222, 500500 msat
  • Verify zero-amount invoice flow still works
  • Verify LNURL pay flow still works
  • Verify quickpay flow still works

Depends on synonymdev/bitkit-core#85
Closes #877

🤖 Generated with Claude Code

Bump bitkit-core to v0.1.56 which rounds up sub-satoshi invoice amounts.

Additionally, stop overriding the amount for invoices that already have
one. Pass null so LDK uses the invoice's native msat precision instead
of our truncated sats value converted back to msat. Only pass the amount
for zero-amount invoices where the user specifies it.

Closes #877
// When the invoice has a built-in amount, pass null so LDK uses the
// invoice's native msat precision (avoids truncation to whole sats).
val paymentAmount = if (decodedInvoice.amountSatoshis > 0uL) null else amount
// For display/UI purposes, use the invoice amount (in sats) when available.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CLAUDE.md compliance: Comments should not be added inside private functions.

From CLAUDE.md: "NEVER add code comments to private functions, classes, etc"

These two new comments are inside private suspend fun proceedWithPayment():

// When the invoice has a built-in amount, pass null so LDK uses the
// invoice's native msat precision (avoids truncation to whole sats).
val paymentAmount = if (decodedInvoice.amountSatoshis > 0uL) null else amount
// For display/UI purposes, use the invoice amount (in sats) when available.
val displayAmountSats = decodedInvoice.amountSatoshis.takeIf { it > 0uL } ?: amount ?: 0uL

Consider removing the inline comments — the logic is self-evident from the variable names (paymentAmount vs displayAmountSats).

Suggested change
// For display/UI purposes, use the invoice amount (in sats) when available.
val paymentAmount = if (decodedInvoice.amountSatoshis > 0uL) null else amount
val displayAmountSats = decodedInvoice.amountSatoshis.takeIf { it > 0uL } ?: amount ?: 0uL

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@claude
Copy link
Copy Markdown

claude bot commented Apr 1, 2026

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@ovitrif ovitrif added this to the 2.2.0 milestone Apr 1, 2026
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.

[Bug]: msat-precision invoices fail to send (regular BOLT11 + LNURL pay/withdraw)

2 participants