Architecture Overview
AGON is a Turborepo monorepo with four layers — web, workers, contracts, and shared types.
AGON is a Turborepo monorepo with four layers:
| Package | Description |
|---|---|
apps/web | Next.js 16 (App Router) + React 19 + TailwindCSS 4. Server Components by default with Client islands for interactivity. |
apps/workers | Python FastAPI backend. AI oracle (multi-LLM), market indexer, liquidation bot, WebSocket/SSE feeds. |
packages/contracts | Solidity smart contracts built with Foundry. MarketFactory, ConditionalTokens (ERC-1155 + CPMM), AIOracleHub. |
packages/shared | Shared TypeScript types and ABIs consumed by both the web app and any external SDK consumers. |
Data flow
+-----------+
| User |
| Wallet |
+-----+-----+
|
+-------------+-------------+
| |
v v
+-------+--------+ +---------+--------+
| Web App | | Direct Contract |
| (Next.js 16) | | Call via wagmi |
+-------+--------+ +---------+--------+
| |
v |
+-------+--------+ |
| REST API | |
| (FastAPI | |
| on Fly.io) | |
+-------+--------+ |
| |
+-------------+-------------+
|
v
+-------+--------+
| Base RPC |
+-------+--------+
|
v
+-----------------+------------------+
| Smart Contracts |
| MarketFactory ConditionalTokens |
| AIOracleHub OracleDAO |
+-----------------+------------------+
Parallel: AI Oracle workers (Python)
+-----------+ +----------------+ +------------------+
| Analyst | --> | Concordance | --> | AIOracleHub.sol |
| (15-min | | (3-4 LLMs | | (on-chain |
| loop) | | fan-out) | | resolution) |
+-----------+ +----------------+ +------------------+There are two primary paths for user interactions. First, the web app renders Server Components that read from the database and call the FastAPI REST API for oracle data, signals, and trade estimates. Second, on-chain writes (buying/selling tokens, adding liquidity) go directly from the browser to Base via wagmi and viem -- the web backend never touches private keys for user trades.
Per-layer tech stack
apps/web
| Component | Version | Role |
|---|---|---|
| Next.js | 16.2.3 | App Router, Server Components, API routes |
| React | 19.2.4 | UI rendering with Server Component defaults |
| TailwindCSS | 4.x | Utility-first styling |
| next-intl | 4.x | Internationalization (en, fr, es, de, ja, ko, zh, pt, ru, tr) |
| iron-session | 8.x | Encrypted cookie sessions for wallet auth |
| viem | 2.x | Low-level EVM interaction (ABI encoding, hashing) |
| wagmi | 2.x | React hooks for wallet connection, contract reads/writes |
| Prisma Client | 7.x | Type-safe database access (schema is source of truth) |
| fumadocs | 16.x | Documentation site framework (this site) |
apps/workers
| Component | Role |
|---|---|
| Python 3.12+ | Runtime |
| FastAPI | REST API server + WebSocket/SSE feeds |
| asyncpg | Async PostgreSQL driver (raw queries, no ORM at runtime) |
| Anthropic SDK (AsyncAnthropic) | Claude Haiku calls for AI analyst |
| google-genai | Gemini 2.0 Flash for concordance + crypto analysis |
| OpenAI SDK (AsyncOpenAI) | GPT-4o for concordance voting |
| web3.py (AsyncWeb3) | On-chain reads/writes (resolution, indexing) |
| pydantic-settings | Typed configuration from environment variables |
| structlog | JSON-formatted structured logging |
packages/contracts
| Component | Role |
|---|---|
| Solidity 0.8.24 | Smart contract language |
| Foundry (forge) | Build, test, deploy toolchain |
| OpenZeppelin 5.x | ERC-1155, ERC-20, Ownable, ReentrancyGuard, Pausable, EIP-712 |
packages/shared
TypeScript-only package. Exports contract ABIs (generated from Foundry
artifacts), type definitions for market structures, and utility constants
shared between apps/web and external SDK consumers.
Database layer
| Store | Technology | Purpose |
|---|---|---|
| Primary | PostgreSQL via Prisma 7 | Markets, trades, users, analytics, signals, validator submissions |
| Cache / Pub-Sub | Upstash Redis | SSE event bus, x402 entitlement cache, session data |
The Prisma schema in apps/web/prisma/schema.prisma is the source of
truth for the database structure. The Python workers connect to the same
PostgreSQL instance using raw asyncpg queries -- there is no ORM on the
Python side. Both layers read and write the same tables.
Event indexer
The apps/workers/indexer/indexer.py module runs a continuous polling
loop against the Base RPC. It watches for on-chain events emitted by
MarketFactory, ConditionalTokens, MarketArena, Parlay, PricePool,
TeamBattle, FootballDuel, and TradingMarket contracts. Each event type
dispatches to a dedicated async handler that materializes the event into
PostgreSQL rows (markets, trades, resolutions, liquidity changes).
The indexer persists a block checkpoint per contract so it can resume
from the last processed block after a restart. The poll interval
defaults to 5 seconds (indexer_poll_interval in config).
