A Flutter wallet application built with Cupertino widgets and Riverpod. This app works with the companion Spring Boot backend in wallet_system to handle registration, login, wallet creation, funding, transfers, transaction history, and profile updates.
This repository is the mobile client for the wallet platform. The backend lives in the companion repository:
Together, both projects provide:
- Mobile onboarding and authenticated wallet flows in Flutter
- REST APIs in Spring Boot
- JWT-based authentication with refresh-token support for app clients
- Wallet creation, funding, transfers, and transaction history
- Profile retrieval and account update flows
- Shared security responsibilities between the client and server
- Register a new user account
- Sign in with email and password
- Create a 6-digit transaction PIN after first-time onboarding
- Reset a forgotten password with email, secret key, and new password
- Load the authenticated user profile and wallet summary
- Fund the wallet
- Search users and send money to a recipient
- Show recent contacts during transfer flow
- Display recent transactions on the home screen
- Browse paginated transaction history
- Update email and phone number from settings
- Change password while signed in
- Toggle light and dark theme
- Sign out and clear stored session data
The mobile app is responsible for user experience, local session handling, and sending the right data to the backend.
Secure local storageStores the access token, refresh token, first-time onboarding state, and theme preference on-device throughflutter_secure_storage.Automatic auth header handlingA shared HTTP client adds the bearer token to protected requests.Refresh-token retry flowIf a protected request returns401or403, the app attempts token refresh before treating the session as expired.Forced logout fallbackIf refresh fails, the app clears local credentials and returns to an unauthenticated state.Background session timeoutThe app logs the user out if it resumes after more than 5 minutes in the background.First-time PIN setup routingNew users are routed into PIN creation before using transfer-related actions.Feature-based architectureRepositories handle API access, while Riverpod providers manage async state and UI refreshes.
These are implemented in wallet_system and are important because the mobile app depends on them for money movement and account protection.
Protected API routes with Spring Security and JWTRefresh-token issuance for app clientsPassword hashing through PasswordEncoderTransaction PIN verification before transfersTransactional funding and transfer servicesPessimistic wallet locking during balance updatesIdempotency-key checks for funding and transfersLedger entries for debit and credit recordsPassword re-verification before sensitive profile updates
- Tokens are persisted through secure device storage instead of regular app preferences.
- Authenticated requests share one HTTP client so token injection and refresh handling stay consistent.
- If a session cannot be recovered, the app removes stored credentials and returns to the auth flow.
- The app adds a basic mobile session-safety rule by logging the user out after extended background time.
- Funding and transfer actions are connected to backend flows that enforce transaction rules.
- The app refreshes profile and activity data after balance-changing actions.
- Recent contacts and recent transactions are surfaced to make repeat activity quicker.
- Transfer flow uses a first-time PIN setup gate to support backend PIN enforcement.
- Users can review their profile and wallet summary from the authenticated area.
- Email and phone updates are available from settings.
- Password reset is supported in two forms: signed-in password change and forgot-password recovery.
lib/main.dartApp bootstrap, splash preservation, auth-state gating, and background timeout handling.lib/src/core/network/http_client.dartShared HTTP client for headers, bearer token injection, refresh handling, and unauthorized fallback.lib/src/core/utils/storage.dartSecure local persistence wrapper.lib/src/core/network/api_endpoints.dartMobile-to-backend route mapping.lib/src/features/auth/repository/auth_repository.dartLogin, registration, PIN setup, logout, forgot-password, and reset-password requests.lib/src/features/fund_wallet/repository/fund_wallet_repo.dartWallet funding request handling.lib/src/features/send_money/repository/send_money_repository.dartUser search, recent contacts, and transfer requests.
- Flutter
- Dart
flutter_riverpodhttpflutter_secure_storageintldecimaluuid- Cupertino-based widgets
lib/
main.dart
src/
common_widgets/
core/
constants/
network/
theme/
user/
utils/
features/
activity/
auth/
fund_wallet/
home/
main/
send_money/
settings/
- Flutter SDK installed
- Dart SDK compatible with your Flutter version
- Android Studio, VS Code, or another Flutter-capable IDE
- A running
wallet_systembackend reachable from your device or emulator
flutter pub getflutter runThe API base URL is currently defined in lib/src/core/network/api_endpoints.dart:
static const String baseUrl = 'http://192.168.0.164:8080/api';Update that value to match the machine hosting your backend before running the app.
- On a physical device, use your computer's LAN IP address.
- On an emulator or simulator, use the host address that matches your setup.
- This mobile app is designed to work with the Spring Boot backend in
wallet_system.
- The app starts and resolves the authenticated user state.
- If the session is valid, the user enters the main tab shell.
- If there is no valid session, the app shows the registration/login entry flow.
- After login, first-time users are directed to create a transaction PIN.
- Authenticated users continue into the main wallet experience.
- The client protects session continuity, but money movement guarantees are primarily enforced by the backend.
- Funding and transfer safety depend on backend transactions, idempotency protection, locking, and ledger recording.
- The current mobile timeout is based on background duration, not a full foreground inactivity timer.
- The app’s role is to store session state securely, send the required auth data, and react correctly to backend authorization outcomes.
flutter analyze
flutter test
flutter run- Keep API calls inside repositories instead of calling HTTP directly from widgets.
- Reuse the shared
HttpClientso auth behavior stays consistent. - Follow the feature-first folder structure when adding new screens or state.