Skip to content

hossam9k/Coins

Repository files navigation

πŸ“± Crypto Portfolio Tracker - KMP

Kotlin Compose Multiplatform License Platform iOS Build

A production-ready Kotlin Multiplatform (KMP) application demonstrating modern mobile development practices with Clean Architecture, MVI pattern, and Compose Multiplatform. Track your cryptocurrency portfolio across Android, iOS, and Desktop platforms with a single shared codebase.

✨ Features

🎯 Core Functionality

  • πŸ“Š Real-time Crypto Tracking - Live cryptocurrency prices and market data
  • πŸ’Ό Portfolio Management - Buy/sell cryptocurrencies with balance tracking
  • πŸ“ˆ Performance Analytics - Track your gains/losses with visual charts
  • πŸ”„ Offline Support - Local database with Room for offline access
  • 🎨 Material Design 3 - Modern UI with dynamic theming

πŸ› οΈ Technical Features

  • πŸ” Secure API Key Management - Build-time injection with environment variants
  • πŸ—οΈ Clean Architecture - Separation of concerns with domain/data/presentation layers
  • 🎭 MVI Pattern - Unidirectional data flow for predictable state management
  • ⚠️ Type-safe Error Handling - Comprehensive Result<T, DataError> pattern with HTTP, network, and business errors
  • πŸ”„ Type-safe Navigation - Compose Navigation 2.8+ with serialization
  • πŸ’‰ Dependency Injection - Koin for KMP
  • πŸ§ͺ Testable - Unit tests with Turbine and AssertK

πŸ—οΈ Architecture

πŸ“ Clean Architecture Layers

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Presentation Layer (UI)              β”‚
β”‚  β€’ Compose Multiplatform UI                  β”‚
β”‚  β€’ MVI ViewModels                            β”‚
β”‚  β€’ Navigation & State Management             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚          Domain Layer (Business)             β”‚
β”‚  β€’ Use Cases / Interactors                   β”‚
β”‚  β€’ Domain Models                             β”‚
β”‚  β€’ Repository Interfaces                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚           Data Layer (Sources)               β”‚
β”‚  β€’ Repository Implementations                β”‚
β”‚  β€’ Remote Data Sources (Ktor)               β”‚
β”‚  β€’ Local Data Sources (Room)                β”‚
β”‚  β€’ DTOs & Mappers                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🎭 MVI Pattern

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   UI State   β”‚ ◄─────┐
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
       β”‚               β”‚
       β”‚ renders       β”‚ updates
       β–Ό               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚     View     β”‚       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
       β”‚               β”‚
       β”‚ sends         β”‚
       β–Ό               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚   Intent     β”‚       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β”‚
       β”‚               β”‚
       β”‚ processes     β”‚
       β–Ό               β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       β”‚
β”‚  ViewModel   β”‚β”€β”€β”€β”€β”€β”€β”€β”˜
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

⚠️ Error Handling Architecture

Type-safe error handling with Result<T, DataError>:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       DataError                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Remote (enum)         β”‚  Local (enum)    β”‚  Business       β”‚
β”‚  ─────────────────     β”‚  ────────────    β”‚  (sealed class) β”‚
β”‚  β€’ UNAUTHORIZED        β”‚  β€’ DISK_FULL     β”‚  β€’ InvalidCreds β”‚
β”‚  β€’ FORBIDDEN           β”‚  β€’ NOT_FOUND     β”‚  β€’ KycRequired  β”‚
β”‚  β€’ NOT_FOUND           β”‚  β€’ INSUFFICIENT  β”‚  β€’ LimitReached β”‚
β”‚  β€’ NO_INTERNET         β”‚  β€’ UNKNOWN       β”‚  β€’ SessionExpiredβ”‚
β”‚  β€’ REQUEST_TIMEOUT     β”‚                  β”‚  β€’ Unknown(code)β”‚
β”‚  β€’ SERVER_ERROR        β”‚                  β”‚                 β”‚
β”‚  β€’ SERIALIZATION       β”‚                  β”‚                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“š Read more: Network & Error Handling

πŸš€ Tech Stack

Core

  • Kotlin Multiplatform - Share code across platforms
  • Compose Multiplatform - Declarative UI framework
  • Kotlin Coroutines - Asynchronous programming

Networking & Data

  • Ktor Client - HTTP networking
  • Kotlinx Serialization - JSON serialization
  • Room Database - Local persistence with KMP support

Architecture & DI

  • Koin - Dependency injection for KMP
  • Lifecycle ViewModel - State management
  • Navigation Compose - Type-safe navigation

UI & Design

  • Material Design 3 - Modern design system
  • Coil 3 - Image loading for Compose
  • Custom Design Tokens - Consistent theming

Build & Security

  • Gradle Build Variants - Dev/Staging/Prod environments
  • ProGuard/R8 - Code obfuscation & shrinking
  • Detekt - Static code analysis
  • ktlint - Code style enforcement & formatting

πŸ“¦ Project Structure

