The RWA-powered multiplayer blockchain elimination game where the minority wins.
Built on the Stellar Network · Powered by Soroban Smart Contracts
Inverse Arena is a high-stakes, real-time PvP elimination game where players compete by making binary choices — Heads or Tails — each round. The twist that makes it unique:
The minority side always wins. Majority is eliminated.
Players who pick the option chosen by fewer players advance to the next round. This creates a pure psychological battle — every decision is a meta-game of predicting what others will do, then doing the opposite.
While the game runs, entry fees are never idle. Funds are routed into Real-World Asset (RWA) yield protocols on Stellar, so the prize pool grows with institutional-grade yield every second the game is live. The last player standing claims the entire pool plus accumulated yield.
| Problem | How Inverse Arena Solves It |
|---|---|
| GameFi economies rely on inflationary token emissions that collapse when growth slows | Prize pools are funded by real yield from US Treasury-backed RWAs — no token printing |
| Billions in GameFi TVL earns 0% while locked in contracts | Player stakes earn ~5% APY from Ondo USDY the moment they enter |
| Majority-rule prediction games breed herd behavior and low tension | Contrarian mechanics reward strategic thinking over crowd-following |
| Long matchmaking wait times with no value accrual | Yield accrues from the moment of deposit, even before a game starts |
Players enter → Choose Heads or Tails → Minority advances → Repeat → Last survivor wins
- Join a Pool — Players stake USDC, EURC, or XLM to enter an arena.
- Yield Starts — Soroban smart contracts route funds into RWA yield vaults (Ondo USDY).
- Each Round — Every 30–60 seconds, players choose Heads or Tails.
- The option chosen by the majority is eliminated.
- Players on the minority side advance.
- Elimination — Majority players exit; their share remains in the pool.
- Winner — The last player standing claims Principal + All Accumulated Yield.
Stellar is the optimal foundation for Inverse Arena:
- 2–5 second finality — Fast enough for real-time elimination rounds
- ~0.00001 XLM per transaction — Micro-stake games are economically viable
- Native RWA ecosystem — Direct access to Ondo USDY, tokenized T-bills, and yield-bearing anchors
- Passkey support — Players can sign moves with FaceID or TouchID; no seed phrases needed
┌─────────────────────────────────────────────────────┐
│ Frontend (Next.js) │
│ Wallet Connect · Game UI · Leaderboard · Analytics │
└────────────────────────┬────────────────────────────┘
│ REST / WebSocket
┌────────────────────────▼────────────────────────────┐
│ Backend (Express + TypeScript) │
│ Auth · Game State · Round Resolution · Job Workers │
│ PostgreSQL · Redis · BullMQ · Prometheus Metrics │
└────────────────────────┬────────────────────────────┘
│ Soroban RPC
┌────────────────────────▼────────────────────────────┐
│ Stellar Blockchain (Soroban/Rust) │
│ Arena Manager · RWA Adapter · Payout Contract │
└─────────────────────────────────────────────────────┘
RWA Yield Flow: For a complete end-to-end explanation of how entry fees are converted to USDY, how yield accrues, and how the winner's payout is calculated, see docs/RWA_YIELD_FLOW.md.
| Contract | Responsibility |
|---|---|
arena_manager.rs |
Player states, round timing, elimination logic |
rwa_adapter.rs |
Interfaces with Stellar Asset Contracts to deposit into yield protocols |
random_engine.rs |
Ledger-based entropy for fair, verifiable round outcomes |
payout.rs |
Distributes principal + yield to the winner |
factory.rs |
Deploys and manages arena contract instances |
| Service | Responsibility |
|---|---|
| Round State Machine | OPEN → CLOSED → RESOLVED → SETTLED with transactional integrity |
| Payout Worker | BullMQ job queue for Soroban transaction submission with retries |
| Auth Service | Wallet-based JWT authentication with nonce challenge flow |
| Metrics | Prometheus endpoint at /metrics for observability |
For a deeper breakdown of the system boundaries, state machines, and data model, see ARCHITECTURE.md.
inversearena-frontend/
├── frontend/ # Next.js 15 application
│ ├── src/
│ │ ├── app/ # Next.js App Router pages
│ │ ├── features/ # Feature modules (arena, wallet, leaderboard…)
│ │ ├── components/ # Shared UI components
│ │ └── lib/ # Utilities and SDK wrappers
│ ├── public/ # Static assets
│ └── .env.example # Frontend environment variable template
│
├── backend/ # Express API + background workers
│ ├── src/
│ │ ├── routes/ # API route handlers
│ │ ├── services/ # Business logic
│ │ ├── workers/ # BullMQ background workers
│ │ ├── middleware/ # Auth, rate limiting, validation
│ │ └── repositories/ # Database access layer
│ ├── prisma/
│ │ └── schema.prisma # PostgreSQL schema (User, Arena, Pool, Round…)
│ ├── tests/ # Integration and unit tests
│ └── .env.example # Backend environment variable template
│
└── CONTRIBUTING.md # Contribution guide (snapshot tests, XDR serialization)
- Node.js 20+
- pnpm 9+ (
npm install -g pnpm) - PostgreSQL 15+
- Redis 7+
- Docker (optional, for monitoring stack)
git clone https://github.com/your-org/inversearena-frontend.git
cd inversearena-frontendA root-level Makefile provides a single discoverable entry point for all common tasks:
make help # List all available targets
make dev # Start frontend + backend in development mode
make test # Run all tests (backend + frontend)
make build # Build both services for production
make migrate # Apply pending Prisma migrations (development)
make migrate-prod # Apply migrations in production (no seed)
make infra # Start PostgreSQL + Redis via Docker Compose
make monitoring # Start Prometheus + Grafana monitoring stack
make clean # Remove build artifacts and node_modulescd frontend
cp .env.example .env.local
pnpm install
pnpm devThe frontend runs at http://localhost:3000 by default.
cd backend
cp .env.example .env
npm install
npm run migrate:dev # Apply Prisma migrations
npm run dev # Start API server on port 3001| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_STELLAR_NETWORK |
No | testnet (default) or mainnet |
NEXT_PUBLIC_SOROBAN_RPC_URL |
Yes | Soroban RPC endpoint |
NEXT_PUBLIC_HORIZON_URL |
Yes | Stellar Horizon endpoint |
NEXT_PUBLIC_FACTORY_CONTRACT_ID |
Yes | Arena factory contract address |
NEXT_PUBLIC_USDC_CONTRACT_ID |
Yes | USDC token contract address |
NEXT_PUBLIC_APP_ORIGIN |
Yes | Canonical app URL (used for CORS) |
ALLOWED_ORIGINS |
Yes | Comma-separated allowed CORS origins |
REDIS_URL |
Yes | Redis connection string (rate limiting) |
NEXT_PUBLIC_SENTRY_DSN |
No | Sentry DSN — leave blank to disable error reporting |
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL connection string |
REDIS_URL |
Yes | Redis connection string |
JWT_SECRET |
Yes | Minimum 32-character secret for JWT signing |
SOROBAN_RPC_URL |
Yes | Soroban RPC endpoint |
STELLAR_NETWORK_PASSPHRASE |
Yes | Network passphrase |
PAYOUT_CONTRACT_ID |
Yes | Payout contract address |
PAYOUT_SOURCE_ACCOUNT |
Yes | Stellar account that submits payout transactions |
PAYOUTS_LIVE_EXECUTION |
No | false (default) — set true to submit real transactions |
PAYOUTS_SIGN_WITH_HOT_KEY |
No | false recommended in production; use external KMS |
ADMIN_API_KEY |
Yes | Secret key for admin endpoints |
Never commit
.envfiles. Use a secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.) for production credentials.
cd frontend
pnpm test:frontend # Jest unit tests
pnpm test:rate-limit # Rate limiter integration test
pnpm test:pagination # Pagination integration testcd backend
npm run test:ci # All tests
npx tsx tests/round.integration.test.ts # Round state machine
npx tsx tests/payment.integration.test.ts # Payout worker
npx tsx tests/auth.unit.test.ts # Auth service unit testsSee CONTRIBUTING.md for snapshot testing requirements.
cargo test --manifest-path contract/arena/Cargo.toml
cargo test --manifest-path contract/payout/Cargo.tomlStart the full observability stack with Docker Compose:
cd backend
docker-compose -f docker-compose.monitoring.yml up -d| Service | URL | Default Credentials |
|---|---|---|
| Prometheus | http://localhost:9090 | — |
| Grafana | http://localhost:3000 | admin / admin |
| Metrics endpoint | http://localhost:3001/metrics | — |
Tracked metrics include HTTP request rates and latencies, BullMQ job queue lengths, transaction confirmation rates, and round resolution counts.
Inverse Arena is designed for production-grade custody:
- Recommended: Set
PAYOUTS_SIGN_WITH_HOT_KEY=false. The backend builds an unsigned XDR transaction, which is then signed by an external KMS or HSM before being returned to the worker for submission. - Development only: Set
PAYOUTS_SIGN_WITH_HOT_KEY=truewithPAYOUT_HOT_SIGNER_SECRET— never use this in production.
| Phase | Status | Milestone |
|---|---|---|
| Phase 1 — Stellar Testnet | ✅ Complete | Soroban core logic, USDC integration, alpha with 100 players |
| Phase 2 — RWA Integration | ⏳ In Progress | Mainnet launch, Ondo USDY yield, MoneyGram Cash-In |
| Phase 3 — Expansion | 🚀 Planned | Mobile app with Passkey, DAO-governed RWA allocation, private arenas |
Pull requests are welcome. Before contributing:
- Read CONTRIBUTING.md — especially the snapshot testing rules for Soroban contract types.
- For smart contract contributions, see docs/CONTRIBUTING_CONTRACTS.md — covers environment setup, build commands, coding conventions, and the PR checklist.
- Run all relevant tests and ensure they pass.
- Keep PRs focused — one concern per pull request.
MIT — see LICENSE for details.