MonGambit is a Monad chess challenge: deposit 1 MON, face authoritative
maximum-skill Stockfish at 5+1, and receive 10 MON total for a verified win.
The current target is a Docker-local application using contracts deployed to
Monad testnet (10143). It is not approved for mainnet funds.
See PROJECT.md for the roadmap and docs/PROTOCOL.md for the locked testnet state machine, economics, oracle trust, key roles, clocks, and failure behavior.
contracts/MonGambit.sol: non-upgradeable native-MON escrow, hard prize reservations, EIP-712 settlement, expiry, forfeit, pause, and protected credits.server/: Fastify/PostgreSQL service that authenticates wallets, verifies finalized entries, owns chess state and clocks, runs native Stockfish, signs results, and relays settlement.app/: React/Next arena connected through wagmi and viem to an injected EVM wallet and the authoritative API. Vercel uses a same-origin/api/gameproxy.docker-compose.yml: local PostgreSQL, game API, and an optional Cloudflare Tunnel profile.
- Node.js 22.13 or newer
- Docker with Compose
- an injected EVM wallet with Monad testnet MON
- separate deployer/admin, result-signer, and relayer roles
Never paste a private key into the UI, source files, logs, or chat. All .env
files are ignored. Copy .env.example to .env and populate it only locally.
npm install
npm run contract:test
npm run server:build
npm run build
npm test- Run
npm run roles:generateto create.env.roleswith separate testnet-only signer and relayer wallets. It refuses to overwrite existing keys and never prints private keys. Fund only the relayer with a small gas balance. - Put the deployer key and signer/relayer public addresses in
.env. - Run
npm run contract:deploy:testnet. The script seeds 20 test MON by default and writesdeployments/10143.json. - Copy the deployed address into
MONAD_CONTRACT_ADDRESSandNEXT_PUBLIC_MONAD_CONTRACT_ADDRESS. - Put the signer and relayer private keys in
.env, then rundocker compose up --build. - Run
npm run dev, connect an injected wallet, sign the authentication message, and enter a challenge.
Set ALLOW_TEST_OUTCOMES=true only for a local deterministic settlement run.
The API port is bound to loopback by Compose.
Stockfish remains at Skill Level 20, with a clock-aware response budget capped
at 1.5 seconds by default. Set STOCKFISH_MOVE_CAP_MS locally to tune the cap
without rebuilding the frontend.
The production request path is:
wallet browser -> https://your-app.vercel.app/api/game/*
-> Vercel server-side proxy
-> https://api.your-domain.example
-> Cloudflare Tunnel -> game-api:8788
This keeps the session cookie on the Vercel site and keeps the API port closed to inbound Internet traffic. The Mac, Docker Desktop, the API containers, and the tunnel must remain online while people play.
-
Add a domain to Cloudflare, then create a named Cloudflare Tunnel in the Zero Trust dashboard.
-
Add a public hostname such as
api.example.com. Set its service URL tohttp://game-api:8788becausecloudflaredruns on the Compose network. -
Copy only the tunnel token into the local
.envasCLOUDFLARE_TUNNEL_TOKEN. Never commit it. -
Generate an unrelated proxy secret with
openssl rand -hex 32. Put that value in local.envasGAME_API_PROXY_SECRET; it is not an EVM key. -
Set
FRONTEND_ORIGIN=https://your-app.vercel.app,SESSION_COOKIE_SECURE=true, andALLOW_TEST_OUTCOMES=falsein local.env. -
Start the backend and tunnel:
docker compose --profile tunnel up -d --build docker compose ps
Use docker compose --profile tunnel down to stop this complete local stack.
The ordinary docker compose up -d --build command still starts only PostgreSQL
and the API.
The repository currently ignores .env, .env.roles, .vercel, build output,
and contract artifacts. Before making it public, verify git status and commit
only the source and .env.example; no deployer, signer, relayer, tunnel, or
proxy secret belongs in GitHub.
Create a public GitHub repository, add it as origin, and push main. Import
that repository in Vercel. vercel.json selects the native Next.js build.
Set these Vercel environment variables for Production and Preview:
NEXT_PUBLIC_MONAD_RPC_URL=https://testnet-rpc.monad.xyz/
NEXT_PUBLIC_MONAD_CONTRACT_ADDRESS=0x4C03610C4daE70bc7f87157373B88412ef1a1923
NEXT_PUBLIC_GAME_API_URL=/api/game
GAME_API_ORIGIN=https://api.example.com
GAME_API_PROXY_SECRET=<same random value as local .env>
Only NEXT_PUBLIC_* values are included in browser JavaScript. Do not
add any wallet private key, tunnel token, database URL, or relayer/signer key to
Vercel. After Vercel assigns the final production URL, make sure it exactly
matches local FRONTEND_ORIGIN, restart game-api, and redeploy the frontend.
Stockfish is GPLv3. The bundled browser-demo license remains at
public/stockfish/Copying.txt; the Docker image installs Debian Stockfish.
React Chessboard is MIT licensed.