Forged in the markets. A decentralized YES/NO prediction-market platform on Arc Testnet, trading USDC through a constant-product AMM with an AMM + on-chain CLOB limit orders, resolved trustlessly by UMA's Optimistic Oracle V2.
Built as a Bun-first monorepo: Vite + React frontend, Bun/Hono backend, Hardhat contracts, USDC collateral, an AMM, an on-chain CLOB, a portfolio page, dual-wallet support, and a mobile PWA.
- USDC collateral — trades settle in Arc Testnet's native USDC ERC-20 (system address
0x3600000000000000000000000000000000000000, 6 decimals), not a mintable test token. - AMM + CLOB limit orders — continuous trading via a constant-product AMM (2% fee), an AMM depth ladder derived from real pool reserves, and escrowed on-chain CLOB limit orders.
- Trustless resolution — UMA Optimistic Oracle V2 (
propose → dispute → settle). The deploy script bootstraps the whole UMA stack on-chain (Finder, whitelists, Store, MockOracle, OO V2). - Dual wallet — MetaMask (injected) or Circle Passkey (WebAuthn smart account, gasless via
paymaster). Every transaction is forced onto Arc Testnet (chain
5042002) so nothing can hit mainnet by accident. - Portfolio, charts, PWA —
/portfolioaggregates positions across live markets; live price charts (lightweight-charts) + per-card sparklines; installable mobile PWA in the brutalist Predict-Edge visual identity. - Multi-market — a base live BTC market + user-created on-chain markets + a categorized grid of demo markets; anyone can create new on-chain markets from the UI.
| Layer | Stack |
|---|---|
Frontend (app/) |
Vite 5 + React 18 (SWC) + Tailwind 3 + shadcn/ui + PWA; wagmi/viem, @tanstack/react-query, react-router, zustand, lightweight-charts; feature-sliced src/{app,features,shared,styles}; Bun |
Backend (server/) |
Hono on Bun (Bun.serve + OpenAPIHono), ethers v6, pino, zod, neverthrow, Scalar API docs |
Contracts (contracts/ + scripts/) |
Solidity 0.8.17 + Hardhat + OpenZeppelin 4.9 + UMA @uma/core; market + AMM + CLOB |
| Tooling | Bun, ESLint 9 flat + Prettier, Docker + nginx |
Architecture decisions are documented in docs/ — see
ADR-001 (core architecture),
ADR-002 (Bun/Vite runtime split), and
tech-stack.md.
predict-edge/
├── app/ # Vite + React frontend (feature-sliced, Bun, PWA)
│ └── src/
│ ├── app/ # shell: main.tsx, App.tsx (routes), Layout, providers
│ ├── features/
│ │ ├── markets/ # market grid, detail, create, chart, sparkline, catalog
│ │ ├── trading/ # AMM trade, CLOB order book, trade history, oracle (resolve)
│ │ ├── portfolio/ # /portfolio aggregation
│ │ └── wallet/ # dual-wallet (MetaMask + Circle Passkey), chain guard
│ └── shared/{ui,lib} # shadcn primitives + utils, contracts (abis/addresses), chain
├── server/ # Hono-on-Bun backend
│ └── src/{index.ts, app.ts, core/, modules/markets}
├── contracts/ # EventBasedPredictionMarket.sol, PredictionMarketAMM.sol, OnChainLimitOrderBook.sol
├── scripts/ # deploy.ts, verify-deploy.ts, generate-wallet.ts, sync-env.ts, reset-markets.ts
├── data/ # markets.json (user-created market metadata)
└── docs/ # ADRs, architecture diagram, contract map, deployment plan, risks, addresses
- Bun 1.3+ — runs the frontend and backend.
- Node.js v18+ — used by Hardhat for the contracts/deploy tooling.
- A wallet — MetaMask (or any injected EVM wallet) on Arc Testnet (chain
5042002), or a Circle Passkey wallet (needs a Circle developer client key/URL). - Arc Testnet USDC — pays for gas and is the trading collateral. Get it from the Circle faucet. (USDC is native on Arc; the ERC-20 balance is the same balance as native gas.)
# 1. Clone
git clone https://github.com/Kirashchuk/Predict-Edge.git
cd Predict-Edge
# 2. Install
bun install # root — Hardhat / contracts tooling
cd app && bun install && cd ..
cd server && bun install && cd ..
# 3. Deployer wallet + env (testnet only — never a mainnet key)
bun run generate-wallet # writes PRIVATE_KEY to .env.local
# → fund the printed address with USDC from https://faucet.circle.com/
# 4. Compile + deploy contracts to Arc Testnet
bun run compile
bun run deploy # bootstraps UMA + market + AMM + CLOB (USDC collateral), writes addresses
bun run sync-env # propagates addresses to app/.env.local (VITE_*)
# 5. Run (two terminals)
cd server && bun run dev # Hono API → http://localhost:8787 (/docs)
cd app && bun run dev # Vite app → http://localhost:5173
# Optional: auto-match crossed CLOB orders
bun run keeperThe frontend dev server proxies /v1/* to the backend.
- Trading —
PredictionMarketAMMis a constant-product (x*y=k) pool with a 2% fee.buyYes/buyNomint a YES+NO pair from collateral and swap the unwanted leg;sellYes/sellNoswap and redeem. YES price =reserveNo / (reserveYes + reserveNo)(reads as probability). - AMM depth — the depth ladder is computed from the live pool reserves using the exact contract math, so it reflects real on-chain liquidity (the price you'd get at increasing size).
- Limit orders — placed on-chain in
OnChainLimitOrderBook. Buy orders escrow USDC; sell orders escrow YES/NO tokens; orders can be cancelled, directly filled, or matched when crossed. - Resolution — UMA OO V2 in event-based mode. Anyone can
proposePrice(1e18=YES,0=NO,5e17=Undetermined) with a bond; after the liveness window anyone cansettle(permissionless). On testnet a TestableTimerlets settle advance past liveness without waiting. Disputes escalate to the (mock) DVM. - Redeem — after settlement,
settle(longTokens, shortTokens)burns positions for USDC by the resolved outcome.
Secrets live in .env.local (git-ignored); only .env.example templates are committed.
| File | Purpose |
|---|---|
root .env.local |
PRIVATE_KEY (deployer), DEPLOY_RPC_URL, and DEPLOY_* addresses (written by bun run deploy). The backend reuses this file. |
app/.env.local |
VITE_* addresses (written by bun run sync-env) + optional VITE_CIRCLE_CLIENT_KEY/URL for the Passkey wallet. |
Collateral is the fixed Arc USDC system address 0x3600…0000 (6 decimals) — configured by default,
no need to set it manually.
| Command | What it does |
|---|---|
bun run compile |
Compile the Solidity contracts (Hardhat) |
bun run deploy |
Deploy UMA stack + market + AMM + CLOB (USDC) to Arc Testnet |
bun run deploy:clob |
Deploy only a CLOB for the current DEPLOY_MARKET_ADDRESS |
bun run verify-deploy |
Read back on-chain state (reserves, prices, balances) |
bun run memo:payment |
Send a small USDC transfer through Arc's Memo contract and verify memo logs |
bun run sync-env |
Copy deployed addresses into app/.env.local as VITE_* |
bun run keeper |
Scan configured CLOBs and auto-match crossed bid/ask orders |
bun run generate-wallet |
Generate a fresh local deployer wallet |
bun run reset |
Clear user-created markets from data/markets.json |
cd app && bun run dev |
Vite frontend (:5173) |
cd server && bun run dev |
Hono backend (:8787, Scalar docs at /docs) |
GET /v1/markets·POST /v1/markets— list / create on-chain markets.GET /health·GET /docs·GET /openapi.json.
Current Arc Testnet addresses (USDC collateral) are tracked in
docs/deployed-addresses.md.
Testnet only — see docs/risks-and-security.md. Notable testnet
trade-offs: a Mock DVM substitutes for UMA's real DVM, the create-market API signs with a server-held
deployer key, and the Testable Timer makes liveness instant. Do not use a mainnet key or real
funds. The prediction-market/CLOB contracts are AGPL-3.0-only; the rest is Apache-2.0.