Fixes 14 issues across the mobile app, backend push/email notifications and the admin dashboard. Mostly fe; one backend change (notification amounts) and one backend + admin change (lending dashboard metrics).
1. Bottom sheets and buttons hidden behind the Android navigation bar
Lark: TBD · Module: Withdraw, Transfer, Convert, Send, Passcode, Card, Lending, Groups · Priority: Medium
Actual: With edge-to-edge on Android, Confirm/Close buttons sit partly or fully under the 3-button navigation bar.
Expected: Every bottom action is fully visible on Android and iOS.
Fix: Fixed-height sheets whose content pads insets.bottom now grow by insets.bottom (confirm withdraw/transfer/convert/send, passcode, issue card, date picker; passcode and date picker capped below the status bar). Completed screens, the loan receipt and the create-group / add-member footers keep insets.bottom + 16.
Commit: 23e7e502
2. Withdraw shows "1.5 USDC" and "0.5000 USDC"
Lark: TBD · Module: Withdraw · Priority: Medium Fix: Amounts pad to two decimals, fees show 2–6 decimals rounded down, so real crypto precision is never cut. Request bodies, idempotency keys and route params keep the raw values. Commit: 59f0a416
3. Typed amounts show "5" while system figures show "5.00"
Lark: TBD · Module: Transfer, Send, Convert, Card · Priority: Medium · https://screenrec.com/share/HheCJL68T9
Fix: Typed amounts are padded to two decimals on blur and in the confirm sheets; placeholders read 0.00. Idempotency keys go through toAmountKey (with a legacy fallback) so 5 and 5.00 stay the same request.
Commit: d29407b5
4. Notifications show "1500.00000000 USD"
Lark: TBD · Module: Push / email notifications (backend) · Priority: Medium · https://prnt.sc/z__UUDHlTUjU
Fix: New formatDisplayAmount helper (two decimals, real crypto precision kept), applied in every notification listener and the lending notifier.
Commit: 06850aee
5. Repeated taps on History stack duplicate screens
Lark: TBD · Module: Convert, Loans, Card · Priority: Medium · https://screenrec.com/share/0d1mw5YGt3
Fix: Convert history rows and icon, loan history and card history navigate through usePushOnce.
Commit: 24425741
6. "+" at the 5-card limit shows a generic error
Lark: TBD · Module: Card · Priority: Medium · https://prnt.sc/ZHVcKXCpxZIj
Fix: Live cards are counted against MAX_CARDS_PER_USER (mirrors the backend) and "+" explains the limit before the fee lookup.
Commit: abdc352f
7. Admin dashboard shows "Not connected" for lending alerts
Lark: TBD · Module: Admin dashboard · Priority: Medium · https://jam.dev/c/599cb52f-3343-4913-ba5f-0650d954cbfc
Fix: Live counts: open ops alerts (resolved_at IS NULL) and open transfer intents older than transfer_stuck_escalation_minutes (default 120, the same rule the SLA sweep uses). The card now links to /lending/risk.
Commit: a8375616
8. Card tab spins forever
Lark: TBD · Module: Card · Priority: Medium Fix: A failed token refresh now rejects the queued requests and signs out instead of leaving them pending. Commit: 30ff9fec
9. Home assets: no icon for EUR/GBP/SGD, USD not first
Lark: TBD · Module: Home · Priority: Low Fix: USD listed first; other fiats get a currency-symbol circle in the same shape as the USD icon. Commit: a004b382
10–14. Smaller UI fixes
- Hide the Invite hub entry and the HKD currency option (commented out, not deleted): 5a6e1be1
- Convert history icon on the header row: a419bdb3
- "USD Wallet" naming in the card transfer flow: ed9db4a0
- Passcode keypad bottom row aligned with the rows above: b9b86582
- "pass code" spelled "passcode" everywhere: bfb0d39a
Verification
- fe (after merging
develop):pnpm type-checkpass ·pnpm lint0 errors · Jest 157/157 suites, 1687/1687 tests. - be:
yarn buildpass; notification and dashboard specs pass; dashboard SQL checked against a real Postgres 16 with all migrations. Two lending controller specs (admin-lending.risk,lending.http) already fail ondevelopand are unrelated. - admin:
pnpm test72/72 suites, 835/835 tests · type-check pass · lint 0 errors. - Device: confirm-withdraw sheet and amount format checked on a Samsung M34 (Android, 3-button navigation). The other sheets were not opened on a device.
Notes
- The dashboard endpoint needs
system:read, while/lending/riskneedslending:read. An admin with onlysystem:readsees the count but cannot open the list. This mismatch already existed and is not changed here. - The dashboard label "over 2 hours" assumes the default threshold of 120 minutes.