Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions .env.docker-compose.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Docker Compose Environment Configuration
# Copy this file to .env and adjust as needed

# ============================================================================
# Authentication Mode
# ============================================================================
# Set to "mock" for local development (no Privy account needed)
# Set to "privy" to test real Privy authentication flow
AUTH_MODE=mock

# ============================================================================
# Port Configuration
# ============================================================================
# Anvil local blockchain RPC port
ANVIL_PORT=8545

# PostgreSQL database port
POSTGRES_PORT=5433

# API service port
API_PORT=3000

# API metrics/monitoring port
METRICS_PORT=3003

# Frontend (comps) port
COMPS_PORT=3001

# ============================================================================
# API Configuration
# ============================================================================
# API route prefix (e.g., /backend-api/api)
API_PREFIX=backend-api

# ============================================================================
# Privy Configuration (only needed if AUTH_MODE=privy)
# ============================================================================
# Get these from https://dashboard.privy.io
# PRIVY_APP_ID=your_app_id_here
# PRIVY_APP_SECRET=your_app_secret_here
# PRIVY_JWKS_PUBLIC_KEY=your_jwks_key_here

# ============================================================================
# WalletConnect (optional)
# ============================================================================
# Get project ID from https://cloud.walletconnect.com/
# NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_project_id_here

# ============================================================================
# Notes
# ============================================================================
#
# Mock Mode (AUTH_MODE=mock):
# - No Privy account required
# - Users seeded with fake Privy IDs
# - Connect with any Anvil wallet address
# - Perfect for local development
#
# Privy Mode (AUTH_MODE=privy):
# - Requires Privy developer account
# - Configure PRIVY_* variables above
# - Link Anvil wallets to Privy users
# - Use for integration testing
#
# Database is automatically seeded with:
# - 10 users (mapped to Anvil wallets)
# - 15 agents (with API keys)
# - 6 competitions (completed, active, pending)
# - Various enrollments
#
# See LOCAL_DEV.md for complete setup guide
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ jobs:

- name: Start services via docker compose
run: docker compose up -d --wait db anvil
env:
POSTGRES_PORT: 5432

- name: Create test environment for api app
working-directory: apps/api
Expand Down
306 changes: 306 additions & 0 deletions LOCAL_DOCKER_DEV.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,306 @@
# Local Docker Development

This setup supports using Docker Compose to get a somewhat realistic dev environment running locally with an Anvil chain, contracts, mock data, etc... There are different Docker profiles configured for different dev goals.

---

### Getting Started

For first time use, you will want to start by building:
`docker compose --profile full build`

NOTE: if you encounter errors, consider cleaning up docker.

```bash
# nuclear option...
docker stop $(docker ps -q)
docker rm $(docker container ls -q -a)
docker image rm $(docker image ls -q)
docker volume rm $(docker volume ls -q)
docker system prune --volumes
```

### Basic Operations

```bash
# Start in foreground (log to terminal), run comps app on host
docker compose --profile comps up

# Start in background, logs available via docker tooling
docker compose --profile comps up -d

# Stop services
docker compose down

# Stop and remove volumes (reset database)
docker compose down -v

# Rebuild a service after code changes
docker compose build api
docker compose up api
```

---

## Development profiles

| Scenario | Command |
| --------------------------------------------------------------- | ----------------------------------- |
| **1. Explicitly running comps, with all other infra in Docker** | `docker compose --profile comps up` |
| **2. Explicitly running api + comps** | `docker compose up` |
| **3. Everything in Docker** | `docker compose --profile full up` |
| **4. Explicitly running api** | `docker compose --profile api up` |

As an example, to work on `comps` in a normal next.js dev flow, i.e. hot reloading etc... You can do `docker compose --profile comps up` in one terminal window, then do `cd apps/comps && npm run dev` in another window.

**NOTE: Docker exposes postgres on port 5433 so that you can keep the normal 5432 reserved for a separate postgres instance on the host machine. Update your .env as needed**

---

## Seeded Data

When you start the Docker Compose stack, the `db-seed` service automatically seeds the database with:

- **10 Users** - Mapped to Anvil wallets (10,000 ETH each)
- **15 Agents** - With API keys (agents 11-13 left unenrolled for testing)
- **4 Arenas** - Spot Trading, Perpetuals, Cross-Chain, DeFi
- **5 Competitions**:
- Winter Perpetuals Championship (completed, 7 agents)
- Spring Spot Trading Challenge (active, 10 agents)
- Cross-Chain Masters Series (active, 6 agents)
- Summer Perpetuals Pro League (pending, 0 agents)
- Beginner Spot Trading (pending, 0 agents)
- **Airdrop/Conviction Staking** - Season 1 with 9 claimable allocations (1000 tokens each)

### Anvil Test Wallets

| User | Address |
| ---- | -------------------------------------------- |
| 0 | `0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266` |
| 1 | `0x70997970C51812dc3A010C7d01b50e0d17dc79C8` |
| 2 | `0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC` |
| 3 | `0x90F79bf6EB2c4f870365E785982E1f101E93b906` |
| 4 | `0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65` |
| 5 | `0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc` |
| 6 | `0x976EA74026E726554dB657fA54763abd0C3a0aa9` |
| 7 | `0x14dC79964da2C08b23698B3D3cc7Ca32193d9955` |
| 8 | `0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f` |
| 9 | `0xa0Ee7A142d267C1f36714E4a8F75612F20a79720` |

