Skip to content

Repository files navigation

Crow

A crypto sportsbook and casino, built as a full-stack demo. It pulls live sports odds from The Odds API and adds four in-house, provably-fair games — Crash, Roulette, Jackpot and Dice — that run in real time over WebSockets. React + TypeScript on the front end, Node + TypeScript on the back.

Portfolio/demo project. Play money only, no real wagering, not affiliated with any operator or with The Odds API. 18+.

Crow lobby


What's inside

  • Sportsbook — live odds for 40+ sports (moneyline, spreads, totals) with a parlay bet slip; stakes and payouts are validated on the server.
  • Crash — a shared multiplier that climbs until it busts; cash out manually or set an auto-cashout.
  • X-Roulette — a 15-slot wheel (red / black / 14× green) that spins for the whole lobby every 12 seconds.
  • Jackpot — players buy into one pot; the winner is drawn with probability proportional to their stake.
  • Dice — instant rolls with an adjustable win chance.
  • Rewards — XP and levels, live rakeback, daily/weekly bonuses, and a wager race.
  • Provably fair — every original round commits to a SHA-256 hash up front and reveals the seed afterwards, so outcomes can be verified.
  • No API key needed — without one, the server serves deterministic mock odds in the exact shape of the real API, so everything works offline.

Screenshots

Sportsbook Crash
Sportsbook Crash
Casino X-Roulette
Casino Roulette
Jackpot Rewards
Jackpot Rewards

Tech

  • Front end: React 18, Vite, TypeScript, Tailwind CSS, Zustand, Framer Motion
  • Back end: Node 20, Express, ws, TypeScript (run with tsx)
  • Data: The Odds API v4, with a built-in mock fallback
  • Fairness: Node crypto — SHA-256 commitments + HMAC-SHA256 outcomes
  • Monorepo via npm workspaces; shared API/WebSocket types in shared/types.ts

Getting started

Requires Node 20+.

npm install
cp .env.example .env     # works out of the box in mock mode
npm run dev              # client on :5173, API on :4000

Open http://localhost:5173. You're signed in automatically as a guest with demo credits.

To use real odds, get a free key at the-odds-api.com and set ODDS_API_KEY in .env, then restart.

For a production-style run (one port, server serves the built client):

npm run build
npm start                # everything on http://localhost:4000

Other scripts: npm run typecheck (whole monorepo), npm run seed (quick API smoke test), node scripts/screenshots.mjs (regenerate the screenshots above).

How it works

flowchart LR
  subgraph Client["Client · React + Vite + TS"]
    API["api.ts"]
    WS["ws.ts"]
  end
  subgraph Server["Server · Node + Express + ws"]
    REST["REST routes"]
    HUB["WebSocket hub"]
    GAMES["Game engines<br/>Crash · Roulette · Jackpot · Dice"]
    SVC["Services<br/>oddsApi · store · bonus"]
    PF["Provably fair<br/>SHA-256 + HMAC"]
  end
  ODDS[("The Odds API v4")]
  API -->|HTTP / JSON| REST
  WS <-->|live frames| HUB
  REST --> SVC
  HUB --> GAMES --> PF
  SVC -->|cached · mock fallback| ODDS
Loading

Live odds. The home feed fans out across the configured sports in one request. Each sport's odds are cached for a short TTL, so a busy lobby costs one upstream credit per sport per window rather than one per visitor. If a key is missing or a request fails, the same call returns deterministic mock data of the identical shape.

Real-time games. Each original is an EventEmitter running its own clock on the server. State transitions are pushed to subscribers over a single multiplexed WebSocket as { channel, type, data } frames (crash, roulette, jackpot, activity).

Provably fair. Commit-and-reveal: the server publishes SHA-256(serverSeed) before betting, derives the outcome from HMAC(serverSeed, clientSeed:nonce), then reveals serverSeed so anyone can re-check it.

flowchart LR
  A["1 · Commit<br/>publish SHA-256(serverSeed)"] --> B["2 · Bet<br/>clientSeed + nonce"]
  B --> C["3 · Derive<br/>HMAC → outcome"]
  C --> D["4 · Reveal<br/>serverSeed published"]
  D --> E{"Verify<br/>SHA-256 == hash?"}
Loading

Project structure

.
├── shared/types.ts          # API + WebSocket types shared by client and server
├── server/                  # Node + Express + ws (TypeScript)
│   └── src/
│       ├── index.ts         # bootstrap, routes, WS, game loops
│       ├── routes/          # auth · sports · casino · bonus · games
│       ├── services/        # oddsApi · store · bonus · sportsBetting · provablyFair
│       ├── games/           # crash · roulette · jackpot · dice
│       └── ws/hub.ts        # channel fan-out
└── client/                  # React + Vite + Tailwind (TypeScript)
    └── src/
        ├── lib/             # api.ts · ws.ts
        ├── store/           # Zustand store
        ├── components/      # Sidebar · TopBar · BetSlip · LiveTicker · …
        └── pages/           # Home · Sports · Casino · Crash · Roulette · Jackpot · Dice · Bonus

API quick reference

Base http://localhost:4000/api. Endpoints marked 🔒 need Authorization: Bearer <jwt>.

Method Endpoint Purpose
POST /auth/guest Start a demo session
GET /featured Multi-sport homepage feed
GET /sports/:key/odds Odds for one sport
POST /bets 🔒 Place a (parlay) bet
GET /casino/games Casino lobby
POST /casino/dice 🔒 Roll dice
POST /games/crash/bet 🔒 Join the crash round
POST /games/jackpot/enter 🔒 Enter the jackpot
GET /bonus 🔒 Bonuses & rakeback

Contact

Telegram — @Kei4650

License

MIT — see LICENSE. This is a non-commercial demonstration with no real money and no affiliation with The Odds API or any betting brand. Gambling is heavily regulated; don't deploy real-money play without the proper licensing.

About

Full-stack crypto sports betting & casino platform — live odds, realtime provably-fair games, dark-neon UI.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages