Skip to content

Project Structure

DWallet is built on a scalable and modular architecture using Riverpod for state management and AutoRoute for navigation. This structure separates presentation logic, business logic, and data handling, ensuring code maintainability and testability.

The root of the project contains configuration files for the Flutter environment and tooling.

dwallet_ui/
├── android/ # Native Android project files
├── ios/ # Native iOS project files
├── lib/ # Main application source code
├── packages/ # Local packages (dwallet_types)
├── docs/ # Documentation (this site)
├── pubspec.yaml # Dependencies and project metadata
└── analysis_options.yaml # Linter rules

The core logic resides in lib/. We follow a feature-based organization with clear separation of concerns.

lib/
├── main.dart # App entry point
└── /app
├── /core # Core utilities
│ ├── /extensions # Dart extensions
│ ├── /helpers # Helper functions
│ ├── /theme # Theme configuration
│ └── _app_lifecycle_observer.dart
├── /di # Dependency injection
│ ├── _run_di.dart # DI initialization
│ └── /services # Service providers
│ ├── _auth_user_service.dart
│ ├── _theme_service.dart
│ ├── _security_service.dart
│ └── _shared_prefs_service.dart
├── /pages # UI pages
│ ├── /auth # Authentication flow
│ │ ├── auth.wrapper.dart
│ │ └── /onboard
│ │ ├── onboard_view.dart
│ │ └── /pages
│ ├── /client # Main app pages
│ │ ├── client.wrapper.dart
│ │ ├── /bottom_nav
│ │ ├── /home
│ │ ├── /wallet
│ │ ├── /analytics
│ │ ├── /all_transaction_list
│ │ ├── /settings
│ │ └── /components # Shared client components
│ └── debugger.wrapper.dart
├── /providers # State providers
│ ├── security_provider.dart
│ └── lockout_provider.dart
├── /router # Navigation
│ ├── _app_router.dart # Route configuration
│ ├── _app_router.gr.dart # Generated routes
│ └── /guards # Route guards
│ └── _onboard_route_guard.dart
└── /widgets # Reusable widgets
├── _app_lock_screen.dart
├── _numeric_pad.dart
├── _wallet_card.dart
└── ...

Data models are isolated in a separate package for better separation and potential reuse.

packages/dwallet_types/
└── /lib/src
├── /abstractions # Interfaces
│ ├── _user.dart
│ ├── _transaction.dart
│ ├── _wallet.dart
│ ├── _category.dart
│ ├── _currency.dart
│ └── _enums.dart
├── /models # Model implementations
│ ├── _user.dart
│ ├── _transaction.dart
│ ├── _wallet.dart
│ ├── _category.dart
│ └── _currency.dart
└── /mocks # Mock data
├── _transaction.dart
├── _wallet.dart
├── _category.dart
├── _currency.dart
└── _user.dart

We use Riverpod for predictable, type-safe state management:

Provider TypeUse CaseExample
AsyncNotifierAsync operations (API calls)AuthUserService
NotifierSync mutable stateThemeService, SecurityNotifier
ProviderComputed/readonly valuesuserCurrencyProvider, showLockScreenProvider

Type-safe routing with code generation:

@AutoRouterConfig()
class DAppRouter extends RootStackRouter {
@override
List<AutoRoute> get routes => [
AutoRoute(page: OnboardRoute.page, path: '/onboard'),
AutoRoute(page: HomeRoute.page, path: '/home'),
// ... more routes
];
}

We use barrel files (*.export.dart) for clean imports:

// Instead of multiple imports:
import '../app/core/extensions/extensions.export.dart';
import '../app/core/helpers/helpers.export.dart';
import '../app/core/theme/theme.export.dart';
// You get one clean import:
import '../app/core/core.export.dart';

Business logic services that interact with external systems:

  • AuthUserService: User authentication state and profile
  • ThemeService: Theme mode and color scheme persistence
  • SecurityStorageService: PIN, biometrics, and app lock settings
  • BiometricService: Local authentication using device biometrics

Feature-based UI organization:

  • /auth/: Authentication and onboarding flows
  • /client/: Main app screens (home, wallet, analytics, settings)
  • Shared components in /client/components/

Additional state providers for specific features:

  • securityProvider: App lock state and PIN verification
  • lockoutProvider: Failed attempt tracking and lockout timer

Centralized navigation management:

  • _app_router.dart: Route definitions with guards
  • /guards/: Route guards (e.g., OnboardRouteGuard)

Reusable UI components:

  • AppLockScreen: Full-screen lock overlay
  • NumericPad: Reusable numeric keypad
  • WalletCardWidget: Wallet display card
  • TransactionCardWidget: Transaction list item