Hartii Games
Hartii Games is a neon-dark, 10-game skill arcade at hartiigames.com. Free play is always available; ranked play stakes a small USD-priced amount (paid in QUAI) into a per-game, on-chain prize pool. A sibling read-only dashboard, Biome, aggregates live numbers from Games plus the other Hartii products.
Architecture
npm workspaces, one repo (hartii-games):
apps/hub— the site itself. Vanilla JS + Canvas 2D, no framework.src/main.jsis the hub shell; each game lives atgames/<name>/{game.js,sim.js}behind a sharedgames/_shared/shell.jscontract between the hub and the game code.apps/biome— a separate static site + three tiny read-only Functions (functions/api/chain.js,ecosystem.js,prices.js), deployed on its own (hartii-biomeCloudflare Pages project) at hartiibiome.com. It holds no wallet-signing or money logic of its own — that stays on hartiigames.com.packages/engine— deterministic core: seeded RNG, replay record/verify. Determinism is a hard product invariant here: the same{seed, input log}must reproduce the same score everywhere, so a server-side replay can verify a client's claimed score without trusting the client.packages/arcade-sdk— wallet + chain interaction.workers/settlement— score verification and payout math for the monthly settlement job.contracts/— Hardhat project: one prize-pool contract per game, plus a small token/sale/ cosmetics/marketplace stack.functions/— Cloudflare Pages Functions (api/) backing the hub.
Live URLs
| Hub (games, ranked play, profile) | hartiigames.com |
| Public API base | https://hartiigames.com/api/ |
| Biome (read-only ecosystem dashboard) | hartiibiome.com |
Data flow
Free play: a game's sim.js runs entirely client-side against a shared daily seed; the
score is posted to /api/play/track and lands on a KV-backed leaderboard. No chain interaction.
Ranked play (see contracts and api for exact mechanics):
- Client requests a price quote for a stake tier, pays it as a plain QUAI transaction straight
to that game's
MonthlyGamePayoutspool contract (enterRanked()or a bare transfer). - Client calls
POST /api/ranked/enterwith the tx hash; the API verifies the transaction on-chain (destination, sender, value within a tolerance band of the tier's USD quote at the current QUAI price) and, if it checks out, issues a fresh deterministic run seed. - Client plays the run against that seed and calls
POST /api/ranked/submitwith the recorded input log and claimed score; the server replays the run itself with the same seed and compares scores — a mismatch is rejected, never trusted from the client. - Once a month, the owner (a manually-signed, non-automated wallet) reviews the off-chain
verified leaderboard and calls
setMonthlyWinState()on each game's pool contract to allocate the prize split as per-winner claimable balances. - Winners pull their own payout with
claimPayout()— the contract never pushes funds to anyone, so no single winner's misbehaving address can block the others' payouts.
Biome: its three Functions simply re-fetch and cache public data from Games, Gallery and Labs (and MEXC/the Quai RPC directly) server-side and re-serve it — it originates nothing.
Live contracts (Quai mainnet, Cyprus-1)
Addresses read from wrangler.toml/contracts/deployed.json, confirmed live via quai_getCode.
Prize pools — one MonthlyGamePayouts deployment per game:
| Game | Pool address |
|---|---|
hash-wars | 0x0056C742a880eC0A55b87Db3a893F2a92E94dD89 |
hex-breaker | 0x0053907D0BB2058c7963835a684ABCd34B61c315 |
gravity-flip | 0x0000D913fe9a98bB2D45941401786724AFf3428c |
orbit-lock | 0x0060b1e1F0EF6e673Fb5dAB93b665eC57446a6a2 |
pulse-snake | 0x0064098E291FB66dA4DEa68f2106066A63023a73 |
shatter-stack | 0x0067525EF7c97002023C167b5154C03D84b237b9 |
nova-storm | 0x005e167915E894a612700AcCE73543070c197f9F |
flux-hop | 0x0000F74169b09449F43c96E05aEEc3bBaA2D7D08 |
neon-drift | 0x0039EB50B9D4e704196C2440211b7896c1Fc91e7 |
blade-pong | 0x001a4ec265e9E2D364C65fC29b9eb16dC95542CA |
All ten confirmed live (non-empty quai_getCode). Only hash-wars currently accepts a ranked
entry — POST /api/ranked/enter rejects every other gameId with 403 — so the other nine
pools are deployed but not yet reachable through the paid-play flow. As of this check,
GET /api/config and GET /api/pools both report paidPlay: false: ranked play is currently
disabled by a global kill switch on production, even for hash-wars. Free play is unaffected.
HARTII token / cosmetics stack:
| Contract | Address | Role |
|---|---|---|
HartiiToken | 0x00356B9bc20Ea80C654D77655Da53ca07547c216 | Fixed-supply ERC-20, the arcade's cosmetic/loyalty currency |
HartiiSale | 0x00483bE6EAaA8015130b216e06d8f70723dF822D | QUAI → HARTII sale at an admin-set rate |
HartiiCosmetics | 0x007fDe17CbA1Fe1750906F08f64fEf44195702eA | ERC-1155 cosmetics, bought with HARTII or won as tournament editions |
HartiiMarketplace (cosmetics) | 0x0034D51cc6162E27bCfDce5E276d92Eb563bb73C | Peer-to-peer resale of cosmetics, priced in HARTII |
All four confirmed live. Cosmetics are earned or bought, never affect gameplay — a product rule
stated directly in the repo's AGENTS.md.
See contracts for the full MonthlyGamePayouts interface and trust model, and
api / integrate for the HTTP surface and code examples.
Biome
hartiibiome.com is a small, separate, read-only static site
(apps/biome) that shows live cross-product numbers — QUAI/USD price, chain stats, and an
"ecosystem" summary that fans out to Games, Gallery and Labs' own public endpoints server-side.
Its wrangler.toml states its scope directly: "Biome serves its own three read-only Functions.
Wallet signing/pinning remains on hartiigames.com; do not inherit Games money configuration or
bindings here." It has no contracts and no write endpoints of its own — see
api for its three routes.