> 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/technical/architecture.md).

# System Architecture

Trade Clash is two layers with a deliberate boundary between them.

```
┌─────────────────────────────────────────────────────────────────────┐
│  ENGINE HOST  (GPL, open)                                           │
│  A real-time strategy engine compiled to WebAssembly and run in the  │
│  browser, plus the orchestrator that runs the shared live match.     │
│                                                                      │
│  Exposes a Spectator API: match state, camera commands, and console  │
│  markers for seed / start / result.                                  │
└─────────────────────────────────────────────────────────────────────┘
              ▲  raw telemetry out            dumb commands in  │
              │                                                  ▼
┌─────────────────────────────────────────────────────────────────────┐
│  PRESENTATION + MARKET LAYER  (closed)                              │
│  Broadcast direction, caster, HUD, plans overlay, win probability,   │
│  the market service, wallet, and NFT minting.                        │
└─────────────────────────────────────────────────────────────────────┘
```

## Why the boundary is strict

The engine layer must work perfectly well on its own. The presentation layer attaches to it through a documented spectator interface and nothing else — no edits to engine internals, no assumptions that the overlay is present. If the presentation layer is missing, the engine still runs; every hook into its DOM is guarded so a missing element degrades to nothing rather than throwing.

This is a licensing boundary as much as an engineering one. The engine layer is GPL and open. The editorial and commercial layer is separate and closed.

## The live match

One shared match is the broadcast. It works like this:

1. The **orchestrator** runs the shared match and publishes its state, including the current match ID
2. Viewers boot the engine host in a render-only spectator mode
3. The presentation layer polls the orchestrator for the live match, then subscribes to the market service over a websocket
4. Every pushed update is a **full snapshot** of the market view — a reconnect is a re-subscribe, with no delta bookkeeping to desynchronise
5. Predictions go over an authenticated HTTP endpoint with a per-intent idempotency key

## The market service

A minimal API plus a websocket hub. It owns the price, the clock, the result, and settlement. Its design rule is short: **the server decides money; clients send intents and render pushed state.**

Authentication is real server-side Sign-In with Ethereum — request a nonce, sign it, exchange the signature for a session, then carry a bearer token.

## Building an agent

The Forge compiles five dials plus standing orders into a personality file of roughly ninety engine parameters. That file is posted to the orchestrator, which compiles it into the engine's own rules, and then queued into the live rotation.

The same compiler runs in the browser and on the server, from one source file, so the configuration a player previews is exactly the configuration that fights.

## Failure behaviour

Every optional service — voice, chat, anchoring, analytics — is called inside a try/catch that fails silently. A dead side service degrades a feature, never the broadcast.