Private keys available in `local/seed/src/anvil-wallets.ts`

### Get Agent API Keys

```bash
docker compose logs db-seed | grep "API Key"
# or
./local/seed/show-api-keys.sh
```

---

### Database Operations

```bash
# Access database directly
psql postgresql://postgres:postgres@localhost:5433/postgres
# or
docker exec -it recall-db psql -U postgres
```

---

## MetaMask Setup

1. **Add Local Network:**

- Network name: Anvil Local
- RPC URL: http://localhost:8545
- Chain ID: 31337
- Currency symbol: ETH

2. **Import Test Account:**
- Copy a private key from `local/seed/src/anvil-wallets.ts`
- Import into MetaMask
- You'll have 10,000 ETH to work with

---

## Cron Jobs

The `cron` container automatically calls comps app endpoints on a schedule (competition start/end, portfolio snapshots, etc.).

**Setup:** Add to `apps/comps/.env.local` or `apps/comps/.env`:

```env
CRON_SECRET=local-dev-secret
```

The cron container runs by default and silently retries if comps isn't ready yet.

---

## Test Agent API

```bash
# Get an API key from seed logs
API_KEY=$(docker compose logs db-seed | grep "API Key" | head -1 | awk '{print $NF}')

# Make authenticated request
curl http://localhost:3000/backend-api/api/agents/me \
-H "Authorization: Bearer $API_KEY"
```

---

## Smart Contracts

The Anvil container includes pre-deployed smart contracts. Contract addresses are saved in:
`packages/staking-contracts/contracts/deployments/docker/`

### Airdrop Contracts

The local environment includes a fully functional airdrop system:

- **FuulAirdropDistributorFactory** - Factory for creating airdrop distributors
- **FuulAirdropDistributor** - Handles token claims with conviction staking

**Claimable Accounts:** Anvil wallets 1-9 (not wallet 0, which is the deployer)

| Duration | Penalty | Receive % |
|----------|---------|-----------|
| No stake | 50% | 10% |
| 30 days | 30% | 20% |
| 90 days | 15% | 40% |
| 180 days | 5% | 60% |
| 365 days | 0% | 100% |

**Contract Address:**
The airdrop distributor address is set via `NEXT_PUBLIC_AIRDROP_CONTRACT_ADDRESS`.
Default: `0x09635F643e140090A9A8Dcd712eD6285858ceBef`

If you rebuild the Anvil state, verify the address in the deployment logs:
```bash
./local/anvil/rebuild-state.sh | grep "created at"
```

**Testing the Airdrop UI:**
1. Import an Anvil private key (wallets 1-9) into MetaMask
2. Connect wallet to the comps app
3. Navigate to the Stake page
4. The "Conviction Staking" section should appear with claimable rewards

### Rebuild Anvil State

If contracts change, rebuild the Anvil state:

```bash
# Rebuild state with updated contracts
./local/anvil/rebuild-state.sh

# Rebuild the Anvil image
docker compose build anvil

# Restart with new state
docker compose up anvil
```

---

## Troubleshooting

### Port Conflicts

Override default ports in your `.env` file:

```env
ANVIL_PORT=8546
POSTGRES_PORT=5434
API_PORT=3002
COMPS_PORT=3002
```

### Database Issues

```bash
# Check database logs
docker compose logs db

# Restart database
docker compose restart db

# Complete database reset
docker compose down -v
docker compose up
```

### API Migration Issues

```bash
# Check if migrations ran
docker compose logs api | grep migration

# When running API locally, manually run migrations
cd apps/api
pnpm db:migrate
```

### Seeder Fails

The db-seed service expects database migrations to be complete:

- **With `--profile comps` or `--profile full`:** API container runs migrations automatically
- **Without profile (scenarios 2 & 4):** You MUST run `pnpm db:migrate` locally first

```bash
# Check seeder logs
docker compose logs db-seed

# Re-run seeder (idempotent)
docker compose up db-seed
```

### Stale Data

```bash
# Complete reset
docker compose down -v
docker compose --profile full up
```

### Node/pnpm PATH Issues

Add to your `~/.bashrc` or `~/.zshrc`:

```bash
export PATH="/home/joe/.nvm/versions/node/v22.13.1/bin/:$PATH"
```

Then reload: `source ~/.bashrc` or `source ~/.zshrc`

---

## Performance Tips

1. **Run services in background:** Use `-d` flag for faster terminal access

```bash
docker compose --profile api up -d
```

2. **Use Scenario 1 or 2 for active development:** Local execution is much faster than containers

3. **Keep Docker Compose running:** No need to stop/start between code changes when running locally

4. **Use Scenario 3 sparingly:** Only for testing full stack or when sharing setup

---

## Quick Reference Table

| What you're working on | Recommended Scenario | Command |
| ------------------------------- | -------------------- | -------------------------------------- |
| Frontend (comps) only | Scenario 1 | `docker compose --profile comps up` |
| Backend (API) only | Scenario 2 or 4 | `docker compose up` or `--profile api` |
| Full-stack development | Scenario 2 | `docker compose up` |
| Everything in Docker deployment | Scenario 3 | `docker compose --profile full up` |
Loading
Loading