# TURBO

BTC 5-minute prediction markets on Monad. Gasless trading via EIP-712 signed orders, on-chain settlement, Pyth oracle resolution, USDC collateral.

## Architecture

```
┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│  Frontend    │────▶│  Backend     │────▶│  Turbo.sol   │
│  (React)     │◀────│  (FastAPI)   │     │  (Monad)     │
│  Telegram    │ WS  │  CLOB + API  │     │  EIP-712     │
│  Mini App    │     │  Relayer     │     │  Pyth        │
└──────────────┘     └──────┬───────┘     └──────────────┘
                            │
                     ┌──────▼───────┐
                     │  Pyth Oracle  │
                     │  BTC/USD SSE  │
                     └──────────────┘
```

## Core Components

### Smart Contract — `Turbo.sol`

Single contract handling everything:

- **Positions**: Internal YES/NO balances per market per user (1 YES + 1 NO = 1 USDC)
- **Split/Merge**: `split()` converts USDC → YES + NO tokens. `merge()` converts back.
- **EIP-712 Orderbook**: Off-chain signed orders, on-chain execution via `executeTrade()`
- **JIT Splitting**: If a seller lacks tokens, auto-splits their USDC during trade execution
- **Pyth Resolution**: `resolve()` settles markets using Pyth BTC/USD price after expiry
- **Redemption**: `redeem()` pays USDC to winning token holders (1 winning token = 1 USDC)
- **Fees**: 0% default. Owner can set up to 5% via `setFee()` to a designated `feeRecipient`
- **Gasless USDC Approval**: `approveUsdcWithPermit()` for EIP-2612 gasless approval

### Backend — `backend/`

| File | Purpose |
|------|---------|
| `main.py` | FastAPI server, WebSocket streaming, background loops, all API routes |
| `clob.py` | Central Limit Order Book engine with price-time priority matching |
| `relayer.py` | Submits transactions to Turbo.sol (createMarket, executeTrade, resolve) |
| `config.py` | Chain config, contract addresses, Pyth feeds |

### Frontend — `frontend/`

React + Vite + Tailwind Telegram mini app with:

- Live BTC price chart (Pyth SSE stream)
- YES/NO trade buttons with implied odds
- Kalshi-style unified orderbook (asks on top, bids below)
- Amount selector, position tracker, market history
- MetaMask wallet connect (auto-switches to Monad)

## MM API

Market makers interact with the CLOB via REST:

```bash
# Place a limit order (BUY YES at 55c, 100 shares)
curl -X POST http://localhost:8080/api/orders \
  -H "Content-Type: application/json" \
  -d '{"maker":"0xYOUR_WALLET","side":0,"outcome":0,"price":550000,"size":100000000,"signature":"","nonce":0,"expiration":0}'

# Amend an order (change price to 52c)
curl -X PUT http://localhost:8080/api/orders/ORDER_ID \
  -H "Content-Type: application/json" \
  -d '{"price":520000}'

# Cancel an order
curl -X DELETE http://localhost:8080/api/orders/ORDER_ID

# List resting orders for a wallet
curl http://localhost:8080/api/orders?maker=0xYOUR_WALLET
```

**Order fields:**
- `side`: 0 = BUY, 1 = SELL
- `outcome`: 0 = YES (UP), 1 = NO (DOWN)
- `price`: 6 decimals (500000 = 50c = 50% implied probability)
- `size`: 6 decimals (1000000 = 1 share = 1 USDC payout if wins)

## Gasless Flow

Users never pay gas:

1. User connects MetaMask → switches to Monad
2. Relayer submits `approveUsdcWithPermit()` (user signs EIP-2612, no gas)
3. User clicks YES/NO → signs EIP-712 order (no gas)
4. Backend matches order against CLOB → relayer calls `executeTrade()` on-chain
5. After 5 min, relayer calls `resolve()` with Pyth price
6. User calls `redeem()` → USDC sent to their wallet

## Deploy

```bash
# 1. Set up .env
cp .env.example .env
# Fill in: DEPLOYER_KEY, TURBO_RELAYER_KEY, TURBO_FEE_RECIPIENT

# 2. Deploy contract to Monad
cd contracts
source ../.env
forge script script/DeployTurbo.s.sol \
  --rpc-url $MONAD_RPC_URL \
  --broadcast \
  --private-key $DEPLOYER_KEY
# Copy TURBO_CONTRACT_ADDRESS into .env

# 3. Run backend
cd backend
pip install -r requirements.txt
python3 main.py

# 4. Run frontend
cd frontend
npm install
npm run dev        # dev: http://localhost:5173
npm run build      # prod: served by backend at :8080
```

## Costs

| Item | Cost |
|------|------|
| Contract deployment | ~0.01 MON |
| Market creation (every 5 min) | ~0.001 MON |
| Trade execution (per match) | ~0.002 MON |
| Resolution (per market) | ~0.002 MON |
| **Total/day** | **< 1 MON** |

## Config

| Env Var | Description |
|---------|-------------|
| `MONAD_RPC_URL` | Monad RPC endpoint |
| `DEPLOYER_KEY` | Private key for contract deployment |
| `TURBO_RELAYER_KEY` | Private key for relayer (pays gas) |
| `TURBO_FEE_RECIPIENT` | Wallet that receives fees |
| `TURBO_USDC_ADDRESS` | USDC on Monad (`0x754704Bc...`) |
| `TURBO_CONTRACT_ADDRESS` | Turbo contract (set after deploy) |

## Wallets

| Role | Address |
|------|---------|
| **Relayer / Deployer / Owner** | `0x4085b0eA2598aF729205bC982b2A3419593BE24d` |
| **Market Maker** | `0x4f020878617eb003311E596069980Fc7c23d97B6` |
| **Test Trader** | `0x7Bcb216158cC557b312857C29ab499B2271D6CB0` |

## Admin Functions

```
setFee(100)              # Set 1% fee (100 bps)
setFeeRecipient(addr)    # Change fee wallet
setRelayer(addr)         # Change relayer wallet
transferOwnership(addr)  # Transfer contract ownership
setPause(true)           # Emergency pause trading
```

## Deposit Gateway (Roadmap)

Turbo runs on USDC internally. The deposit gateway converts other assets to USDC on deposit, charging a fee per asset tier.

| Asset | Fee | Method | Priority |
|-------|-----|--------|----------|
| USDC/USDT | 0% | Direct deposit (live) | Done |
| Memecoins (Monad) | 5% | DEX router swap → USDC | 1 |
| Memecoins (EVM — ETH, Base, Arb) | 5% | DEX swap + bridge → USDC on Monad | 2 |
| Memecoins (SVM — Solana) | 5% | Jupiter swap → bridge → USDC on Monad | 3 |
| ETH, SOL, BTC | 2% | Bridge + swap → USDC | 4 |
| CS2 Skins | 15% | Skin marketplace API → sell → USDC | 5 |
| XMR | 2% | XMR node/swap service → USDC | 6 |

### Architecture

```
User deposits ANY asset
       ↓
Deposit Gateway (per asset type)
       ↓
Swap to USDC (DEX / bridge / marketplace)
       ↓
Keep fee % → fee wallet
       ↓
Credit USDC to user's Turbo balance
```

The Turbo contract stays USDC-only. The gateway handles all conversions before crediting.

## Future Markets (Roadmap)

- BTC 5MIN (live)
- ETH 5MIN
- SOL 5MIN
- Memecoin markets (custom pairs)
- Esports match outcomes
