Summary
The app's card features now run on the KeySecure card account (/card-account). No app code calls the legacy /cards/*, /reap/* or /chats/external-transfer routes. FE only; no backend changes.
-
API layer: hand-written
fe/src/api/card-account/: summary, cards, card, entries, consumptions, deposit, issue card, freeze/unfreeze, and error classification. While a card is APPLYING (less than 2 minutes old), the app polls it. -
Card tab (approved cardholder):
- One card-account balance plus the pending amount.
- Card stack drawn from
last4/status/designSlug. - Issue card, guarded against double taps.
- Purchases (consumptions) and Activity (entries) history.
- Card detail: Add fund, Freeze/Unfreeze, and "Card details" disabled with a "Coming soon" hint. PAN/CVV reveal is SP4b-2, which needs the KeySecure iframe SDK in a WebView.
-
Funding:
- Transfer posts
POST /card-account/depositwith the amount normalised to 2 decimals, and has no card picker. - The Add-fund chooser offers Transfer only.
- Transfer posts
-
Convert (minimal):
-
cardIdis dropped from the quote, and the Reap card-balance call is removed. - Another branch reworks Convert into crypto
↔ fiat wallet. The leftovers belong to that rework: thecardReceiveprop, theconvert.noCardAdded,selectCardandcardSendkeys, andisCardFunding.
-
-
Removed:
- The chat money flows (send money, split equally, request money) and the card-funded Send path. Send is now crypto only.
- The Reap-only screens: add-card, billing/shipping address, card settings, PIN, limit, add-current-card.
-
api/cards, the card stores, orphaned card components, hooks and translation keys.
Testing
-
pnpm type-checkis clean.pnpm jestpasses 111 suites and 1018 tests. eslint on the changed files shows 0 errors. - The grep gate for legacy routes and hooks prints nothing.
- Simulator against a local BE, 6/6 pass:
- Card tab and the Issue card error toast.
- History tabs.
- A Transfer deposit of 5 USD to the card account.
- Add fund shows Transfer only.
- Chat has no money actions.
- Card detail freeze/unfreeze and details disabled.
- Card issuance in the sandbox is still blocked:
/card/applyreturns 3008 until the reserve is funded.
Notes / follow-ups
-
Backend:
POST /card-account/cardsreturns 400 with nocodewhen the wallet cannot cover the issue fee. Swagger documents 422INSUFFICIENT_BALANCE. The app handles it, but the backend should be fixed. -
Issue fee: not shown in the app; the only fee route is the legacy
/cards/issue-fee. -
Local env: a local BE needs
KEYSECURE_CARD_PACKAGE_NO, otherwise Issue card returns 503KEYSECURE_NOT_CONFIGURED. - Polling: an APPLYING card stops polling after 2 minutes. The backend sweeper only resolves older cards (every 5 minutes), so a 202 card can show "Processing" until the screen is reopened.
-
Cardholder status: a
CARDHOLDER_NOT_APPROVEDerror while loading the balance does not refresh the cardholder status (the Issue path does). -
Dead code:
-
send/confirm.tsxkeeps a crypto chat branch and group-member plumbing that are now unreachable. -
detail-card/card-action-button.tsxandutils/format-card-number.tswere already unused before this branch.
-
-
UI polish:
- The card face shows a Mastercard logo for a Visa BIN.
- The Transfer fee row reads "0 PRV".
- The confirm sheet shows the raw typed amount ("5.").