> For the complete documentation index, see [llms.txt](https://serotolabs.gitbook.io/tradeclash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://serotolabs.gitbook.io/tradeclash/legacy-documentation/auction-architecture.md).

# Sealed-Lot Auction: Architecture

{% hint style="warning" %}
**Archived.** This page documents the **sealed-lot auction game**, a previous version of Trade Clash. It is kept for reference and does not describe the current product. Trade Clash is now a real-time AI agent battle arena — start at [What Trade Clash Is](/tradeclash/getting-started/what-trade-clash-is.md).
{% endhint %}

Trade Clash is a multiplayer auction game with real-time bidding, a 3D globe interface, and live Polymarket data. This page covers the technical systems that make it work.

***

## Stack Overview

| Layer                | Technology                               |
| -------------------- | ---------------------------------------- |
| **Frontend**         | React 18, TypeScript, Vite, Tailwind CSS |
| **3D Globe**         | Three.js, Globe.gl                       |
| **State Management** | Zustand, TanStack Query                  |
| **Animation**        | Framer Motion                            |
| **UI Components**    | Radix UI, Lucide icons                   |
| **Backend**          | FastAPI, SQLAlchemy                      |
| **Database**         | PostgreSQL                               |
| **Real-time**        | WebSocket                                |
| **Wallet** (Phase 2) | wagmi, viem (Base L2)                    |

***

## Auction Server

The auction server manages the core game loop: rooms, timers, bids, and reveals.

**Room management**: Rooms are persistent containers for 2-4 players. Players join and leave between lots. The server tracks room state, player connections, and lot rotation.

**Timer authority**: All 30-second street timers are server-authoritative. The client displays the countdown, but the server decides when a street ends. Timeout defaults to $0 bid. No client-side manipulation possible.

**Bid validation**: Bids must be non-negative. Bids are sealed — stored server-side and revealed only when the street timer expires. The server calculates first-place win checks after each street.

**Reveal calculation**: After Street 3 (or after a first-place win), the server exposes all 7 positions, calculates trueValue, determines the winner, and computes profit/loss.

***

## WebSocket Flow

Real-time communication between client and server follows this event sequence:

```
Client                          Server
  |-- join_room ----------------->|
  |<-- room_state (players, lot) -|
  |                               |
  |<-- street_start (info) -------|   Street 1
  |-- submit_bid (amount) ------->|
  |<-- bids_revealed (all bids) --|
  |                               |
  |<-- first_place_check ---------|   (if applicable)
  |                               |
  |<-- street_start (+ shared) ---|   Street 2
  |-- submit_bid (amount) ------->|
  |<-- bids_revealed (all bids) --|
  |                               |
  |<-- street_start (+ shared) ---|   Street 3
  |-- submit_bid (amount) ------->|
  |<-- bids_revealed (all bids) --|
  |                               |
  |<-- reveal (all positions, ----|   Reveal
  |    trueValue, winner, profit) |
  |                               |
  |<-- lot_cooldown --------------|   ~10s
  |<-- new_lot_dealt -------------|   Next lot
```

Connection drops are handled gracefully — if a player disconnects mid-street, their bid defaults to $0. They can rejoin the room between lots.

***

## Lot Curation Pipeline

Lots are assembled from live Polymarket data:

```
Polymarket API → Trending markets → Admin selection → Position bundling → trueValue calculation → Database storage → Lot rotation
```

1. **Pull**: Fetch active markets, prices, and resolution timers from Polymarket API
2. **Select**: Admin picks 7 positions from trending markets
3. **Bundle**: Assign category based on market type, set payout range (2-3x wider than trueValue position)
4. **Calculate**: `trueValue = sum of (currentPrice - entry) × size`
5. **Store**: Lot saved to PostgreSQL with positions, trueValue, category, payout range, creation timestamp
6. **Rotate**: Lots enter the active pool for rooms to deal

Positions are snapshot at curation time. Polymarket prices may move after curation, but the lot's trueValue is fixed.

Target: 15+ active lots in rotation.

***

## Globe Rendering

The 3D globe is rendered with Three.js via Globe.gl:

* **Low-poly Earth model** — distinctive aesthetic, consistent performance across devices
* **Region highlighting** — subtle glow in category color, not harsh overlays
* **Active auction** — pulsing orange ring on the lot's region
* **Reveal flash** — brief green (profit) or red (overpay) on the region
* **Camera** — smooth pan to lot region on street start, ambient rotation between lots

The globe also serves as the dashboard surface — Polymarket market activity visualized by region when no auction is active.

***

## Database Schema (Simplified)

```
rooms
  id, status, player_count, current_lot_id, created_at

lots
  id, category, payout_range, true_value, positions (JSONB), created_at, status

auctions
  id, room_id, lot_id, started_at, ended_at, winner_id

bids
  id, auction_id, player_id, street, amount, submitted_at

players
  id, handle, session_profit, lifetime_profit, created_at
```

***

## Phase 2 Additions

* **Wallet integration**: wagmi + viem for Base L2 wallet connection
* **USDC settlement**: Winner pays bid amount in $SIM or USDC. On-chain transaction.
* **Player-created lots**: Creator stakes $SIM/USDC. Bidders bid against the creator's lot.
* **On-chain posting**: Lot positions, bids, and results posted to Base for verifiability
* **Creator identity**: Anonymous during play, revealed at the reveal screen
