fix(send): surface real BTC fee errors and validate LNURL receive limits - #680
Merged
Conversation
Sending from the Breez Spark BTC wallet to a Flash address (or any LNURL destination) failed with a misleading 'make sure you have enough balance' message whenever anything went wrong in fee estimation. The most common real cause is the receiver's advertised LUD-06 maxSendable cap (ENG-540: IBEX advertises 150k sats instead of 150M), which the SDK rejects client-side before requesting an invoice. - fetchBreezFee now returns a typed BreezFeeError instead of swallowing every failure into one hardcoded balance string; real errors are recorded to Crashlytics - amounts are validated against the receiver's minSendable/maxSendable before prepareLnurlPay, so the UI can show the actual limit - send-details screen resolves the receiver's limits per destination and DetailAmountNote validates as the user types for BTC-wallet sends (previously only USD/USDT lnurl sends were validated) - ConfirmationWalletFee: fix dead 'fee === "null"' string comparison, map typed errors to accurate messages - useSwap: stop reporting every fee error as 'amount exceeds balance' - new i18n keys in en + all 23 locales (English placeholder convention) - unit tests for limit conversion/validation, error classification, and message mapping Linear: ENG-540 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7A41jET8aH7u5WXP7EZoS
3 tasks
- extract shared useFormatSats hook, replacing four hand-rolled copies of the sats formatting closure (details screen, DetailAmountNote, ConfirmationWalletFee, useSwap) - resolve the receiver's LNURL payRequest once on the details screen and pass it through to fetchBreezFee, removing the duplicate network round-trip to the receiver's LNURL service on every BTC send (fetchLnurlLimits -> fetchLnurlPayRequest) - add component tests for DetailAmountNote's BTC receiver-limit validation branch (over-max regression case, below-min, within-bounds, unknown limits, lnurl payment type) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7A41jET8aH7u5WXP7EZoS
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7A41jET8aH7u5WXP7EZoS
The added knownPayRequest parameter pushed the signature to five positional params, tripping max-params on the changed-lines lint gate. An options object is the better API anyway — no optional-middle-arg call sites. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G7A41jET8aH7u5WXP7EZoS
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
Sending from the Breez Spark BTC wallet to a Flash address (or any LNURL destination) failed with a misleading "make sure you have enough balance" message whenever fee estimation failed for any reason. The most common real cause is the receiver's advertised LUD-06
maxSendablecap (ENG-540: IBEX advertises 150k sats instead of 150M), which LNURL-compliant clients reject client-side before ever requesting an invoice.fetchBreezFeereturns a typedBreezFeeError(amount-above-max/amount-below-min/insufficient-funds/network/sdk) instead of swallowing every failure into one hardcoded balance string; real errors are recorded to CrashlyticsminSendable/maxSendablebeforeprepareLnurlPay, so the UI shows the actual limit (e.g. "The most this recipient can receive per payment is $97.03 (150,000 sats)")DetailAmountNotevalidates as the user types for BTC-wallet sends (previously only USD/USDT lnurl sends were validated)ConfirmationWalletFee: fixed the deadfee === "null"string comparison and wired typed-error mappinguseSwap: BTC→USD swap fee errors no longer all report as "amount exceeds balance"en+ all 23 locales (English placeholder convention per feat(mobile): Plaid Link SDK cutover for Bridge external accounts [ENG-524] #668/feat(bank): fall back to manual entry when Plaid Link is blocked #678)Linear: ENG-540
Test plan
yarn tsc:checkcleanyarn test— 50 suites / 267 tests pass, incl. 2 new suites covering msat→sat limit conversion (with the exact 150k-cap regression case), bounds validation, SDK error classification, and message mappingnode utils/check-translation-drift.jsgreen;yarn update-translationsregenerated and stablemaxSendable🤖 Generated with Claude Code
https://claude.ai/code/session_01G7A41jET8aH7u5WXP7EZoS