Prediction Game Wiring Map
Execution coordinates for the engineering agent. All paths relative to the implementation worktree.
Pages
| Screen | Route | File | Pattern to Copy |
|---|---|---|---|
| Match List | /predictions | BLOCKER — new app, path TBD | Existing NX app page structure |
| Prediction Form | /predictions/{matchId}/predict | BLOCKER — new app, path TBD | Form patterns from CRM deal create |
| My Predictions | /predictions/mine | BLOCKER — new app, path TBD | List patterns from CRM contact list |
| Match Detail | /predictions/{matchId} | BLOCKER — new app, path TBD | Detail patterns from CRM deal detail |
Components
| Component | File | Serves (Screen Contract ref) |
|---|---|---|
| FixtureCard | BLOCKER — new component | Match List — fixture card element |
| OutcomeSelector | BLOCKER — new component | Prediction Form — outcome radiogroup |
| PoolDistribution | BLOCKER — new component | Match Detail — pool chart, Prediction Form — pool meter |
| PredictionCard | BLOCKER — new component | My Predictions — prediction card element |
| StatusBadge | BLOCKER — new component | My Predictions — status badge element |
| ZkLoginButton | BLOCKER — new component | Prediction Form — auth prompt |
Infrastructure
Move Modules
| Module | Purpose | Key Types | Dependencies |
|---|---|---|---|
game.move | Game registry, fixture lifecycle | GameRegistry (shared), Fixture (shared) | sui::clock, sui::event |
prediction.move | Prediction creation, state machine | Prediction (owned), PredictionReceipt (owned, Display) | game.move, sui::display |
oracle.move | Result submission, hot potato | OracleResult (no abilities), OracleCap (owned) | game.move, sui::clock |
treasury.move | Pool accounting, settlement, payouts | Treasury (shared), Pool (owned by fixture) | prediction.move, oracle.move |
leaderboard.move | Season tracking, rankings | Season (shared), LeaderboardEntry (owned) | prediction.move |
season.move | Season lifecycle, competition config | SeasonConfig (shared) | game.move |
admin.move | Admin capabilities, manual overrides | AdminCap (owned) | All modules |
Backend Services
| Layer | File | Purpose |
|---|---|---|
| Gas Station | BLOCKER — new service | Sponsor user PTBs, manage SUI balance, enforce daily caps |
| Oracle Agent | BLOCKER — new service | Fetch match results from sports API, submit on-chain with attestation |
| zkLogin Salt | BLOCKER — depends on Sui zkLogin infrastructure | Manage ZKP salt for OAuth → address derivation |
Frontend Integration
| Layer | File | Purpose |
|---|---|---|
| dApp Kit provider | BLOCKER — new app root | Sui network config, wallet adapter, zkLogin setup |
| PTB composer | BLOCKER — new lib | Compose multi-step PTBs for predict, settle operations |
| Sponsored tx signer | BLOCKER — new lib | Request platform co-signature for gasless transactions |
Existing Tests
| Type | File | Covers (Story/Build ref) |
|---|---|---|
| Move unit tests | BLOCKER — within each .move file | S3 (settlement), S5 (oracle safety) |
| Integration tests | BLOCKER — new test directory | S2 (full predict flow), S3 (full settle flow) |
| E2E tests | BLOCKER — Playwright in new app | S1 (browse), S2 (predict), S4 (history) |
Seeds and Fixtures
Test Data Required
- 5+ fixture objects in
GameRegistrywith varying states (upcoming, live, settled) - 10+ prediction objects across fixtures for settlement testing
- Oracle capability object for test oracle agent
- Admin capability object for override testing
- SUI balance in gas station wallet for sponsored transactions
Test Accounts
- Admin: holds
AdminCapandOracleCap - Oracle agent: holds
OracleCap(separate from admin in production) - Test users: 3+ zkLogin accounts for prediction testing
- Gas station: funded account for sponsoring transactions
Implementation Guardrails
- Use
@mysten/dapp-kitfor all Sui interactions — do not use raw RPC calls - Follow existing Move package structure from
packages/directory - All multi-step operations must use PTB composition — never sequential transactions
- Hot potato pattern for
OracleResult— nostore,copy, ordropabilities - Clock guard on all time-sensitive operations — use
sui::clock::timestamp_ms() - Dynamic Display for prediction receipts — template resolves from object state
- Sponsored transactions for all user-facing PTBs — user never pays gas
- Pool accounting must enforce: sum of payouts <= total pool (no inflation)
- Error codes: 100s for game.move, 200s for prediction.move, 300s for oracle.move, 400s for treasury.move
- Do not create alternate domain terminology — use spec naming (fixture, prediction, pool, receipt)