Overview
Fix Card creation pending feedback, Card 5-card limit badge and add-button disable consistency across app restarts, Add funds wallet reconnect state synchronization, and QR payment USD currency selection with end-to-end fiat transfer support.
Bug Links & Detailed Changes
1. Card Creation Pending Message
- Task Link: https://hola-tech.sg.larksuite.com/record/CmQgrVrWle0KcQck3p7l0Fd6g7b
- Problem: When user confirms the card issuance fee (-2 USD), there is no visual feedback or message while card creation is processing in background.
-
Fix: Show immediate info flash message
Creating your card...upon tapping confirmation inApprovedCardView. -
Affected files:
fe/src/components/card-account/approved-card-view.tsx,fe/src/translations/en.json.
2 & 3. Card 5-Card Limit Badge and Add Button Disabled State Consistency
- Task Links:
-
Problem: When user reaches the 5-card limit, killing and reopening the app resets the
limitReachedflag because it was only stored in a local React state variable set during an API error callback. -
Fix: Evaluate
limitReachedaslimitError || visible.length >= 5 || (summary.data?.cardCount ?? 0) >= 5. This ensures the+button is disabled with reduced opacity and the message"You've reached the limit of 5 cards."remains visible whenever 5 or more cards exist, persisting across app restarts and remounts. -
Affected files:
fe/src/components/card-account/approved-card-view.tsx,fe/src/components/card-account/approved-card-view.test.tsx.
4. Add Funds Wallet Connect Session Synchronization
- Task Link: https://hola-tech.sg.larksuite.com/record/UprcrVWenetYNTc0tWflvyaegqP
-
Problem: In Add funds (
/deposit-wallet-send), if MetaMask / AppKit has an active connection in AppKit'sConnectionsControllerwhile wagmi'suseAccount()is still in adisconnectedstate, the screen failed to show the connected wallet and kept prompting "Connect Wallet". -
Fix:
- Read account state from AppKit (
useAccountfrom@reown/appkit-react-native) as an authoritative fallback foraddressandisConnected. - Prevent auto-opening connect modal when an active AppKit session exists or while AppKit is restoring a session (
useAppKitState().isLoading). - Gate the Send action strictly on signer readiness (
signerReady = isConnected && !!address), rendering an explicit restoring state when AppKit is active but wagmi is still initializing, preventing orphan PENDING deposit creation. - Consistently display connected wallet address and Disconnect control in AppKit-only states via
useAppKit().disconnect().
- Read account state from AppKit (
-
Affected files:
fe/src/components/deposit/deposit-wallet-send-form.tsx,fe/src/components/deposit/deposit-wallet-send-form.test.tsx.
5. QR Payment Currency Selection: USD Support
- Task Link: https://hola-tech.sg.larksuite.com/record/LkbjrLYa9ecif0cP4XFlwk1JgWb
-
Problem: When scanning a recipient QR code with USD amount and currency, the payment screen only displayed
USDCandUSDTselection buttons, preventing the user from transferring with USD. -
Fix:
- Made selectable currencies kind-aware in
fe/src/app/payment.tsx: recipient QRs allow['USD', 'USDC', 'USDT'], while on-chain address QRs strictly restrict to['USDC', 'USDT'](preventing withdrawal routing failures). - Routed direct USD recipient sends through the passcode-confirmed fiat transfer rail
POST /transactions/transfer(useTransactionsControllerTransfer) withpaymentMethod: 'fiat'instead of the crypto/fireblocks/internal-transferendpoint (which only accepts USDC/USDT). - Added passcode pre-flight and
PasscodeSheetinvocation inConfirmSendSheetfor USD transfers. - Guarded group chat transfers against unsupported USD batch transfers.
- Sourced USD balance from
useFiatBalances()and renderedUsdIconon send confirmation screen.
- Made selectable currencies kind-aware in
-
Affected files:
fe/src/app/payment.tsx,fe/src/app/send/confirm.tsx,fe/src/app/send/index.tsx,fe/src/components/send/confirm-send-sheet.tsx,fe/src/components/send/confirm-send-sheet.test.tsx,fe/src/components/payment/payment-screen.test.tsx,fe/src/components/send/qr-recipient.test.tsx.
Verification
-
Unit & Integration Tests:
-
confirm-send-sheet.test.tsx(4/4 passed) -
approved-card-view.test.tsx(27/27 passed) -
deposit-wallet-send-form.test.tsx(36/36 passed) -
payment-screen.test.tsx(35/35 passed) - Full Jest suite: 1647 passed across 155 test suites (0 failed).
-
-
TypeScript:
pnpm type-check(0 errors). - ESLint: 0 errors on modified files.
-
Maestro CLI End-to-End: Verified on iOS simulator with local mock server:
- Scanned QR code with
USDcurrency -> SelectedUSD-> Navigated to Send -> VerifiedBalance: 2,500.00 USD-> Confirmed -> Typed passcode1357-> Verified completed transfer screen -> Mock backend recorded exact fiat transfer payload. - Scanned Address QR -> Verified
Use USDis absent, only USDC and USDT offered. - Tapped Card
+icon -> VerifiedCreating your card...toast appeared immediately. - Switched mock to 5 cards -> Relaunched app -> Navigated to Card tab -> Verified
"You've reached the limit of 5 cards."persists on app launch with+disabled.
- Scanned QR code with
Review follow-up
Addressed all 10 review threads in c6cfca87 and 03c18969:
- Blocked self-transfer on both FE and BE.
- Rounded USD down to two decimals and rejected zero-after-rounding.
- Added duplicate-submit ref guard and durable idempotency with concurrent replay.
- Added code-aware passcode errors (401/409/429 and non-passcode 401).
- Replaced the unsafe DTO cast with a typed payload.
- Used
paymentMethod: fiatfor USD fee estimation. - Bounded AppKit restore to 10 seconds with Connect fallback, preserved submitting UI, and restricted fallback to
eip155. - Reset card-limit state when fresh card count drops below five.
Additional verification
- Frontend: 156 suites, 1664 tests passed; type-check and changed-file ESLint pass.
- Backend targeted transfer suites: 64 tests passed; transfer service 9/9; backend production build and changed-file ESLint pass.
- Maestro: USD
10.555 -> 10.55, fiat fee payload, idempotency key, self-transfer rejection, address QR has no USD, card creation toast, card limit at five, and add button re-enabled after count drops. - Full backend suite has unrelated pre-existing failures in lending/treasury configuration. Repo-wide
be:lintalso reports pre-existing errors outside the changed files; changed backend files are lint-clean.