Skip to content

feat(cashout): show the real settlement amount on the cashout entry screen - #683

Merged
islandbitcoin merged 3 commits into
mainfrom
feat/cashout-rate-preview
Aug 8, 2026
Merged

feat(cashout): show the real settlement amount on the cashout entry screen#683
islandbitcoin merged 3 commits into
mainfrom
feat/cashout-rate-preview

Conversation

@islandbitcoin

Copy link
Copy Markdown
Contributor

Why

Users anchor on the entry screen's JMD conversion, which uses the realtimePrice display rate (mid-market) — but JMD cashouts settle at the NCB rate minus the 2% fee, so bank deposits arrive ~5-7% below the number people remember. Support is fielding "I received less than the app showed" because of it.

What

On the cashout entry screen (bank cashouts only; Bridge withdrawals unaffected), once an amount is entered:

You'll receive about J$14,964.60 in your bank account
Settlement rate: US$1 = J$152.70
Final amount is confirmed on the next screen

  • Fed by the new cashoutRate query — companion backend PR: feat(cashout): expose the JMD settlement rate pre-quote (cashoutRate query) flash#471 (must deploy first; until then the preview simply doesn't render).
  • estimateJmdReceiveCents mirrors the backend quote math exactly (fee bps off USD first, integer conversion at JMD-cents-per-USD) — unit-tested including flooring parity and NaN guards. The authoritative number is still the offer's receiveJmd on the confirmation screen; the preview just makes the anchor honest.
  • Fails quiet: rate query error → no preview, flow unchanged.

Tests / checks

  • __tests__/screens/cashout-estimate.spec.ts (4 tests, incl. backend-math parity case).
  • tsc:check, check:translations, check:codegen, eslint on changed files: all green locally.

🤖 Generated with Claude Code

https://claude.ai/code/session_017iEVSCGxZMRjwsmSsd6ZNU

…creen

Users anchored on the AmountInput's JMD conversion, which uses the
realtimePrice display rate (mid-market) — but JMD cashouts settle at the
NCB rate minus the 2% fee, so bank deposits came in ~5-7% below the number
people remembered. The entry screen now shows what will actually arrive.

- New CashoutRate query (backend companion PR) fetched on the entry screen
  for bank cashouts; skipped for Bridge withdrawals.
- "You'll receive about J$X" + "Settlement rate: US$1 = J$Y" + a note that
  the final amount is confirmed on the next screen — rendered once an
  amount is entered.
- estimateJmdReceiveCents mirrors the backend quote math (fee in bps off
  the USD amount first, then integer conversion at JMD-cents-per-USD);
  unit-tested including flooring parity and NaN guards.
- Fails quiet: if the rate query errors, the preview is simply absent and
  the confirmation screen still shows the authoritative offer numbers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017iEVSCGxZMRjwsmSsd6ZNU
@islandbitcoin
islandbitcoin force-pushed the feat/cashout-rate-preview branch from 82bfb16 to eff6087 Compare August 8, 2026 05:37
Dread and others added 2 commits August 7, 2026 23:17
Review findings: a user whose only cashout account is USD gets a USD payout
with no conversion — the preview showed a JMD estimate anyway. The payout
account selection is now a shared pure helper (pickDefaultBankAccount /
selectsJmdPayout) used by both onNext and the preview condition so they can
never disagree; +6 tests including the stored-default equivalence property
the preview relies on.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017iEVSCGxZMRjwsmSsd6ZNU
@islandbitcoin
islandbitcoin merged commit 364737e into main Aug 8, 2026
10 checks passed
islandbitcoin added a commit that referenced this pull request Aug 11, 2026
…d top-ups (#688)

* feat(topup): show net "you'll receive" and enforce $10 minimum on card top-ups

Fast-follow to the merged backend fee feature (lnflash/flash#473), which exposes
Globals.fygaroTopup with the processor/Flash fee params and the top-up minimum.

- Add `fygaroTopup { minimumAmount processorFeePercent processorFeeFixed
  flashFeePercent flashFeeFixed }` to the `transferFlags` globals query that the
  topup/cashout entry screen already fetches, so the data is cache-warm on
  arrival. The field + the `FygaroTopupInfo` type were hand-added to
  public-schema.graphql (no backend access to re-introspect) and codegen was
  regenerated.
- TopupDetails now shows "You'll receive $X.XX" (net after fees) live as the
  user types, mirroring the cashout settlement-amount preview (#683). Card-only;
  the line is hidden when `fygaroTopup` is null so a wrong number is never shown.
- Raise/enforce the card minimum to `fygaroTopup.minimumAmount` (fallback $10
  when null); the invalid-amount alert now states the real minimum.
- New i18n keys added to en + all 23 locale files. Tests cover the $10 floor,
  the $5 rejection (incl. null fallback), and the $9.01 net for a $10 gross.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NcEjF6SS3Ci5D4CzZqdPjb

* fix(topup): mirror backend cent-rounding in net estimate, gate preview on minimum

Address code-review findings on the "you'll receive" top-up disclosure:

- estimateTopupNet now computes in integer cents, rounding each fee
  component (processor %+fixed, flash %+fixed) to the nearest cent before
  subtracting, exactly as the backend does (flash#473). The prior
  float-dollar math with a single final round diverged by a cent for a
  large fraction of non-round amounts (e.g. $10.25 showed $9.25 while the
  backend credits $9.24), over-promising the headline number.
- The net preview is now gated on the enforced minimum, so a below-floor
  amount (e.g. $5) no longer shows a concrete receive figure that
  Continue will immediately refuse.
- Tests: added a non-round unit case (10.25 → $9.24) and a preview case
  (10.25 → $9.24, not $9.25) that fail under the old float math, plus a
  below-minimum hide case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QwZjNcKfkMhrBE33HcUVN

---------

Co-authored-by: Dread <dread@example.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant