## User Balance System Documentation

### Overview
A per-market wallet system that tracks individual balances for each cryptocurrency market. Swaps deduct from the "from" wallet and credit the "to" wallet.

### Files Created

1. **Database Migration**: `database/migrations/2026_01_25_120001_create_user_balances_table.php`
   - Creates `user_balances` table with user_id, market_id, and balance columns
   - Unique constraint on (user_id, market_id) pair

2. **Model**: `app/Models/UserBalance.php`
   - Methods: `addBalance()`, `deductBalance()`, `hasSufficientBalance()`
   - Relationships: `user()`, `market()`

3. **Service**: `app/Services/WalletService.php`
   - Reusable helper functions for wallet management

### WalletService - Available Methods

#### 1. Ensure User Has All Wallets
```php
use App\Services\WalletService;
use App\Models\User;

$user = User::find(1);
WalletService::ensureUserHasAllMarketBalances($user);
```
Creates missing balance records for all active markets (initialized to 0).

#### 2. Get User's Balance for Specific Market
```php
$user = User::find(1);
$market = Market::find(1);

$userBalance = WalletService::getUserMarketBalance($user, $market);
$amount = $userBalance->balance; // 100.50000000
```

#### 3. Get All User Balances
```php
$user = User::find(1);
$allBalances = WalletService::getUserBalances($user);

foreach ($allBalances as $balance) {
    echo $balance->market->asset . ': ' . $balance->balance;
}
```

#### 4. Check Sufficient Balance
```php
$user = User::find(1);
$market = Market::find(1);
$amount = 50.5;

if (WalletService::hasSufficientBalance($user, $market, $amount)) {
    // User has at least 50.5 in this market
}
```

#### 5. Get Total Balance Across All Markets
```php
$user = User::find(1);
$total = WalletService::getTotalBalance($user); // 500.25000000
```

#### 6. Deduct Balance (with validation)
```php
try {
    WalletService::deductBalance($user, $market, 50.5);
} catch (\Exception $e) {
    // Handles insufficient balance or missing wallet
    echo $e->getMessage();
}
```

#### 7. Add Balance (with validation)
```php
try {
    WalletService::addBalance($user, $market, 100.0);
} catch (\Exception $e) {
    echo $e->getMessage();
}
```

### Swap Flow (Automatic via SwapService)

1. User visits `/swap` route
   - `WalletService::ensureUserHasAllMarketBalances()` is called
   - Ensures user has balance record for each market

2. User previews swap (AJAX call)
   - Checks balance in FROM market
   - Returns current balances in both markets

3. User executes swap
   - Validates sufficient balance in FROM market (including fee)
   - Deducts from FROM market balance
   - Credits to TO market balance
   - Records transactions

### Updated Controllers/Services

#### SwapController
- **index()**: Now calls `WalletService::ensureUserHasAllMarketBalances()` on page load
- **preview()**: Uses `WalletService::hasSufficientBalance()` and per-market balances

#### SwapService
- **executeSwap()**: Uses `WalletService` methods instead of `user->balance`
  - Checks balance in FROM market
  - Deducts from FROM market + fee
  - Credits to TO market

### Usage Examples in Custom Code

#### Example 1: Deposit to a User's Wallet
```php
use App\Services\WalletService;
use App\Models\User;
use App\Models\Market;

$user = User::find(1);
$bitcoinMarket = Market::where('asset', 'BTC')->first();

WalletService::ensureUserHasAllMarketBalances($user);
WalletService::addBalance($user, $bitcoinMarket, 0.5);
```

#### Example 2: Process a Manual Withdrawal
```php
$user = User::find(1);
$ethMarket = Market::where('asset', 'ETH')->first();
$withdrawAmount = 10.5;

try {
    WalletService::deductBalance($user, $ethMarket, $withdrawAmount);
    // Record in transaction history
    Transaction::create([
        'user_id' => $user->id,
        'type' => TransactionType::WITHDRAW,
        'amount' => $withdrawAmount,
        'market_id' => $ethMarket->id,
    ]);
} catch (\Exception $e) {
    return response()->json(['error' => $e->getMessage()], 422);
}
```

#### Example 3: Check Balance Before Processing
```php
$user = User::find(1);
$market = Market::find(3);
$requiredAmount = 100;

if (!WalletService::hasSufficientBalance($user, $market, $requiredAmount)) {
    return response()->json([
        'error' => 'Insufficient balance',
        'current' => $balance = WalletService::getUserMarketBalance($user, $market)->balance
    ], 422);
}

// Process operation
```

#### Example 4: Get User's Total Portfolio Value
```php
use App\Services\WalletService;

$user = User::find(1);
$allBalances = WalletService::getUserBalances($user);

$totalInUSD = 0;
foreach ($allBalances as $balance) {
    $marketPriceInUSD = $balance->market->price; // or your conversion method
    $totalInUSD += $balance->balance * $marketPriceInUSD;
}

echo "Portfolio Value: $" . number_format($totalInUSD, 2);
```

### Migration & Deployment

Run the migration:
```bash
php artisan migrate
```

### Database Structure

```sql
CREATE TABLE user_balances (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    uuid CHAR(36) UNIQUE NOT NULL,
    user_id BIGINT NOT NULL,
    market_id BIGINT NOT NULL,
    balance DECIMAL(30, 8) DEFAULT 0,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    UNIQUE KEY (user_id, market_id),
    INDEX (user_id),
    INDEX (market_id),
    INDEX (created_at),
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
    FOREIGN KEY (market_id) REFERENCES markets(id) ON DELETE CASCADE
);
```

### Key Features

✅ Per-market wallet balances (not global user balance)
✅ Automatic wallet initialization for new users
✅ Transaction-safe balance operations
✅ Clear, descriptive error messages
✅ Easy to use anywhere in the app
✅ Swap validation against FROM market balance only
✅ Fee deduction from source wallet
✅ Immediate crediting to destination wallet
✅ All operations logged in transaction history
