Documentation
# Obol Architecture

A comprehensive Rust portfolio tracker with real-time price monitoring, historical data collection, and interactive visualization.

## System Overview

```
┌─────────────────────────────────────────────────────────────┐
│                     Obol Portfolio Tracker                 │
├─────────────────────────────────────────────────────────────┤
│  CLI Commands: obol [TUI] | nw | edit | start | stop       │
└─────────────────────────────────────────────────────────────┘
         │                    │                    │
         ▼                    ▼                    ▼
┌───────────────┐    ┌───────────────┐    ┌───────────────┐
│   TUI Module  │    │ Background    │    │ CLI Commands  │
│ (Interactive) │    │   Daemon      │    │ (One-shot)    │
└───────────────┘    └───────────────┘    └───────────────┘
         │                    │                    │
         └────────────────────┼────────────────────┘
                   ┌─────────────────┐
                   │ Portfolio Core  │
                   │   (lib.rs)      │
                   └─────────────────┘
         ┌────────────────────┼────────────────────┐
         │                   │                    │
         ▼                   ▼                    ▼
┌───────────────┐    ┌───────────────┐    ┌───────────────┐
│ Configuration │    │ Price Engine  │    │   Database    │
│   & Parsing   │    │ (Multi-API)   │    │ (Time Series) │
└───────────────┘    └───────────────┘    └───────────────┘
```

## Core Architecture Components

### 1. Entry Points (`main.rs`)
- **CLI Router**: Dispatches commands (`nw`, `edit`, `start`, `stop`)
- **TUI Launcher**: Default action launches interactive interface
- **Configuration Management**: Auto-creates `~/.obol/portfolio.toml`

### 2. Library Core (`lib.rs`)
Central re-export hub exposing:
```rust
pub use config::*;           // TOML configuration & parsing
pub use portfolio::*;        // Portfolio builder & data structures  
pub use price::*;           // Multi-provider price engine
pub use database::*;        // SQLite time series storage
pub use error::*;           // Unified error handling
pub use validation::*;      // Multi-tier validation system
```

### 3. Configuration System (`config.rs`)

```
Portfolio Config
├── currencies: HashMap<String, Decimal>     // "USD" -> 1000.00
├── stocks: HashMap<String, i32>             // "AAPL" -> 10  
└── crypto: HashMap<String, Decimal>         // "bitcoin" -> 0.5
                                            // "0x.../ethereum" -> 100.0
```

**Key Features:**
- **TOML Format**: Human-readable configuration
- **Auto-validation**: Two-tier validation (basic + comprehensive)
- **Contract Support**: Ethereum addresses with chain specification
- **Backwards Compatibility**: Graceful upgrades

**Validation Tiers:**
```rust
validate_basic()    // Fast, synchronous format checks
validate()          // Full async validation with external APIs
```

### 4. Portfolio Engine (`portfolio.rs`)

**Builder Pattern Architecture:**
```rust
PortfolioBuilder::new(config)
    .base_currency("USD")
    .with_price_provider(provider)
    .cache_first(true)                    // Skip API calls
    .build()                              // Result<Portfolio, Error>
    .build_with_fallback()               // (Portfolio, Vec<String>)
```

**Asset Holdings:**
```rust
AssetHolding {
    quantity: Decimal,     // User's amount
    price: Decimal,        // Current market price
    value: Decimal,        // quantity * price in base currency
}
```

### 5. Price Engine (`price/`)

**Multi-Provider System:**
```
CombinedPriceProvider
├── CurrencyProvider (FawazCurrencyAPI) → 300 req/min
├── StockProvider (Yahoo Finance)       → 100 req/min  
└── CryptoProvider (CoinGecko)         → 10 req/min
```

**Rate Limiting Architecture:**
```rust
RateLimiter::with_retry("CoinGecko", || async {
    // API call with automatic exponential backoff
}).await
```

**Provider Configurations:**
- **CoinGecko**: 10 req/min, 6s delays, conservative backoff
- **Yahoo Finance**: 100 req/min, 600ms delays  
- **FawazCurrency**: 300 req/min, 200ms delays

### 6. Database Layer (`database/`)

**SQLite Schema:**
```sql
assets                    price_data
├── id (INTEGER PK)      ├── id (INTEGER PK)
├── symbol (TEXT)        ├── asset_id (INTEGER FK)
├── asset_type (TEXT)    ├── price (REAL)
├── contract_address     ├── timestamp (INTEGER)
└── chain (TEXT)         └── source (TEXT)

portfolio_snapshots
├── id (INTEGER PK)
├── timestamp (INTEGER)
├── total_value (REAL)
└── breakdown (JSON)
```

**Time Series Features:**
- **WAL Mode**: Concurrent daemon + TUI access
- **Asset Resolution**: Symbol → ID mapping with contract support
- **Historical Queries**: Price trends, portfolio snapshots
- **Automatic Schema**: Self-initializing on first run

### 7. Background Daemon (`daemon/`)

**Service Architecture:**
```
DaemonService
├── PriceScheduler → Fetches prices every 5 minutes
├── RateLimiter    → Prevents API overload
└── Database       → Stores historical data
```

**Process Management:**
- **PID Tracking**: `/tmp/obol-daemon.pid`
- **Signal Handling**: Graceful shutdown on SIGTERM
- **Error Recovery**: Continues on individual API failures

### 8. TUI Interface (`tui/`)

**Real-time Components:**
```
App State
├── Portfolio Data    → Live calculations
├── Chart History    → Database queries  
├── Refresh Timer    → Auto-updates
└── Error Display    → User feedback
```

**Chart System:**
- **Ratatui Framework**: Terminal-based UI
- **Real-time Updates**: Automatic refresh with rate limiting
- **Historical Charts**: Price trends over time
- **Interactive Navigation**: Keyboard controls

### 9. Validation System (`validation.rs`)

**Multi-Validator Architecture:**
```rust
ValidationPipeline
├── CurrencyValidator → ISO codes, exchange rates
├── StockValidator    → Symbol format, market existence  
└── CryptoValidator   → Ticker symbols, contract addresses
```

**Validation Strategy:**
- **Format Validation**: Immediate syntax checking
- **Market Validation**: External API verification
- **Contract Validation**: Ethereum address format + chain

## Trait System & Dependencies

### Core Traits

**Price Provider Trait:**
```rust
#[async_trait]
trait PriceProvider {
    async fn get_currency_rate(&self, from: &str, to: &str) -> Result<Decimal>;
    async fn get_stock_price(&self, symbol: &str) -> Result<Decimal>;  
    async fn get_crypto_price(&self, asset_key: &str) -> Result<Decimal>;
}
```

**Database Trait:**
```rust
trait TimeSeriesDB {
    fn store_price_data(&self, data: &[PriceDataPoint]) -> Result<()>;
    fn get_price_history(&self, symbol: &str, days: i32) -> Result<Vec<PricePoint>>;
    fn get_latest_prices(&self) -> Result<HashMap<String, Decimal>>;
}
```

### Error Handling Strategy

**Unified Error Types:**
```rust
#[derive(thiserror::Error)]
enum Error {
    #[error("Configuration error: {message}")]
    Config { message: String },
    
    #[error("Price fetch failed: {provider} - {message}")]  
    PriceFetch { provider: String, message: String },
    
    #[error("Database error: {0}")]
    Database(#[from] rusqlite::Error),
    
    #[error("Validation failed: {field} - {message}")]
    Validation { field: String, message: String },
}
```

**Context Chaining:**
```rust
.with_context(|| format!("Failed to fetch {} price", symbol))
.map_err(|e| Error::price_fetch("CoinGecko", e.to_string()))
```

### Key Dependencies

**Core Runtime:**
- `tokio` - Async runtime for concurrent price fetching
- `serde` + `toml` - Configuration serialization
- `thiserror` + `anyhow` - Structured error handling

**Data & Calculation:**
- `rust_decimal` - Precise financial calculations
- `rusqlite` - SQLite database interface
- `time` - Timestamp handling and formatting

**Networking & APIs:**  
- `reqwest` - HTTP client for API calls
- `serde_json` - API response parsing

**User Interface:**
- `ratatui` - Terminal UI framework
- `crossterm` - Cross-platform terminal control

**Utilities:**
- `dirs` - Cross-platform directory discovery
- `tempfile` - Test file management
- `tracing` - Structured logging

## Data Flow Architecture

### Price Collection Flow
```
1. Daemon Scheduler (every 5 min)
   2. Rate Limiter → Acquire permits
     
3. Price Providers → Fetch from APIs
   4. Database Storage → Store time series
   5. TUI Auto-refresh → Display updates
```

### Portfolio Building Flow
```
1. Config Loading → Parse TOML file
   2. Asset Parsing → currencies/stocks/crypto
   3. Price Fetching → Concurrent API calls
   4. Portfolio Assembly → Calculate holdings
   5. Display/Storage → TUI or database
```

### Validation Flow
```
1. Basic Validation → Format checks (sync)
   2. Full Validation → Market verification (async)
   3. Error Collection → User-friendly messages
   4. Graceful Degradation → Partial success handling
```

## Performance & Scalability

### Concurrent Design
- **Async-first**: All I/O operations use `tokio`
- **Parallel Price Fetching**: Multiple APIs simultaneously
- **Non-blocking UI**: TUI remains responsive during data loading

### Caching Strategy
- **Database Cache**: Historical prices stored locally
- **Cache-first Mode**: Skip API calls entirely when possible
- **Fallback Mechanism**: Use cache when APIs fail

### Resource Management
- **Connection Pooling**: Reuse HTTP connections
- **Memory Efficiency**: Stream large datasets
- **Rate Limit Compliance**: Prevent API bans

### Error Resilience
- **Graceful Degradation**: Partial data better than complete failure
- **Retry Logic**: Exponential backoff for transient failures
- **Timeout Protection**: All network operations have limits

## Security & Reliability

### Data Protection
- **No API Keys Required**: Uses public endpoints only
- **Local Storage**: All data remains on user's machine
- **Read-only APIs**: No sensitive operations

### Reliability Features
- **Two-tier Validation**: Catch errors early and comprehensively
- **Timeout Protection**: Prevent hanging operations
- **Graceful Error Handling**: Clear user feedback
- **Atomic Operations**: Database consistency

This architecture provides a robust, scalable foundation for portfolio tracking with clean separation of concerns, comprehensive error handling, and excellent user experience.