fix(lnurlp): emit min/maxSendable in msats per LUD-06 - #39
Merged
Conversation
The well-known lnurlp handler re-emitted lnurl-pay's requestPayServiceParams values (details.min/max, denominated in SATS) directly as minSendable / maxSendable, which LUD-06 defines as MILLISATS. Every Flash lightning address therefore advertised a max-receive of 150,000 sats (~$97) instead of the 150M sats IBEX actually allows (raw maxSendable 150,000,000,000 msats), and a sub-1-sat minSendable of 1 msat. Spec-compliant wallets (Breez SDK in flash-mobile, Phoenix, Zeus, etc.) enforce these bounds client-side, so all payments above ~150k sats to any name@flashapp.me address were refused before an invoice was ever requested. Prefer the upstream service's raw msat values verbatim; fall back to sats * 1000 if rawData is unavailable. Verified against the live IBEX payRequest: raw msats 1,000 / 150,000,000,000 now pass through unchanged (150M sats max). Linear: ENG-540 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7A41jET8aH7u5WXP7EZoS
… byte-faithfully Review follow-ups on #39: - move the min/maxSendable resolution into a pure lib/lnurl.ts helper so it can be unit-tested once the repo grows a test runner, and reused by any future handler needing LUD-06 fields - prefer the upstream service's raw metadata string verbatim: wallets verify the invoice description hash against the exact bytes of this string, so a re-serialized parse (key order, whitespace) could invalidate otherwise-good invoices — same passthrough-fidelity class as the msat fix Live-verified against IBEX: emitted minSendable 1000 / maxSendable 150000000000 msats, metadata byte-identical to the raw service response, and the rawData-less fallback path produces the same msat values. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7A41jET8aH7u5WXP7EZoS
islandbitcoin
added a commit
to lnflash/charts
that referenced
this pull request
Aug 6, 2026
Picks up lnflash/flash-pay#39 — the lnurlp well-known handler was re-emitting lnurl-pay's sat-denominated values as the msat LUD-06 minSendable/maxSendable fields, advertising a 150k-sat (~$97) receive cap on every Flash lightning address instead of IBEX's actual 150M sats. Also passes metadata through byte-faithfully. Image digest sha256:62a48b94... = flash-pay 0.6.1, built from ec69592 (post-merge main). ENG-540. Claude-Session: https://claude.ai/code/session_01G7A41jET8aH7u5WXP7EZoS Co-authored-by: Dread <dread@example.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the root cause of ENG-540: every Flash lightning address advertised
maxSendable: 150000000msats (= 150k sats ≈ $97) andminSendable: 1msat.The
/.well-known/lnurlp/[username]handler resolves the user's underlying IBEX lnurl withrequestPayServiceParamsfrom thelnurl-paypackage — which returnsdetails.min/details.maxin satoshis — and re-emitted those numbers asminSendable/maxSendable, which LUD-06 defines in millisatoshis. A silent 1000× under-advertisement.IBEX's raw payRequest is already correct (
maxSendable: 150000000000msats = 150M sats,minSendable: 1000msats = 1 sat). Spec-compliant wallets (Breez SDK in flash-mobile, Phoenix, Zeus, Strike…) enforce the advertised bounds client-side, so every payment above ~150k sats to anyname@flashapp.meaddress was refused before an invoice was ever requested — including in-app BTC-wallet sends to Flash addresses (fixed UX-side in lnflash/flash-mobile#680).The fix passes the upstream service's raw msat values through verbatim, falling back to
sats * 1000ifrawDatais unavailable.Test plan
prettier --check,eslint,tsc --noEmitall clean (repo has no unit-test runner)1000/150000000000pass through unchangedcurl -s https://flashapp.me/.well-known/lnurlp/rewards | jq '.maxSendable, .minSendable'→ expect150000000000and1000, then a >$100 BTC-wallet send in the app and a >150k-sat send from an external wallet🤖 Generated with Claude Code
https://claude.ai/code/session_01G7A41jET8aH7u5WXP7EZoS