Coins/
β”œβ”€β”€ composeApp/                          # Main application module
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ commonMain/                  # Shared code (all platforms)
β”‚   β”‚   β”‚   └── kotlin/org/poc/app/
β”‚   β”‚   β”‚       β”œβ”€β”€ core/                # Core utilities & config
β”‚   β”‚   β”‚       β”‚   β”œβ”€β”€ config/          # App configuration & BuildConfig
β”‚   β”‚   β”‚       β”‚   β”œβ”€β”€ data/            # Core data (database, network)
β”‚   β”‚   β”‚       β”‚   β”‚   β”œβ”€β”€ network/     # HTTP client, error handling
β”‚   β”‚   β”‚       β”‚   β”‚   └── datasource/  # Data source interfaces
β”‚   β”‚   β”‚       β”‚   β”œβ”€β”€ domain/          # Core domain models (Result, DataError)
β”‚   β”‚   β”‚       β”‚   └── presentation/    # MVI base classes
β”‚   β”‚   β”‚       β”œβ”€β”€ feature/             # Feature modules
β”‚   β”‚   β”‚       β”‚   β”œβ”€β”€ coins/           # Crypto list feature
β”‚   β”‚   β”‚       β”‚   β”œβ”€β”€ portfolio/       # Portfolio feature
β”‚   β”‚   β”‚       β”‚   └── trade/           # Buy/Sell feature
β”‚   β”‚   β”‚       β”œβ”€β”€ navigation/          # App navigation
β”‚   β”‚   β”‚       └── ui/                  # Design system
β”‚   β”‚   β”‚           β”œβ”€β”€ components/      # Reusable UI components
β”‚   β”‚   β”‚           β”œβ”€β”€ foundation/      # Colors, typography, spacing
β”‚   β”‚   β”‚           └── theme/           # Theme configuration
β”‚   β”‚   β”œβ”€β”€ androidMain/                 # Android-specific code
β”‚   β”‚   β”œβ”€β”€ iosMain/                     # iOS-specific code
β”‚   β”‚   └── desktopMain/                 # Desktop-specific code
β”‚   β”œβ”€β”€ build.gradle.kts                 # Build configuration
β”‚   └── proguard-rules.pro              # ProGuard rules
β”œβ”€β”€ iosApp/                              # iOS Xcode project
β”œβ”€β”€ docs/
β”‚   └── NETWORK_AND_ERROR_HANDLING.md   # Error handling architecture
β”œβ”€β”€ config/
β”‚   └── detekt/detekt.yml               # Code quality config
β”œβ”€β”€ local.properties.example             # Template for API keys
β”œβ”€β”€ API_KEYS_SETUP.md                   # API key security guide
β”œβ”€β”€ BUILD_VARIANTS.md                   # Build variants documentation
└── README.md                           # This file

πŸ› οΈ Setup & Installation

Prerequisites

  • JDK 17+ - Java Development Kit
  • Android Studio Ladybug+ - Latest stable version
  • Xcode 15+ (for iOS) - macOS only
  • Gradle 8.14+ - Build tool

1️⃣ Clone the Repository

git clone https://github.com/hossam9k/Coins.git
cd Coins

2️⃣ Configure API Keys

# Copy the example file
cp local.properties.example local.properties

# Edit and add your API keys
# Get free API keys from: https://coincap.io/
nano local.properties

local.properties:

# Development
DEV_COINCAP_API_KEY=your_dev_key_here
DEV_API_BASE_URL=https://api.coincap.io/v2

# Staging
STAGING_COINCAP_API_KEY=your_staging_key_here
STAGING_API_BASE_URL=https://api.coincap.io/v2

# Production
PROD_COINCAP_API_KEY=your_prod_key_here
PROD_API_BASE_URL=https://api.coincap.io/v2

πŸ“š Read more: API_KEYS_SETUP.md

3️⃣ Build & Run

Android

# Development build
./gradlew :composeApp:assembleDevDebug

# Install to device
./gradlew :composeApp:installDevDebug

iOS (macOS only)

# Build iOS framework
./gradlew :composeApp:linkDebugFrameworkIosSimulatorArm64

# Open Xcode project
open iosApp/iosApp.xcodeproj

Desktop

# Run desktop app
./gradlew :composeApp:run

πŸ“š Read more: BUILD_VARIANTS.md

🎯 Build Variants

The project supports three environment variants:

Variant App ID Debug Analytics Use Case
dev org.poc.app.dev βœ… ❌ Local development
staging org.poc.app.staging ❌ βœ… QA testing
prod org.poc.app ❌ βœ… Production
# Build different variants
./gradlew :composeApp:assembleDevDebug
./gradlew :composeApp:assembleStagingDebug
./gradlew :composeApp:assembleProdRelease

πŸ§ͺ Testing

Run Unit Tests

./gradlew test

Run Android Instrumentation Tests

./gradlew :composeApp:connectedDevDebugAndroidTest

Code Quality Analysis

# Run Detekt static analysis
./gradlew detekt

# Run ktlint code style check
./gradlew ktlintCheck

# Auto-format code with ktlint
./gradlew ktlintFormat

πŸ“± Screenshots

Coming soon...

πŸ” Security & Code Quality

Security Features

  • βœ… No Hardcoded Secrets - API keys in gitignored local.properties
  • βœ… Build-time Injection - Keys embedded during compilation
  • βœ… ProGuard Obfuscation - Code obfuscation in release builds
  • βœ… Environment Separation - Different keys per environment
  • βœ… CI/CD Ready - Environment variable support

Code Quality

  • βœ… Detekt - Static code analysis with custom rules
  • βœ… ktlint - Automated code formatting & style enforcement
  • βœ… Compose Function Naming - Proper @Composable conventions
  • βœ… Explicit Imports - No wildcard imports for clarity
  • βœ… Consistent Naming - SCREAMING_SNAKE_CASE for constants

πŸ“š Documentation

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the project
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

πŸ“ž Contact

Hossam Atef - @hossam9k

Project Link: https://github.com/hossam9k/Coins

About

A production-ready Kotlin Multiplatform (KMP)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors