feat: React Native mobile app, compliance reporting, real-time FX WebSocket (#942 #943 #944)#993
Merged
Haroldwonder merged 1 commit intoJun 29, 2026
Conversation
…ime FX WebSocket (Haroldwonder#942 Haroldwonder#943 Haroldwonder#944) ### Haroldwonder#942 — React Native mobile app for senders - Initialise Expo-based React Native project under `mobile/` - Screens: Home, Send Money (3-step wizard), Transaction History, Transaction Detail, KYC Status - Biometric confirmation (Face ID / fingerprint) via `expo-local-authentication` before every transfer - Push notification registration (FCM + APNs) via `expo-notifications` with deep-link tap handling - Service layer (`services/api.ts`) for remittance, KYC, and FX calls against the backend REST API - Secure token storage via `expo-secure-store` - Bottom-tab + stack navigation with `@react-navigation` ### Haroldwonder#943 — Compliance reporting dashboard for regulators - DB migration adding `compliance_thresholds`, `compliance_flagged_remittances`, and `compliance_report_audit` tables - `GET /api/compliance/report` — filtered by date range, status, currency, corridor; returns JSON or CSV (`csv-stringify`) - `GET/POST /api/compliance/thresholds` — configurable per-corridor reporting thresholds - `POST /api/compliance/flag` and `PATCH /api/compliance/flag/:id` — manual flag management - `autoFlagIfAboveThreshold()` called on every new remittance to auto-flag above-threshold transfers - Full audit trail written to `compliance_report_audit` on every report access (actor, IP, filters, row count) ### Haroldwonder#944 — Real-time FX rate WebSocket feed - `socket.io` namespace `/fx-rates` mounted at path `/ws` on the existing HTTP server - `FxRateWebSocketServer` pushes updates to subscribed rooms within 1 s of cache refresh - `subscribe` / `unsubscribe` messages support per-pair filtering (`USD/PHP`, `USD/MXN`, ...) - Rate-replay on subscribe: last known rate sent immediately to reconnecting clients - `FxRateCache` emits `rate_updated` events (via injected `EventEmitter`) on every background refresh and new fetch - Graceful shutdown: WebSocket server closed before PostgreSQL pool drain - WebSocket protocol documented in `API.md`
|
@ink-mami is attempting to deploy a commit to the Harold's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@ink-mami Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
closes #942 — React Native mobile app for senders (
mobile/)Why: Migrant workers predominantly use mobile devices; SwiftRemit had no mobile surface.
What was built:
mobile/) targeting iOS and Androidexpo-local-authentication) — Face ID / fingerprint required before every transfer; gracefully falls through on devices without hardware biometricsexpo-notifications) — registers for FCM (Android) and APNs (iOS) on first launch; notification tap deep-links to the relevant transactionexpo-secure-store; typed service layer for all backend API calls@react-navigationKey files:
mobile/App.tsxmobile/src/screens/SendMoneyScreen.tsxmobile/src/screens/TransactionHistoryScreen.tsxmobile/src/screens/KycStatusScreen.tsxmobile/src/services/api.tsmobile/src/services/biometrics.tsmobile/src/services/notifications.tscloses #943 — Compliance reporting dashboard for regulators (
backend/)Why: Regulators require real-time / periodic reporting of cross-border transfers above a threshold.
What was built:
add_compliance_reporting.sql) — three new tables:compliance_thresholds— configurable per-corridor thresholds (e.g. USD/PHP above $3 000)compliance_flagged_remittances— auto-flagged transfers with status lifecycle (pending → reported → cleared)compliance_report_audit— immutable log of every report access (actor, IP, filters, row count)autoFlagIfAboveThreshold()called on every new remittance creation; no manual intervention needed/api/compliance:GET/reportGET/thresholdsPOST/thresholdsPOST/flagPATCH/flag/:idcsv-stringify— FINCEN/FATF-compatible column headerscloses #944 — Real-time FX rate WebSocket feed (
backend/)Why: Clients had to poll REST to get FX updates; adds latency and unnecessary load.
What was built:
socket.iodependency added to backendFxRateWebSocketServer(backend/src/fx-rate-websocket.ts) — Socket.io namespace/fx-ratesmounted at path/wson the existinghttp.Serversubscribe/unsubscribewith apairsarray (e.g.["USD/PHP", "USD/MXN"]); internally rooms are keyed by pair so only relevant subscribers receive each updateFxRateCachenow emitsrate_updatedvia an injectedEventEmitter; background refreshes and new fetches both trigger the event, so connected clients receive updates within 1 s of any cache writefxRateWss.close()called before PostgreSQL pool drainAPI.md(connection URL, events, reconnect behaviour, JS example)Test plan
cd mobile && npx expo start— app boots on iOS / Android simulator; all 3 tabs reachablePOST /api/compliance/thresholdswith{ "corridor": "USD/PHP", "currency": "USD", "threshold": 100 }→ create a remittance > 100 →GET /api/compliance/reportreturns the flagged record in < 5 sGET /api/compliance/report?format=csvreturns a downloadable CSVsubscribe { pairs: ["USD/PHP"] }→ receivesfx_rateimmediately (rate-replay) and again within 1 s of next cache refresh