TryHard is a competitive 1v1 Trivia game built on the Solana blockchain. Players stake SOL in an on-chain escrow to answer questions generated by AI (automatically using the name entered by user) in real-time. The fastest player to answer correctly wins the round, and the overall winner sweeps the staked pool.
This repository contains the entire TryHard ecosystem.
you can view the demo video here or download the app from here : tryhard.abhee.dev
Test Accounts
account 1
email: [email protected]
pass [email protected]
account 2
email: [email protected]
pass: [email protected]
The system is built on an event-driven architecture. The mobile clients do not have a persistent WebSocket connection to the Node.js server. Instead, all live game state is driven by Supabase Realtime (postgres_changes), which fans out database row updates to every subscribed client instantly.
graph TD
%% Entities
ClientA["📱 Mobile App – Player 1"]
ClientB["📱 Mobile App – Player 2"]
Web["🌐 Next.js Landing Page"]
Server["⚙️ Node.js Game Engine"]
Supabase[("🗄️ Supabase\n(PostgreSQL + Realtime)")]
Program["📜 Anchor Escrow Program"]
Blockchain["⛓️ Solana Blockchain"]
%% REST Actions — client talks to backend only for triggered actions
ClientA -->|"REST: create match / join / start / submit answer"| Server
ClientB -->|"REST: join / submit answer"| Server
%% Backend manages all match state in Supabase DB
Server -->|"Write match state\n(status, current_question_index, scores)"| Supabase
%% Game Engine ticks every 1s — advances question and finishes match
Server -->|"1s engine tick:\nadvance question / finish match"| Supabase
%% Clients subscribe directly to Supabase Realtime — no backend WS needed
Supabase -->|"🔴 Realtime postgres_changes:\nstatus=starting➜active➜finished,\ncurrent_question_index"| ClientA
Supabase -->|"🔴 Realtime postgres_changes:\nsame subscription"| ClientB
%% On-chain escrow
ClientA -.->|"On-chain deposit (SOL)"| Program
ClientB -.->|"On-chain deposit (SOL)"| Program
Server -->|"RPC: resolve / draw escrow\n(payout authority only)"| Program
Program --- Blockchain
%% Website
Web -->|Download / promo| ClientA
| Step | Who | What Happens |
|---|---|---|
| 1 | Player 1 | Calls POST /match/create on the backend. Match is created with status=waiting (or status=funding if staked). |
| 2 | Player 1 | If staked, signs a Solana tx to deposit SOL into the on-chain escrow PDA. Backend verifies tx and flips status=waiting. |
| 3 | Player 2 | Finds the match (public feed or 6-digit code). Calls POST /match/:id/join. Backend sets status=ready. |
| 4 | Both clients | Supabase Realtime fires a postgres_changes UPDATE event — both clients receive the status=ready update instantly in the Waiting Room. |
| 5 | Player 2 | If staked, signs and sends their escrow deposit tx. Backend verifies it. |
| 6 | Player 1 | Calls POST /match/:id/start. Backend sets status=starting and started_at. |
| 7 | Both clients | Supabase Realtime fires — both clients receive status=starting and show the 5-second pre-game countdown. |
| 8 | Backend Engine | 1-second polling loop detects the countdown has elapsed. Sets status=active, current_question_index=0, question_start_time. |
| 9 | Both clients | Supabase Realtime fires — clients receive status=active and enter the question phase, showing an interlude then the first question. |
| 10 | Both players | Answer questions by calling POST /match/:id/answer. Answers are stored in match_answers. |
| 11 | Backend Engine | Each tick, checks if both players answered OR time expired. If so, increments current_question_index (or finishes the match). |
| 12 | Both clients | Supabase Realtime fires on each current_question_index change → interlude countdown → next question shown. |
| 13 | Backend Engine | After last question, scores are tallied. status=finished, winner_id are written. If staked, escrow is resolved on-chain. |
| 14 | Both clients | Supabase Realtime fires status=finished → both clients are automatically navigated to the Results screen. |
The Mobile Application (Front-End) Built using React Native (Expo), this is the core client application players install on their devices (iOS/Android).
- Stack: Expo, Expo Router, React Native, Zustand, Supabase JS Client
- Real-time: Uses
supabase.channel().on('postgres_changes', ...)directly — no backend WebSocket. All game phases (waiting,ready,starting,active,finished) and question advancement are driven by Supabase Realtime events. - Run Locally:
cd app→npm install→npx expo start
The Game Engine & Authority Server A Node.js (Express) server responsible for match lifecycle management, AI question generation, and Solana escrow authority.
- Stack: Express, Supabase JS (server-side), Solana Web3.js, Google Generative AI (Gemini)
- Game Engine: A
setIntervaltick runs every 1 second, pollingstatus=startingandstatus=activematches from Supabase. It advancescurrent_question_index, calculates final scores, and marks matchesfinished. Clients react to these DB changes via Realtime. - Run Locally:
cd backend→pnpm install→pnpm dev
The Solana Smart Contract (Escrow) Written in Rust (Anchor Framework), this on-chain program guarantees trustless financial wagers.
- Stack: Rust, Anchor
- Features: Initializes a PDA escrow for each match. The backend is the sole authority that can resolve (pay winner) or draw (refund both) the escrow. Players deposit directly via the mobile app.
- Run Locally:
cd program→anchor build→anchor test
The Promotional Landing Page A Next.js web application serving as the public-facing marketing and download page.
- Stack: Next.js 15+, Tailwind CSS v4, React 19
- Run Locally:
cd website→npm install→npm run dev
To run this complex application locally, you will need to operate three separate terminals simultaneously:
- Start the Database / Backend: Ensure your Supabase instance is running, supply the
.envkeys in/backend, and launch the Game Server. - Start the Local Validator (Optional): If testing smart contracts locally, run
solana-test-validatorandanchor deployin the/programdirectory. - Launch the Game Client: Open
/appand runnpx expo startto launch the mobile bundler using an emulator or Expo Go.