AstroFight is a real-time 1v1 space shooter built for Solana devnet, with cinematic Three.js combat, wallet-based staking, and a server-secured payout path designed to evolve into a MagicBlock Ephemeral Rollup authoritative game loop.
Players connect Phantom, enter a duel room, stake equal SOL, and launch into a live spaceship battle in a fully 3D arena. The game focuses on fast arcade dogfighting, readable laser combat, premium sci-fi presentation, and a clean on-chain match flow suitable for hackathon demos and devnet testing.
- 1v1 spaceship duel with direct face-to-face arena spawns
- Fully 3D battle scene with imported
.glbship models - Laser-based combat with visible beam trails and impact effects
- Real wallet connection through Phantom
- On-chain devnet escrow deposit flow
- Server-side settlement path for winner payout
- MagicBlock ER-ready match-state architecture
- Responsive UI for desktop and mobile
- Background music loop plus laser and explosion SFX
W/Up Arrow: move forwardS/Down Arrow: move backwardA: strafe leftD: strafe rightMouse: aim ship headingLeft ClickorSpace: fire laserShift: boost
- Each ship starts with
100 HP - Player lasers are green
- Enemy lasers are red
- Asteroids and planets act as real obstacles
- Ships cannot pass through planets or asteroids
- First pilot to reduce the opponent to
0 HPwins - Disconnects and timeout flows are tracked in match resolution
React + TypeScript + ViteThree.jsvia@react-three/fiberand@react-three/dreiTailwind CSSZustandFramer MotionSolana web3.jsPhantom wallet adapterAnchorMagicBlock router / match-state integration scaffoldVercel-compatible server API routes
AstroFight uses an Anchor escrow program to hold equal stake deposits from both players. Funds remain in escrow until the match result is finalized and the winner receives the full prize pool.
Deployed escrow program:
36jNz1GXXBV4DoXHETExtqHCawyw3sE9JhUNsn57BxAh
A separate match_state program is deployed to track authoritative room state and is structured to support MagicBlock delegation.
Deployed match-state program:
7k4vyWB43PQNUU2RVFsP8czAqhgV1Fv7w4e31AitM3FF
For the current hackathon build, the match is settled through a secure server-side settlement authority. The browser never holds the private key. Only the public key is exposed to the client.
Public arbiter:
9fmVEUnfwHvzezsGMLjrbjweydmf3vS8HBFUuanwhVhM
The project is already structured for MagicBlock, but the live gameplay loop is still a hybrid prototype:
- local duel sync currently uses WebRTC transport
- MagicBlock router probing and room PDA derivation are wired
- server APIs prepare and finalize on-chain match-state
- escrow settlement now expects match-state participation
This means the app is strong enough for a devnet hackathon demo, while still being transparent that full ER-authoritative combat is the next major step.
The following custom assets are integrated into the game:
- banner image for project branding
lasershoot.mp3for firingexplosion.mp3for ship defeatbgmusic.mp3for low-volume looping background music
Asset locations:
Install dependencies:
npm installRun the app:
npm run devBuild production assets:
npm run buildLint:
npm run lintCopy .env.example to .env and configure:
VITE_SOLANA_RPC_HTTP=https://api.devnet.solana.com
VITE_SOLANA_CLUSTER=devnet
VITE_MAGICBLOCK_RPC_HTTP=https://devnet-router.magicblock.app
VITE_MAGICBLOCK_RPC_WS=wss://devnet-router.magicblock.app
VITE_MATCH_STATE_PROGRAM_ID=
VITE_MAGICBLOCK_VALIDATOR=
VITE_MAGICBLOCK_COMMIT_FREQUENCY_MS=3000
VITE_ESCROW_PROGRAM_ID=
VITE_MATCH_ARBITER=
MATCH_ARBITER_SECRET_KEY=Important:
VITE_*values are exposed to the browserMATCH_ARBITER_SECRET_KEYmust remain server-only- for Vercel, put
MATCH_ARBITER_SECRET_KEYin server environment variables only
Frontend and server routes can be deployed on Vercel. Solana programs are deployed separately with Anchor.
Recommended Vercel env vars:
VITE_SOLANA_RPC_HTTPVITE_SOLANA_CLUSTERVITE_MAGICBLOCK_RPC_HTTPVITE_MAGICBLOCK_RPC_WSVITE_MATCH_STATE_PROGRAM_IDVITE_ESCROW_PROGRAM_IDVITE_MATCH_ARBITERMATCH_ARBITER_SECRET_KEY
- src/App.tsx: app flow, wallet, room lifecycle, staking, match settlement calls
- src/components/scene/AstroFightScene.tsx: 3D scene, ships, lasers, VFX
- src/game/engine.ts: movement, shooting, damage, bot simulation
- src/game/store.ts: runtime match state
- src/solana/escrow.ts: client-side escrow deposit flow
- src/solana/matchService.ts: secure server API client
- server/matchApi.ts: server-side match-state preparation and settlement
- anchor/programs/astrofight_escrow/src/lib.rs: escrow contract
- anchor/programs/astrofight_match_state/src/lib.rs: match-state contract
AstroFight is currently positioned as a polished devnet prototype:
- real wallet flow
- real escrow deposit structure
- secure server-side payout path
- playable cinematic 3D combat
- MagicBlock-aligned architecture
What is still next:
- full authoritative combat through MagicBlock ER
- stronger anti-cheat validation
- live cross-device production testing
This repository is currently intended for project and hackathon use.
