System Architecture
Components
Frontend: Mouth Web App
- Framework: Next.js (App Router)
- Auth & Wallets: Privy SDK
- Styling: Tailwind CSS
- State management: React Query for server state
- Key pages:
/— Landing page + explore active bets/create— Create a new bet/bet/[id]— Bet detail page (view, accept, claim)/@[handle]— User profile page/leaderboard— Global leaderboard
Backend: Mouth API
- Runtime: Node.js
- Framework: Express or Hono
- Database: PostgreSQL (bet metadata, user profiles, X handles)
- Key responsibilities:
- User registration and X handle mapping
- Bet CRUD operations (off-chain metadata)
- Serve data to the web app (bet lists, profiles, leaderboard)
- Trigger smart contract interactions via server-side Privy wallets
X Bot Service
- Runtime: Node.js (standalone service)
- X API: v2 (filtered stream or polling for mentions)
- Key responsibilities:
- Monitor
@MouthBetmentions - Post bet links, notifications, and results
- Parse tweet context for pre-filling bet creation
- Monitor
Resolution Engine
- Runtime: Node.js (cron-based or event-driven)
- Key responsibilities:
- Monitor bets approaching expiration
- Fetch data from oracles for automatic resolution
- Queue manual resolutions for the Mouth team
- Submit resolution transactions to smart contracts
- Manage dispute windows
Event Indexer
- Options: Custom indexer, Envio, or The Graph subgraph
- Key responsibilities:
- Listen to on-chain events from bet contracts (BetCreated, BetAccepted, BetResolved, FundsClaimed)
- Update the database in real-time
- Ensure the web app reflects the latest on-chain state
Smart Contracts (Base)
- MouthBetFactory: Deploys individual bet contracts
- MouthBet: Individual bet escrow contract (holds USDC, enforces rules)
- Language: Solidity ^0.8.24
- USDC: Native USDC on Base (
0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)
Data Flow
Bet Creation
- User authenticates via Privy (X login → embedded wallet)
- User fills bet form on web app
- API stores off-chain metadata (description, tweet URL, category)
- API triggers Factory contract to deploy a new Bet contract
- User’s embedded wallet deposits USDC into the Bet contract
- Indexer picks up
BetCreatedevent, updates database - Bot posts on X (if applicable)
Bet Resolution
- Resolution Engine detects bet has reached expiration
- For auto-resolution: fetches oracle data, determines outcome
- For manual resolution: flags for Mouth team review
- Resolution is submitted to the Bet contract via
resolve() - If disputeable: 48-hour dispute window starts →
finalize()after window expires - If non-disputeable: bet is immediately finalized
- Indexer picks up
Resolved/Finalizedevents - Bot posts result on X
- For non-disputeable PvP 1v1: backend calls
resolverClaim()to distribute funds automatically - For disputeable / Open PvP: winner claims via web app → USDC sent to embedded wallet