System architecture


┌─────────────────────────────────────────────────────────────────┐
│                         Loop client                             │
│              Next.js 16 · React 19 · wagmi · viem               │
└────────────┬───────────────────────────────┬────────────────────┘
             │                               │
    ┌────────▼────────┐             ┌────────▼────────┐
    │  Market & news  │             │  Arc Testnet    │
    │  data providers │             │  (chain 5042002)│
    └────────┬────────┘             └────────┬────────┘
             │                               │
   SoSoValue · Finnhub              StockVault.sol
   CryptoPanic · RSS                 PerpEngine.sol
             │                               │
             └──────── optional ────────────┘
                        Neon Postgres
              (perp mark history · closed trades)

Layers

LayerRole
ClientReact pages, wagmi wallet connection
APINext.js route handlers for market data, perp quotes, oracle sync, news
Servicessrc/lib: caching, SoSoValue client, perp mark engine, news sync, portfolio
PersistenceIn-memory and file caches; optional Neon for perp history
Chainviem with RPC timeouts; user txs via wallet; server txs via PRIVATE_KEY

Stack

Next.js 16 (App Router), React 19, Tailwind CSS 4, wagmi 3, viem 2, TanStack Query. Contracts in contracts/ (Solidity 0.8.24, Foundry). App code in web/src/ (app/, components/, hooks/, lib/).

Runtime behavior

Cache-first APIs return warm data and refresh in the background. A Neon circuit breaker prevents database timeouts from blocking requests. Market cold start prefetches the full catalog in parallel (~8–12s on Vercel). Arc RPC calls use explicit timeouts.