# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

H2H (Head to Head) is a peer-to-peer betting platform MVP where users can create, accept, and settle wagers directly with other users. The platform demonstrates core betting workflows with escrow, real-time updates, and a marketplace.

## Tech Stack

- **Backend**: FastAPI (Python 3.11+) with async SQLAlchemy ORM
- **Database**: SQLite (via aiosqlite) - designed for easy migration to PostgreSQL
- **Frontend**: React 18+ with Vite, TypeScript, TailwindCSS
- **Authentication**: JWT tokens with refresh mechanism
- **Real-time**: WebSockets for live updates
- **State Management**: Zustand for client state, React Query for server state

## Commands

### Backend Development

```bash
# Setup
cd backend
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install -r requirements.txt

# Initialize database
python seed_data.py

# Run development server
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

# Run with Docker
docker-compose up backend
```

### Frontend Development

```bash
# Setup
cd frontend
npm install

# Run development server
npm run dev

# Build for production
npm run build

# Type checking
npm run type-check  # If configured

# Run with Docker
docker-compose up frontend
```

### Full Stack

```bash
# Start both services
docker-compose up --build

# Stop all services
docker-compose down

# Reset database (when needed)
docker-compose down -v
```

## Architecture

### Core Data Flow

1. **Bet Creation Flow**:
   - User creates bet → Validates funds → Bet enters marketplace (status: OPEN)
   - No funds locked until bet is accepted

2. **Bet Matching Flow**:
   - User accepts bet → Validates opponent funds → Locks funds in escrow for BOTH parties → Updates bet status to MATCHED
   - Both creator and acceptor have funds locked in wallet.escrow

3. **Settlement Flow**:
   - Winner submits claim → Loser confirms OR disputes → Funds distributed or flagged for review
   - On confirm: escrow released, winner receives stake from both sides
   - On dispute: bet marked DISPUTED for manual resolution

### Database Architecture

**Critical relationship pattern**: The Bet model uses multiple foreign keys to User:
- `creator_id` → User who created the bet
- `opponent_id` → User who accepted the bet (nullable until matched)
- `winner_id` → User who won (nullable until settled)

When querying bets with relationships, use `selectinload()` or `joinedload()` to prevent N+1 queries:

```python
query = select(Bet).options(
    selectinload(Bet.creator),
    selectinload(Bet.opponent)
)
```

### Async SQLAlchemy Patterns

All database operations are async. Key patterns:

**Transaction safety for critical operations**:
```python
async with db.begin_nested():  # Creates savepoint
    bet = await db.get(Bet, bet_id, with_for_update=True)  # Row lock
    wallet.balance -= amount
    wallet.escrow += amount
    # All changes committed together or rolled back
```

**CRUD operations must use async methods**:
- `await db.execute(query)` not `db.execute(query)`
- `await db.commit()` not `db.commit()`
- `await db.refresh(obj)` not `db.refresh(obj)`

### Wallet & Escrow System

The wallet has two balance fields:
- `balance`: Available funds the user can use
- `escrow`: Locked funds in active bets

**Critical invariant**: `balance + escrow` should always equal total funds. When accepting a bet:
1. Deduct from `balance`
2. Add to `escrow`
3. Create ESCROW_LOCK transaction record

When settling:
1. Deduct from loser's `escrow`
2. Add to winner's `balance`
3. Deduct from winner's `escrow` (their original stake)
4. Add to winner's `balance` (their original stake returned)

### WebSocket Events

WebSocket connections authenticated via query param: `ws://host/api/v1/ws?token={jwt}`

Event types broadcast to relevant users:
- `bet_created`: New bet in marketplace
- `bet_accepted`: Bet matched with opponent
- `bet_settled`: Bet result confirmed
- `wallet_updated`: Balance or escrow changed
- `notification`: General user notifications

## Key Constraints

### Bet State Transitions

Valid state transitions:
- OPEN → MATCHED (via accept)
- OPEN → CANCELLED (creator cancels before match)
- MATCHED → IN_PROGRESS (event starts)
- IN_PROGRESS → PENDING_RESULT (event ends, awaiting settlement)
- PENDING_RESULT → COMPLETED (settlement confirmed)
- PENDING_RESULT → DISPUTED (settlement disputed)

Invalid: Cannot cancel MATCHED bets, cannot settle OPEN bets

### Validation Rules

- Stake amount: Must be > 0, ≤ $10,000
- User cannot accept their own bet
- User must have sufficient balance to accept bet
- Only creator can modify/cancel OPEN bets
- Only bet participants can settle
- Odds must be > 0

## Environment Configuration

Backend requires (see `backend/.env.example`):
- `DATABASE_URL`: SQLite path (default: `sqlite+aiosqlite:///./data/h2h.db`)
- `JWT_SECRET`: Secret for signing tokens
- `JWT_ALGORITHM`: HS256
- `ACCESS_TOKEN_EXPIRE_MINUTES`: Token TTL

Frontend requires (see `frontend/.env.example`):
- `VITE_API_URL`: Backend API URL (default: `http://localhost:8000`)
- `VITE_WS_URL`: WebSocket URL (default: `ws://localhost:8000`)

## Migration to Production Database

The codebase is designed for easy migration from SQLite to PostgreSQL:

1. Update `DATABASE_URL` to PostgreSQL connection string:
   ```python
   DATABASE_URL = "postgresql+asyncpg://user:pass@host:5432/h2h"
   ```

2. Update `requirements.txt`:
   - Remove: `aiosqlite`
   - Add: `asyncpg`

3. Run Alembic migrations against new database

4. No code changes needed - SQLAlchemy ORM abstracts database differences

## Testing Data

Run `python seed_data.py` to create test users:
- alice@example.com / password123
- bob@example.com / password123
- charlie@example.com / password123

Each starts with $1000 balance and sample bets in marketplace.

## MVP Scope

**In scope**: User auth, virtual wallet, bet creation/acceptance, basic settlement, WebSocket updates, responsive UI

**Out of scope** (future): Real payments, KYC/AML, blockchain, odds feeds, admin panel, email notifications, social features
