Live deployment: https://solmachines.wiktor.uk (hosted on DigitalOcean)
One-line pitch: Spectators pay a Solana SPL token ($BOOST) on devnet to physically turbo a self-driving RC car in real time, while an AI agent reads the spectator chat to update the car's driving strategy on the fly.
Why it's interesting:
- An on-chain
$BOOSTSPL transfer on Solana devnet causes a real-world physical action (BLE turbo packet to the RC car) within ~1–2 seconds via aaccountSubscribeWebSocket subscription on the treasury ATA. - A computer-vision-driven RC car (OpenCV or PyTorch CNN) follows a tape track autonomously, with DAgger online learning — human keyboard corrections during autonomous driving auto-retrain the CNN every 20 corrections and hot-reload weights with no restart.
- An OpenAI
o4-mini"CrowdAgent" reads spectator chat every N messages and emits a structuredCarStrategy(throttle aggressiveness, boost policy, etc.) that is applied live to the perception loop.
Tech stack at a glance: Solana devnet + $BOOST SPL token, Phantom Wallet, @solana/web3.js, @solana/spl-token, OpenAI o4-mini, PyTorch (TorchScript) + DAgger, OpenCV, Python FastAPI, bleak BLE, Node.js + Express + SQLite, Next.js + React + TypeScript + Tailwind, Raspberry Pi Zero 2 W + Pi Camera Module 3, go2rtc + RTSP/H.264, DigitalOcean for deployment, Claude Code as the primary AI dev tool.
Live $BOOST token (Solana devnet):
- Mint:
3rTR28PEaZRxGdXxsqAV7jQFjhB5v76bE2PqZv9rnCV9 - Treasury:
CGKs9nAfT8GZFsk6Fr2MvYGaDdLqFc1P83rippv1Frmp - Decimals:
0· Supply: 1,000,000 in treasury + 100,000 in faucet
Where to look first (judges):
- Open https://solmachines.wiktor.uk to see the deployed spectator UI.
- Read
Aedonys/Sol-Machine/hardware/main.py— the FastAPI hub for BLE, perception, boost, Solana listener, DAgger, and chat. - Read
Aedonys/Sol-Machine/hardware/solana_listener.py— the Solana → physical-action bridge. - Read
Aedonys/Sol-Machine/hardware/crowd_agent.py— the OpenAI structured-output strategy agent. - Read
Aedonys/Sol-Machine/solana/mint.tsandfaucet.ts— token + faucet setup.
Physical hardware (Pi + RC car) is not part of the deployed website — that is the live demo at the venue. The deployed site shows the spectator/admin UI, Solana payment flow, betting cycle, and chat agent, with the hardware backend stubbed when the car is not connected.
Sol Machine is an autonomous RC racing and spectator-control project. It combines a physical camera-equipped racing car, computer vision line following, a betting/voting race interface, Solana devnet payment helpers, and an AI-assisted crowd strategy chat.
The active application lives in Aedonys/Sol-Machine/.
Older root-level folders such as V2/, Submission/, and docs/ are reference snapshots unless you are specifically working on firmware or legacy UI files.
- Streams a live camera feed from the car setup.
- Connects to and controls Shell Racing Legends BLE cars.
- Runs autonomous line following with OpenCV or a small CNN backend.
- Lets spectators place race bets and vote for boost targets.
- Tracks race cycles, votes, bets, settlement, and payouts in a Node/SQLite backend.
- Lets spectators discuss car strategy; the Python hardware backend can summarize that discussion into a structured strategy with OpenAI and apply it to driving behavior.
- Bridges race-state boost decisions from the Node backend to the Python hardware backend so UI boost state and physical turbo can stay aligned.
Aedonys/Sol-Machine/
|-- frontend/ Next.js public/admin UI, runs on port 3002
|-- backend/ Node/Express race, betting, SQLite, Solana helpers, runs on port 3001
|-- hardware/ Python/FastAPI BLE, camera, perception, boost, chat strategy, runs on port 3000
|-- training/ Frame collection and CNN training scripts
|-- solana/ Devnet scripts and token-related helpers
`-- docs/ Legacy/static UI reference
The frontend hides most of the split-backend setup through Next rewrites:
/api/car/*,/api/cars/*,/api/camera/*,/api/training/*,/api/boost/*, and/api/chat/*proxy to the Python hardware backend.- Other
/api/*routes proxy to the Node race/betting backend.
The Node backend is the race authority. The Python backend is the hardware authority.
Path: Aedonys/Sol-Machine/frontend
Runs the public spectator page and admin page.
- Public UI:
http://localhost:3002/ - Admin UI:
http://localhost:3002/admin
Path: Aedonys/Sol-Machine/backend
Owns:
- race cycle state:
idle,starting,voting,finalizing,boost - bet intents and confirmations
- vote intents and confirmations
- internal race-scoped boost voting credits
- race result intake and bet settlement
- SQLite persistence
- devnet SOL payment verification and payout helpers
- bridge call to Python
/boost/triggerwhen a vote cycle enters boost
Path: Aedonys/Sol-Machine/hardware
Owns:
- BLE car scan/connect/disconnect/control
- 20 Hz control packet writer
- camera ingest and MJPEG/debug streams
- OpenCV/CNN perception loop
- turbo/boost state
- training sample capture
- OpenAI-powered crowd strategy chat
- Node.js
20.18+ - Python
3.11+ - Bluetooth-capable laptop for BLE car control
- Raspberry Pi camera/go2rtc setup or a local webcam test mode
- Optional: Phantom wallet and Solana devnet configuration
- Optional:
OPENAI_API_KEYfor crowd strategy analysis
Install frontend dependencies:
cd Aedonys/Sol-Machine/frontend
npm installInstall race backend dependencies:
cd Aedonys/Sol-Machine/backend
npm installCreate a Python environment for the hardware backend:
cd Aedonys/Sol-Machine/hardware
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Optional: install PyTorch (CPU build) only if you plan to use the CNN perception backend
pip install torch --index-url https://download.pytorch.org/whl/cpuCreate local environment configuration:
cd Aedonys/Sol-Machine
cp .env.example .envThen edit .env for your hardware, camera, Solana, and OpenAI settings.
Install frontend dependencies:
cd Aedonys\Sol-Machine\frontend
npm installInstall race backend dependencies:
cd Aedonys\Sol-Machine\backend
npm installCreate a Python environment for the hardware backend:
cd Aedonys\Sol-Machine\hardware
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txtCreate local environment configuration:
cd Aedonys\Sol-Machine
Copy-Item .env.example .envThen edit .env for your hardware, camera, Solana, and OpenAI settings.
Use three terminals.
Terminal 1, hardware backend:
cd Aedonys/Sol-Machine/hardware
source .venv/bin/activate
python main.pyDefault URL: http://localhost:3000
Terminal 2, race backend:
cd Aedonys/Sol-Machine/backend
npm startDefault URL: http://localhost:3001
Terminal 3, frontend:
cd Aedonys/Sol-Machine/frontend
npm run devDefault URL: http://localhost:3002
Tip: Backend boot takes ~30s while it tries the first RTSP connection. Requests are served normally during that window — it will retry in the background if the Pi/camera is offline.
Terminal 1, hardware backend:
cd Aedonys\Sol-Machine\hardware
.\.venv\Scripts\Activate.ps1
python main.pyDefault URL: http://localhost:3000
Terminal 2, race backend:
cd Aedonys\Sol-Machine\backend
npm startDefault URL: http://localhost:3001
Terminal 3, frontend:
cd Aedonys\Sol-Machine\frontend
npm run devDefault URL: http://localhost:3002
The $BOOST SPL token is already deployed on devnet (see addresses in the Judges Quick Intro). To redeploy or run the faucet locally:
cd Aedonys/Sol-Machine/solana
npm install
# Mint a fresh $BOOST token (idempotent — re-running loads existing keypairs/mint from disk)
npm run mint
# Airdrop $BOOST to a Phantom wallet (devnet)
npm run faucet -- <PHANTOM_PUBKEY>After minting, copy the printed mint/treasury addresses into your .env (BOOST_TOKEN_MINT, SOLANA_TREASURY_PUBKEY, SOLANA_TREASURY_ATA).
Devnet airdrops are rate-limited per IP per day. If
solana airdropfails, top up keypairs manually at https://faucet.solana.com.
The spectator UI and Node backend are deployed on DigitalOcean at https://solmachines.wiktor.uk. The Python hardware backend runs locally next to the RC car at the demo venue (BLE + camera require physical hardware) and connects to the deployed services over the network.
Shared or integration:
RACE_BACKEND_URL: Node-to-Python hardware backend URL. Defaults tohttp://localhost:3000.AEDONYS_BACKEND_URL: frontend rewrite target for the Node backend. Defaults tohttp://localhost:3001.NEXT_PUBLIC_RACE_BACKEND: browser-visible hardware backend URL for camera streaming. Defaults tohttp://localhost:3000.
Hardware/camera:
PORT: Python hardware backend port. Defaults to3000.PI_IP: Raspberry Pi address.GO2RTC_PORT: go2rtc HTTP port. Defaults to1984.RTSP_PORT: go2rtc RTSP port. Defaults to8554.RTSP_PATH: RTSP stream path. Defaults tocamera.USE_LAPTOP_CAMERA: set to1to use a local webcam.LAPTOP_CAMERA_INDEX: webcam index for local testing.
Perception:
PERCEPTION_BACKEND:opencvorcnn.PERCEPTION_HZ: perception loop rate.CAMERA_ROTATE_DEG:0,90,180, or270.OPENCV_THRESHOLD,OPENCV_ROI_TOP,OPENCV_DEADBAND: OpenCV line follower tuning.CNN_WEIGHTS_PATH: optional path to CNN weights.
Boost and strategy:
BOOST_DURATION_SEC: hardware boost duration.OPENAI_API_KEY: enables crowd strategy analysis.CROWD_TRIGGER_N: number of chat messages before strategy analysis. Defaults to5.
Race/backend:
PORT: Node backend port when set in the backend process. Defaults to3001.DB_PATH: SQLite database path. Defaults to./data/sol-machine.sqlite.APP_MODE:demoordevnet.DEMO_MODE: set tofalseto require real verification paths.AUTO_FAKE_RACE_RESULTS: local helper for automatic mock race settlement.ADMIN_TOKEN: optional token required for admin endpoints outside relaxed local development.
Solana/devnet:
SOLANA_RPC_URL: defaults to devnet.SOLANA_CLUSTER: defaults todevnet.TREASURY_WALLET: public treasury wallet for Node devnet SOL flows.TREASURY_SECRET_KEY: treasury private key for payouts.TOKEN_SYMBOL: display symbol, defaults toBOOST.TOKEN_MINT: optional token mint address.SOLANA_TREASURY_PUBKEY,SOLANA_TREASURY_ATA,BOOST_TOKEN_MINT,BOOST_TOKEN_DECIMALS: used by the hardware Solana listener/token flow.
Frontend routes through Next rewrites, so prefer /api/... from UI code.
Node race backend:
GET /api/configGET /api/cycle/currentGET /api/cycle/resultPOST /api/race/startPOST /api/bet-intentPOST /api/bet-submitGET /api/bet/current?wallet=...GET /api/bet/latest-settled?wallet=...POST /api/vote-intentPOST /api/vote-submitGET /api/boost-balance?wallet=...GET /api/boost-power/currentPOST /api/race/resultPOST /api/admin/reset-race
Python hardware backend:
GET /healthGET /cars/knownPOST /car/scanPOST /car/connectPOST /car/disconnectGET /car/statusPOST /car/autonomousPOST /car/controlPOST /boost/triggerGET /boost/statusGET /camera/infoGET /camera/snapshotGET /camera/stream.mjpegGET /camera/debugPOST /training/sampleGET /training/statsPOST /training/clearPOST /training/runPOST /training/dagger_correction— DAgger online correction ({label: 0|1|2}for left/straight/right)POST /chat/messageGET /chat/messagesGET /chat/strategyWS /camera/ws— pull-mode JPEG stream (client sends"ready", server returns current frame). Eliminates TCP-buffer lag from MJPEG push streams.
While the car drives autonomously with the CNN perception backend, pressing A/W/D in AUTO mode submits a human correction:
| Key | Label | Meaning |
|---|---|---|
| A | 0 | steer left |
| W | 1 | go straight |
| D | 2 | steer right |
Each correction saves the current frame + label to training/data/ and applies a 400ms steering override. After DAGGER_RETRAIN_EVERY corrections (default 20), the CNN auto-retrains in the background via train.py and hot-reloads weights — no server restart required.
The driver UI (hardware/static/index.html) and admin console show live correction count and "Retraining…" / "Model updated ✓" status.
- Spectator flow (deployed): Open https://solmachines.wiktor.uk, connect Phantom (devnet), and observe the live race cycle and BOOST button.
- Solana payment → physical action: A click on BOOST sends 1
$BOOSTSPL token to the treasury ATA. The PythonSolanaListenerwatches the ATA viaaccountSubscribeWebSocket and triggers a turbo packet over BLE to the RC car within ~1–2 seconds. - Crowd-driven AI strategy: Type messages in the chat panel — every
CROWD_TRIGGER_Nmessages the OpenAIo4-miniagent re-reads the chat and emits a structuredCarStrategyJSON applied to the live perception loop. - Online learning (admin console): With perception set to
cnn, drift the car off the line, pressA/Dto correct — watch the DAgger counter increment and the model hot-reload after 20 corrections. - Perception tuning:
http://localhost:3000/camera/debugshows the live binary threshold, ROI, and centroid overlay used by the OpenCV backend.
Frontend build:
cd Aedonys/Sol-Machine/frontend
npm run buildNode syntax check:
cd Aedonys/Sol-Machine/backend
node --check server.jsPython syntax check:
cd Aedonys/Sol-Machine/hardware
python -m py_compile main.py crowd_agent.py boost.py solana_listener.py perception/base.py perception/opencv_line.py perception/cnn_line.pyFrontend build:
cd Aedonys\Sol-Machine\frontend
npm run buildNode syntax check:
cd Aedonys\Sol-Machine\backend
node --check server.jsPython syntax check:
cd Aedonys\Sol-Machine\hardware
python -m py_compile main.py crowd_agent.py boost.py solana_listener.py perception\base.py perception\opencv_line.py perception\cnn_line.py- Keep the Node and Python backends separate unless there is a strong reason to merge them.
- Node is responsible for authoritative race, betting, voting, and settlement state.
- Python is responsible for hardware, camera, perception, and physical boost execution.
- The current direct bridge is Node calling Python
/boost/triggerwhen a vote cycle resolves into boost. - The canonical Node settlement path is
recordRaceResultAndSettleBetsTx(). - Do not reintroduce separate settlement functions for manual/admin results.
- Hardware behavior depends on BLE availability, car firmware, camera setup, and local network conditions.
- Crowd strategy is in-memory and requires
OPENAI_API_KEY. - Solana code is devnet/demo oriented.
- Public frontend currently focuses on winner-style betting, while backend support for trifecta settlement exists.