feat(bridge): Bridge banking in settings#653
Conversation
Introduce a single "Bank accounts" settings surface that unifies the Bridge virtual (receive) account and the user's withdrawal banks behind one rail-agnostic view model, replacing the standalone routing-number row. - add normalized BankAccountVM + useBankAccounts() hook merging bridgeVirtualAccount (receive), bridgeExternalAccounts (USD withdraw) and me.bankAccounts (local withdraw), with per-currency default resolution - add BankAccountsScreen: Receive card (reveal/copy, KYC-gated) + currency grouped Withdraw list with default selection, status pills and add flow - interim client-side default store (AsyncStorage) until backend adds isDefault + bridgeSetDefaultExternalAccount (kept isolated from the persistentState migration chain for a one-file swap later) - wire BankAccounts route + settings row; hub handles KYC state internally Scaffolding only: set-default persists client-side; remove is gated on a future bridgeDeleteExternalAccount mutation. tsc + eslint clean.
- Add Cancel button in the Add Bank Account header (navigation.goBack) - Add Contact Support button at the bottom of the Bank accounts hub that opens WhatsApp support (wa.flashapp.me) via openWhatsAppUrl
KYC-not-approved state now shows an Upgrade your account button that navigates to the AccountType upgrade flow — same destination as the QuickStart upgrade card on the Home screen.
Conflict in BridgeAddExternalAccount.tsx: #652 switched the post-link navigation to navigation.replace (back must not return to the form) and added an already-linked path (BRIDGE_API_ERROR treated as success); this branch added the returnTo=BankAccounts entry point and i18n. Resolved by extracting a single navigateAfterLink helper used by both the success and already-linked alerts: returnTo=BankAccounts navigates back to the existing hub instance (drops the form from the stack), otherwise replace to CashoutDetails per #652. The already-linked path now also respects returnTo, so adding a duplicate bank from Settings returns to Settings instead of dropping into the cash-out flow. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- extract the #652 already-linked alert strings to i18n (BridgeAddExternalAccount.alreadyLinkedTitle/Message) - toast confirmation when a default withdrawal account is set in the hub (no feedback before beyond the radio moving) - CashoutWithdrawTo: reload the stored default on screen focus instead of mount only, so a default changed in Settings is reflected when returning to an already-mounted cash-out screen - promote serverDefault to a proper optional field on BankAccountVM instead of smuggling it through type casts Verified: tsc:check clean, eslint clean on touched files, jest 36 suites / 159 tests green on the merged tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Pushed two commits to unblock this PR:
Verification on the merged tree (this repo's PR CI runs no typecheck or tests): Deliberately NOT done here: wiring the backend #423 API ( 🤖 Generated with Claude Code |
The translation-drift check (added in #604) requires every locale to contain all en.json keys. Backfill the 72 new Bank accounts / add-bank keys into all 23 locale files with English placeholder values — same interim convention as existing untranslated keys (e.g. Cashout section). Proper translations can follow the ENG-242 machine-translate process. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…switch The Bank accounts hub (#653) landed after the ENG-465 remote-config gate was folded into feat/fygaro and missed it: the settings row rendered for everyone and the hub fired Bridge KYC/virtual-account/external-account queries with the kill switch off — violating the gate's contract (hide Bridge entry points, skip Bridge queries) and dead-ending users at an Upgrade CTA whose Bridge path is hidden. - hide BankAccountsSetting when !bridgeTopupEnabled (same contract as AccountType / TopupCashout) - skip useBridgeKycStatusQuery in useBankAccounts when the flag is off; the virtual/external account queries already skip on !kycApproved and are now transitively gated - split the AsyncStorage default-account helpers into default-account-store.ts: CashoutWithdrawTo/CashoutDetails only need the stored id, and importing the hook module would have pulled feature-flags-context (and Firebase Remote Config) into their module graph — breaking home.spec and coupling cash-out to settings Verified: tsc:check clean, eslint clean, jest 36 suites / 159 tests green (home.spec included). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
Establishes a single Bank accounts hub in Settings that unifies everything
bank-transfer related: money-in (your Flash USD receiving account) and
money-out (withdrawal banks). The user sees one place to receive by bank
transfer, add withdrawal accounts, and choose a default withdrawal account.
This supersedes and removes the original standalone "Account and routing number"
screen/row. The receiving account now lives inside the hub as the Receive card.
What's in this PR
1. Receive money
same
AccountTypeupgrade flow as Home screen QuickStart2. Withdraw to bank accounts
BankAccountVM+useBankAccounts()normalize:bridgeVirtualAccount-> single receive accountbridgeExternalAccounts(USD) -> Bridge withdrawal accountsme.bankAccounts(local) -> local withdrawal accountsWithdraw toconfirmation selectorto the hub instead of dropping the user into the cash-out flow
3. PR cleanup / review pass
Interim vs. backend dependency
Bridge external accounts have no
isDefaultand no set-default mutation yet, sothe chosen default is persisted client-side in AsyncStorage for now. The storage
helpers are isolated in
use-bank-accounts.tsso the frontend can swap to serverdefaults in one place once the backend PR lands.
Backend PR for full best-case: lnflash/flash#423
BridgeExternalAccount.isDefault: Boolean!bridgeSetDefaultExternalAccount(input:{ externalAccountId }): ...bridgeDeleteExternalAccount(input:{ externalAccountId }): ...bankAccountSetDefault/bankAccountCreatefor local-rail parityUntil the backend mutations land, remove is still shown as "coming soon" and defaults
are client-side.
File-by-file
app/screens/settings-screen/bank-accounts/types.tsBankAccountVM/WithdrawGroupapp/screens/settings-screen/bank-accounts/use-bank-accounts.tsapp/screens/settings-screen/bank-accounts/bank-accounts-screen.tsxapp/screens/settings-screen/settings/bank-accounts.tsxapp/screens/settings-screen/settings-screen.tsxapp/components/topup-cashout-flow/CashoutWithdrawTo.tsxapp/screens/topup-cashout-flow/CashoutDetails.tsxapp/screens/topup-cashout-flow/BridgeAddExternalAccount.tsxapp/navigation/*BankAccounts, remove orphanedBridgeAccountRoutingapp/i18n/*Verification
yarn tsc:check✅yarn check:translations✅yarn check:codegen✅yarn graphql-check✅git diff --check✅yarn test__tests__/screens/send-confirmation.spec.tsx