High-Level Architecture
Relevant source files
The following files were used as context for generating this wiki page:
Hesabyar is a Persian-first personal finance application for Android that utilizes a hybrid architecture combining a Kotlin/Jetpack Compose frontend with a shared native core written in Rust. The system is designed with an offline-first philosophy, where all critical business logic, financial calculations, and data processing occur on-device.
The architecture is structured into a clean separation of concerns: the Android application layer handles the user interface and platform-specific services, while the hesabyar-core (Rust) manages performance-critical operations such as Persian Natural Language Processing (NLP), Jalali calendar conversions, and financial analytics. Communication between these layers is facilitated by UniFFI, which generates safe Kotlin bindings for the native code.
Sources: README.md:15-23, AGENTS.md:5-7, rust/hesabyar-core/README.md:3-5
System Overview
The project is organized into two primary domains: the Android App (Kotlin) and the Shared Core (Rust).
Architectural Layers
- UI Layer (Android): Built with Jetpack Compose and Material 3, following an MVVM pattern. It handles user interactions, notifications via WorkManager, and UI state management.
- Domain/Data Layer (Android): Manages data persistence using Room (SQLite) and coordinates business logic through Use Cases and Repositories.
- Native Core Layer (Rust): Provides high-performance implementations for currency formatting, calendar arithmetic, and intelligent parsing.
- Bridge Layer: A
RustBridgeobject in Kotlin acts as the interface to the auto-generated UniFFI scaffolding.
Sources: README.md:83-111, AGENTS.md:46-52, app/src/main/java/io/github/mojri/hesabyar/rust/RustBridge.kt:14-23
The diagram illustrates the flow from the Android UI components through the domain layer into the native Rust core via the UniFFI bridge.
Core Components and Responsibilities
Native Core (hesabyar-core)
The Rust core contains the "hot" logic of the application. By extracting this logic into Rust, the project ensures memory safety and high performance for complex string manipulations and mathematical calculations.
| Module | Responsibility |
|---|---|
| Parser (NLP) | Processes Persian text to detect amounts, categories, and transaction types. |
| Calendar | Handles bidirectional conversion between Gregorian and Jalali (Solar Hijri) dates. |
| Analytics | Aggregates transaction data to compute dashboard statistics and financial health scores. |
| Crypto | Provides AES-256-GCM encryption for data backups. |
| Validation | Enforces business rules for entities like Loans, Installments, and Transactions. |
Sources: README.md:25-30, rust/hesabyar-core/README.md:7-19, app/src/main/java/io/github/mojri/hesabyar/rust/RustBridge.kt:144-165
Data Flow and Reliability
A critical aspect of the architecture is the Kotlin Fallback mechanism. Use cases, such as GetDashboardDataUseCase, check if the native Rust library is initialized and available. If the native core fails to load or returns invalid data, the application falls back to a pure Kotlin implementation of the business logic to ensure the UI remains functional.
Sources: app/src/main/java/io/github/mojri/hesabyar/domain/usecase/GetDashboardDataUseCase.kt:33-40
Sequence of data retrieval demonstrating the fallback logic used to maintain app stability.
Technical Specifications
Data Modeling and Storage
The application uses specific types to maintain financial accuracy and platform compatibility:
- Money: Handled as
Long(representing Rial) to match SQLite's storage capabilities and avoid floating-point errors. - Date: Stored as
Long(UTC Timestamps) but presented via Jalali conversions. - Entities: Shared models exist in both Kotlin (Room entities) and Rust (FFI structs), with
RustMappershandling the transformation between them.
Sources: README.md:65-71, AGENTS.md:37-43, app/src/main/java/io/github/mojri/hesabyar/domain/usecase/GetDashboardDataUseCase.kt:22-30
The UniFFI Bridge
Communication is managed through Java Native Access (JNA) via UniFFI. The Rust core is compiled into a .so (shared object) library for various Android ABIs (aarch64, armv7, x86, x86_64).
Key Bridge Operations:
rustCallSync: Executes native code on the calling thread for low-latency operations like currency formatting.rustCall: Dispatches complex operations (like AI validation) toDispatchers.Defaultto prevent UI blocking.
Sources: rust/hesabyar-core/README.md:32-34, app/src/main/java/io/github/mojri/hesabyar/rust/RustBridge.kt:33-55
Conclusion
The high-level architecture of Hesabyar strikes a balance between modern Android development (Compose, Room, Coroutines) and high-performance native processing. By centralizing core financial and linguistic logic in Rust, the app achieves cross-platform potential while maintaining a robust, offline-capable experience for the Android user base. This structure ensures that even if native components fail, the application logic remains redundant and reliable through Kotlin fallbacks.