This commit is contained in:
2026-01-02 10:43:20 -06:00
commit 14d9af3036
112 changed files with 14274 additions and 0 deletions

216
CLAUDE.md Normal file
View File

@ -0,0 +1,216 @@
# 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