A full-stack, peer-to-peer coinflip betting game on Solana. Players connect a wallet, create or join on-chain game rooms, and compete head-to-head for 2Γ the stake. The UI updates in real time over WebSockets, outcomes are resolved on-chain with Orao VRF, and the backend tracks rooms, chat, and match history in MongoDB.
- Overview
- Features
- How it works
- Architecture
- Repository structure
- Prerequisites
- Getting started
- Configuration
- WebSocket API
- Supported tokens
- Smart contracts
- Security and fairness
- Deployment notes
- Roadmap
- Contact
- License
This project is a multiplayer Solana casino coinflip application split into three packages:
| Package | Role |
|---|---|
| coinflip-frontend | React UI β wallet connect, create/join rooms, live lobby, chat |
| coinflip-backend | Node.js WebSocket server β room orchestration, tx relay, MongoDB, VRF game handling |
| coinflip-smart-contract | Anchor/Rust programs β on-chain game logic (see Smart contracts) |
The production PvP program used by the frontend and backend is deployed at:
472RXUv8zUX7zm4LprxNsFQvAZYEpSGaY9EUE4akCvG6
- Create a room β Pick Head or Tail, set bet amount, choose SOL or SPL token.
- Join a room β Browse open games in the live lobby and match against another player.
- PvP coinflip β When two players are in the same room, the backend triggers on-chain resolution.
- 2Γ payout β The winner receives double the bet (fees apply on-chain).
- Room expiration β Open rooms older than 5 minutes with no opponent are expired and refunded automatically.
- Portfolio stats β Win count and total games per wallet.
- Real-time lobby β WebSocket broadcasts for new rooms, joins, results, and expirations.
- Global chat β Wallet-linked messages with pagination.
- Phantom wallet β Connect via
@solana/wallet-adapter. - Multiple currencies β SOL, USDT, USDC, BONK (configurable in backend constants).
- Optional Twitter posts β Match results can be tweeted after settlement (configure credentials).
bandicam.2025-06-17.03-34-32-981.mp4
- Connect wallet (Phantom) on the frontend.
- Create game β Choose side (Head/Tail), amount, and token; sign the
createGametransaction. - Another player joins β They sign
joinOppositewith the same stake. - Settlement β The backend calls
handleGameusing Orao VRF; the coin result is written on-chain. - Winner paid β Funds move per program rules; the UI shows the result and confetti on win.
If nobody joins within 5 minutes, the backend:
- Refunds the creator (and opponent if partially joined).
- Removes the room from MongoDB.
- Broadcasts
EXPIRE_GAMEto all connected clients.
flowchart LR
subgraph Client
UI[React Frontend]
Wallet[Phantom Wallet]
end
subgraph Server
WS[WebSocket :8881]
DB[(MongoDB)]
Relayer[Anchor Relayer Keypair]
end
subgraph Chain
Program[Coinflip Program]
VRF[Orao VRF]
end
UI <-->|JSON events| WS
UI -->|Sign txs| Wallet
Wallet -->|Solana RPC| Program
WS --> DB
WS --> Relayer
Relayer --> Program
Program --> VRF
Data flow (simplified):
- Frontend opens WebSocket to backend (
WS_HOST). CREATE_ROOMβ backend builds unsigned tx β user signs βMANAGE_GAMEDATA(create) β backend submits and saves room.JOIN_ROOMβ second user signs βMANAGE_GAMEDATA(join) β backend runshandleGameβUPDATE_RESULTbroadcast.
Solana-Casino-Coinflip-Game/
βββ coinflip-frontend/ # React + Tailwind + wallet adapter
β βββ src/
β β βββ Component/ # UI (Coinflip, Modals, Header, chat)
β β βββ Context/ # WebSocket + effects providers
β β βββ config/ # RPC, program IDs, menu tokens
β βββ package.json
β
βββ coinflip-backend/ # WebSocket server + MongoDB
β βββ controller/ # Anchor txs, refunds, Twitter
β βββ model/ # Game & message schemas
β βββ config/ # DB connection
β βββ constant/ # Program ID, seeds, token list
β βββ index.ts # WebSocket entry (port 8881)
β βββ package.json
β
βββ coinflip-smart-contract/ # Anchor workspace
β βββ coinflip/
β βββ programs/coinflip/ # Rust program (solo-style reference)
β βββ tests/
β βββ cli/
β
βββ readme.md # This file
Install before running locally:
| Tool | Version (recommended) |
|---|---|
| Node.js | 18+ |
| Yarn or npm | Latest |
| MongoDB | Atlas or local instance |
| Rust | Latest (for smart contract work) |
| Solana CLI | 1.18+ |
| Anchor | 0.26+ (for contract development) |
You also need:
- A Solana wallet with devnet SOL for testing.
- A backend relayer keypair (
PRIVATE_KEY) funded on the same cluster as your RPC. - The Anchor IDL file
coinflip.tsincoinflip-backend/(see Configuration).
Run all three services for local development.
Create a MongoDB database (local or MongoDB Atlas). Note the connection credentials for .env.
cd coinflip-backend
yarn installCreate coinflip-backend/.env (see Configuration).
Place the program IDL at coinflip-backend/coinflip.ts (TypeScript export of the deployed programβs IDL). This file is gitignored; generate it from your deployed Anchor program or copy from your build artifacts.
yarn dev
# or: yarn start (nodemon)The WebSocket server listens on port 8881.
cd coinflip-frontend
yarn installEdit coinflip-frontend/src/config/constant.ts:
- Set
WS_HOSTtows://localhost:8881for local backend. - Set
RPCto your Solana cluster URL (default: devnet).
yarn startOpen http://localhost:3000.
The coinflip-smart-contract folder contains an Anchor program useful for learning and testing. The live PvP game uses the deployed program ID above; rebuilding requires aligning program ID, IDL, and frontend/backend constants.
cd coinflip-smart-contract/coinflip
yarn install
anchor build
anchor test| Variable | Description |
|---|---|
RPC |
Solana RPC URL (e.g. https://api.devnet.solana.com) |
PRIVATE_KEY |
Base58-encoded secret key for the relayer wallet |
FEE_RECEIVER |
Public key that receives platform fees |
DB_USERNAME |
MongoDB username |
DB_PASSWORD |
MongoDB password |
DB_HOST |
MongoDB cluster host |
DB_NAME |
Database name |
PORT |
Optional HTTP port (default 9000; WebSocket uses 8881 in code) |
Example:
RPC=https://api.devnet.solana.com
PRIVATE_KEY=your_base58_secret_key
FEE_RECEIVER=YourFeeReceiverPublicKey
DB_USERNAME=your_user
DB_PASSWORD=your_password
DB_HOST=cluster0.xxxxx.mongodb.net
DB_NAME=coinflip| Constant | Purpose |
|---|---|
COINFLIP |
On-chain program public key |
WS_HOST |
WebSocket URL (ws://localhost:8881 locally) |
RPC |
Solana JSON-RPC endpoint |
FEE_RECEIVER / treasury |
Fee and treasury accounts |
coinflip-backend imports the program IDL from ../coinflip (coinflip.ts). That file is listed in .gitignore. Without it, the backend will not compile. After deploying or updating the contract, regenerate:
anchor idl parse -f target/idl/coinflip.json -o coinflip.tsCopy the output into coinflip-backend/coinflip.ts.
Connect to WS_HOST (default ws://localhost:8881). Messages are JSON: { "type": "<EVENT>", ... }.
| Type | Description |
|---|---|
CREATE_ROOM |
Build create-game tx (unit, mint, decimal, amount, creator, selection) |
JOIN_ROOM |
Build join tx (unit, opposite, creator_key, mint, index, amount) |
GET_ROOMS |
List active rooms (last 5 minutes) |
MANAGE_GAMEDATA |
event: "create" or "join" β submit signed txs after wallet approval |
Fetch_Result |
Stats for a wallet address |
MESSAGE |
Send chat message |
FETCH_MESSAGE |
Paginated chat history (page) |
| Type | Description |
|---|---|
ROOM_CREATED |
Unsigned create tx (base64) + room metadata |
USER_JOINED |
Unsigned join tx + gamePDA |
ROOM_LIST |
Active rooms array |
ADD_NEW |
New room broadcast |
UPDATE_JOIN |
Opponent joined |
CHANGE_PROCESS |
Tx processing state |
UPDATE_RESULT |
Game finished with result |
EXPIRE_GAME |
Room expired / refunded |
FETCH_INFO |
{ win, games } for wallet |
MESSAGE_LIST |
Chat messages |
ERROR_HANDLE |
Error string for UI toasts |
Default list in coinflip-backend/constant/index.ts:
| Symbol | Type | Notes |
|---|---|---|
| SOL | Native | 9 decimals |
| USDT | SPL | Mainnet mint in config |
| USDC | SPL | Custom mint in repo config |
| BONK | SPL | Custom mint in repo config |
Update mint addresses and decimals for your target network (devnet vs mainnet).
This repo includes two related but distinct on-chain setups:
- Program ID:
472RXUv8zUX7zm4LprxNsFQvAZYEpSGaY9EUE4akCvG6 - Instructions:
initialize,createGame,joinOpposite,handleGame, refunds, etc. - Randomness: Orao Solana VRF (
@orao-network/solana-vrf) - Seeds:
coinflip_global_main,coinflip_game
The backend drives game creation, joins, and settlement via this programβs IDL.
- Program ID (local):
7ttfENVhNwb21KjZiLHgXLsX2sC1rKoJgnTVL4wb54t1 - Model: Single-player pool (
play_game,claim_reward) with slot/timestamp-based randomness - Use: Reference implementation, tests, and CLI scripts β not wired to the live PvP UI without redeploying and updating IDs
When extending the project, treat the deployed PvP program + IDL as the source of truth for production behavior.
Multiplayer resolution uses Orao VRF:
- A unique randomness account per game PDA
- Verifiable, on-chain random outcomes
- Transparent settlement in the coinflip program
- Stakes are locked in program-derived accounts during a match
- The relayer wallet only signs protocol actions configured in the program (e.g.
handleGame) - Expired rooms trigger backend-initiated refunds
- Not audited in this README β Conduct a professional audit before mainnet use with real funds.
- Devnet by default β Frontend
RPCpoints to devnet; switch deliberately for production. - Secrets β Never commit
.env,PRIVATE_KEY, or API keys. Move hardcoded Twitter credentials to environment variables before production. - Gambling regulations β Operators are responsible for compliance in their jurisdiction.
| Component | Suggested approach |
|---|---|
| Frontend | yarn build β static host (Vercel, Netlify, etc.) |
| Backend | Node process with env vars; expose port 8881 for WSS |
| MongoDB | MongoDB Atlas |
| RPC | Dedicated provider (Helius, QuickNode, etc.) for production |
| Program | Deploy PvP program to target cluster; sync IDL + all COINFLIP constants |
Production frontend config references Railway-hosted backend URLs in comments β replace with your own endpoints and use wss:// for secure WebSockets.
Planned or stubbed in the UI:
- Jackpot mode (
/jackpot, coming soon) - History page (coming soon)
For questions, collaboration, or support:
Telegram: @microRustyme
No license file is included in the root repository. Add a LICENSE file if you intend to open-source or distribute this project.
# Terminal 1 β backend
cd coinflip-backend && yarn && yarn dev
# Terminal 2 β frontend
cd coinflip-frontend && yarn && yarn startEnsure MongoDB is running, .env is configured, coinflip.ts IDL exists, and WS_HOST / RPC match your setup.