A real-time, blockchain-integrated multiplayer quiz game API built with Flask and Socket.IO. Players can create lobbies, join them using their crypto wallets, and compete by submitting numeric guesses to AI-generated trivia questions. The game leverages Web3 for secure betting and prize distribution, storing game records on the blockchain as blob data. It supports a best-of-5 format where the player with the closest guess wins each round, with winnings multiplied and transferred to their wallet.
-
Web3 Integration: Players use crypto wallets for authentication, betting, and prize distribution via blockchain transactions.
-
Real-Time Gameplay: Utilizes Socket.IO for live lobby updates, round progression, and game results.
-
AI-Generated Questions: Trivia questions are generated by Google Gemini AI, ensuring challenging and unique content.
-
Betting System: Players wager credits, with the winner receiving 1.8x the bet amount, delivered directly to their wallet.
-
Blockchain Records: Game data is saved as blob records on the blockchain for transparency and immutability.
-
JWT Authentication: Secure player verification using JSON Web Tokens.
-
JSON-Based API: All endpoints return JSON data for seamless frontend integration.
-
Python 3.8+
-
A Google API Key for Gemini AI
-
A Web3 RPC URL, API Key, and Wallet Address (configured in
.env) -
Access to a blockchain network supporting
state.Transferandblob.Submitmethods (e.g., Pops One)
-
Clone the Repository:
git clone https://github.com/Fatihparm/PaceUp.git cd PaceUp -
Install Dependencies:
pip install -r python/requirements.txt
-
Set Up Environment Variables:
- Create a
.envfile in the project root with the following:GOOGLE_API_KEY=your_google_api_key_here JWT_SECRET_KEY=your_jwt_secret_key_here WALLET_ADDRESS=your_wallet_address_here API_KEY=your_web3_api_key_here RPC_URL=https://your_rpc_url_here TX_STATUS_URL=https://your_tx_status_url_here NAME_SPACE=your_namespace_here
- Run the Server:
python python/app.py
- The API will start on http://localhost:5001.
To set up the project, follow these steps:
yarn install
yarn dev
This project is built using:
- Next.js (15.1.7)
- React (19.0.0)
- TailwindCSS (3.4.1)
- Socket.io-client (4.8.1)
- Ethers.js (6.13.5)
- Web3.js (4.16.0)
- WalletConnect
- CosmJS
The available scripts are:
yarn dev– Starts the development server with Turbopack.yarn build– Builds the project for production.yarn start– Runs the production build.yarn lint– Lints the project.
GET \
-
Description: Returns the API status.
-
Response:
{"message": "Quiz Game API is running", "version": "1.0"} -
Status: 200 OK
POST /create_lobby
-
Description: Creates a new lobby with a unique UUID.
-
Request Body (form-data):
-
username: Player’s wallet address (string) -
bet: Bet amount (integer) -
topic: Trivia topic (string, e.g., "Sport", "History")
-
-
Response:
{"lobby_id": "550e8400-e29b-41d4-a716-446655440000", "username": "0x123...", "credits": 100} -
Status: 201 Created
GET /api/lobbies
-
Description: Returns all active lobbies.
-
Response:
{ "550e8400-e29b-41d4-a716-446655440000": { "owner": "0x123...", "players": {"0x123...": {"credits": 100, "ready": false}}, "scores": {"0x123...": 0}, "bet": 500, "topic": "Sport", "status": "waiting" } } -
Status: 200 OK
GET /api/lobby/<lobby_id>
-
Description: Returns details of a specific lobby.
-
Response:
{ "owner": "0x123...", "players": {"0x123...": {"credits": 100, "ready": false}}, "scores": {"0x123...": 0}, "bet": 500, "topic": "Sport", "status": "waiting" } -
Status: 200 OK, 404 if not found
GET /api/game/<lobby_id>
-
Description: Returns the current game state for a lobby.
-
Response:
{ "lobby_id": "550e8400-e29b-41d4-a716-446655440000", "current_question": {"question": "In Formula 1, ...", "answer": 24}, "players": {"0x123...": {"credits": 100, "ready": true}, "0x456...": {"credits": 100, "ready": true}}, "scores": {"0x123...": 0, "0x456...": 0}, "status": "playing" } -
Status: 200 OK, 404 if game not started
POST /protected (JWT Required)
-
Description: A protected route requiring JWT authentication.
-
Response:
{"message": "Access granted", "walletAddress": "0x123..."} -
Status: 200 OK, 401 if unauthorized
POST /verify_transfer
-
Description: Verifies a blockchain transaction by its hash.
-
Response:
{"tx_hash": "0xabc..."} -
Status: 200 OK, 400 if invalid request
GET /get_game_record/<game_id> (JWT Required)
-
Description: Retrieves a specific game record from the blockchain.
-
Response: Game data blob (JSON format), e.g.:
{ "game_id": 1, "players": [{"wallet": "0x123..."}, {"wallet": "0x456..."}], "bet_amount": 500, "scores": {"0x123...": 3, "0x456...": 1}, "winner": "0x123...", "timestamp": "2025-02-28 12:00:00", "questions": [{"question": "In Formula 1, ...", "answers": {"0x123...": 24, "0x456...": 30}, "correct": 24}, ...] } -
Status: 200 OK, 404 if not found
GET /get_player_history (JWT Required)
-
Description: Returns the match history for the authenticated player.
-
Response: Game data blob (JSON format), e.g.:
{ "matches": [ {"game_id": 1, "player1": "0x123...", "player2": "0x456...", "block_height": 12345, "namespace": "quiz_game", "is_player1": true} ] } -
Status: 200 OK, 500 if error
-
join_lobby:-
Payload:
{"lobby_id": "550e8400-...", "username": "0x123...", "credits": 100} -
Joins a player to a lobby.
-
-
ready:-
Payload:
{"lobby_id": "550e8400-...", "username": "0x123..."} -
Marks a player as ready.
-
-
submit_guess:-
Payload:
{"lobby_id": "550e8400-...", "username": "0x123...", "guess": 42} -
Submits a guess for the current round.
-
-
leave_lobby:-
Payload:
{"lobby_id": "550e8400-...", "username": "0x123..."} -
Removes a player from the lobby.
-
-
lobby_update:- Payload: Lobby data (same as
/api/lobby/<lobby_id>response)
- Payload: Lobby data (same as
-
start_game:- Payload:
{"lobby_id": "550e8400-..."}
- Payload:
-
new_round:- Payload:
{"question": "In Formula 1, ...", "players": ["0x123...", "0x456..."], "scores": {"0x123...": 0, "0x456...": 0}, "timer": 15}
- Payload:
-
round_result:- Payload:
{"correct_answer": 24, "winner": "0x123..."}
- Payload:
-
game_over:- Payload:
{"winner": "0x123...", "scores": {"0x123...": 3, "0x456...": 1}}
- Payload:
-
error:-Payload:
{"message": "Lobi dolu"}
-
Transactions: Uses
state.Transferfor prize distribution andblob.Submitfor game record storage. -
Verification:
verify_transferendpoint checks transaction validity within a 2-minute window. -
Prize: Winner receives 1.8x the bet amount, transferred via Web3 RPC.
-
Port: Default port is 5001. Adjust in app.py if needed.
-
Blockchain: Configured for Pops One network (update RPC_URL and TX_STATUS_URL for other networks).
- Fork the repository, submit issues, or send pull requests!