{"id":50586207,"url":"https://github.com/effectstream/kachina-colosseum","last_synced_at":"2026-06-05T06:30:53.668Z","repository":{"id":300148863,"uuid":"904872909","full_name":"effectstream/kachina-colosseum","owner":"effectstream","description":"Player vs player on-chain battle game built on the Midnight blockchain","archived":false,"fork":false,"pushed_at":"2026-05-12T18:46:54.000Z","size":21093,"stargazers_count":1,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-05-12T20:36:12.616Z","etag":null,"topics":["compact","midnightntwrk"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/effectstream.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-12-17T17:59:23.000Z","updated_at":"2026-05-12T18:47:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"3eb4106b-113c-4692-be00-c290cca44dda","html_url":"https://github.com/effectstream/kachina-colosseum","commit_stats":null,"previous_names":["paimastudios/pvp-arena","effectstream/kachina-colosseum"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/effectstream/kachina-colosseum","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/effectstream%2Fkachina-colosseum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/effectstream%2Fkachina-colosseum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/effectstream%2Fkachina-colosseum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/effectstream%2Fkachina-colosseum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/effectstream","download_url":"https://codeload.github.com/effectstream/kachina-colosseum/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/effectstream%2Fkachina-colosseum/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33932048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-05T02:00:06.157Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compact","midnightntwrk"],"created_at":"2026-06-05T06:30:52.837Z","updated_at":"2026-06-05T06:30:53.662Z","avatar_url":"https://github.com/effectstream.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PVP Arena — Kachina Kolosseum\n\nKachina Kolosseum is a blockchain-based turn-based PvP battle game built on the Midnight Network. Two players face off with teams of 3 heroes in a gladiatorial arena. Game moves are kept private using zero-knowledge proofs — commands are committed on-chain and only revealed after both players have submitted, preventing any front-running or move-snooping.\n\n## Repository Structure\n\n```\npvp-v2/\n├── frontend/               # Yarn monorepo\n│   └── src/\n│       ├── contract/       # Compact DSL smart contract + compiled ZK output\n│       ├── api/            # TypeScript layer for contract interaction (PVPArenaAPI)\n│       └── phaser/         # Phaser 3 browser game UI (scenes, wallet, batcher client)\n└── backend/                # Deno workspace\n    └── packages/\n        ├── midnight/       # Contract deployment, local Midnight chain, faucet\n        ├── node/           # Paima effectstream runtime (syncs on-chain state)\n        └── batcher/        # Party B HTTP service — balances \u0026 proves delegated txs\n```\n\n## Prerequisites\n\n- **Deno**\n- **Node.js** + **Yarn 4.1.0**: `corepack enable \u0026\u0026 corepack install --global yarn@4.1.0`\n- **Compact compiler v0.30.0** — install the correct binaries from Midnight docs\n\n## Local Development\n\n### Terminal 1 — Backend\n\n```bash\ncd backend\ndeno task -f @pvp-arena-backend/contract-pvp compact \u0026\u0026 deno task -f @pvp-arena-backend/node dev\n```\n\nWait until you see `finalized block {1}`, `finalized block {2}`, … before starting the frontend.\n\n### Terminal 2 — Frontend\n\n```bash\ncd frontend/src/contract \u0026\u0026 yarn install \u0026\u0026 npm run build\ncd ../api \u0026\u0026 yarn install \u0026\u0026 npm run build\ncd ../phaser \u0026\u0026 yarn install \u0026\u0026 npm run build-undeployed \u0026\u0026 npm run preview\n```\n\nThe game will be available at `http://localhost:4173/`.\n\n## Smart Contract\n\nThe game logic lives in a single Compact DSL contract:\n\n- **Backend source** (canonical): [`backend/packages/midnight/contract-pvp/src/pvp.compact`](backend/packages/midnight/contract-pvp/src/pvp.compact)\n- **Frontend copy** (compiled from the same file): [`frontend/src/contract/src/pvp.compact`](frontend/src/contract/src/pvp.compact)\n\n### Exposed Circuits (on-chain functions)\n\n#### Match lifecycle\n\n| Circuit | Caller | Description |\n|---|---|---|\n| `create_new_match(match_nonce, is_match_public, is_match_practice, now)` | P1 | Creates a new match. Derives a unique `match_id` from P1's public key + nonce. Returns the `match_id`. |\n| `join_match(now)` | P2 | Joins an existing match (identified by `current_match_id` witness). Registers P2's public key. |\n| `close_match()` | P1 or P2 | Closes a match that has not started yet (P1 only), or any practice match. P2 may also force-close if P1 times out during hero selection. Sets state to `tie`. |\n| `cleanup_match()` | P1 or P2 | Removes all on-chain ledger entries for a finished match, freeing storage. Only callable once the match is in a terminal state (`p1_win`, `p2_win`, or `tie`). |\n\n#### Hero selection — alternating draft\n\n| Circuit | Caller | Description |\n|---|---|---|\n| `p1_select_first_hero(first_p1_hero, now)` | P1 | P1 picks their first hero (equipment loadout). |\n| `p2_select_first_heroes(all_p2_heroes, now)` | P2 | P2 picks their first two heroes (sees P1's first hero first). |\n| `p1_select_last_heroes(last_p1_heroes, now)` | P1 | P1 picks their remaining two heroes (sees P2's two heroes). |\n| `p2_select_last_hero(last_hero, now)` | P2 | P2 picks their final hero (sees P1's full team). Triggers full pairwise damage-cache computation. |\n\n#### Combat — commit-reveal per round\n\n| Circuit | Caller | Description |\n|---|---|---|\n| `p1_commit_commands(nonce, now)` | P1 | P1 privately commits their 3 attack targets + stances as a ZK hash. Commands are never disclosed on-chain at this point. |\n| `p2_commit_commands(now)` | P2 | P2 submits their commands publicly (no need to hide since P1 already committed). |\n| `p1_reveal_commands(now)` | P1 | P1 reveals their commands. The circuit verifies they match the earlier hash, then resolves all damage, updates alive/dead state, and advances to the next round or sets a winner. |\n\n#### End-of-round outcomes\n\nAfter `p1_reveal_commands` the contract sets `game_state` to one of:\n- `p1_commit` — match continues, next round begins\n- `p1_win` / `p2_win` / `tie` — match over\n\n#### Timeout \u0026 surrender\n\n| Circuit | Caller | Description |\n|---|---|---|\n| `claim_timeout_win()` | P1 or P2 | Claims a win if the opponent has not acted within the 10-minute turn timeout. P1 can claim during P2's turns and vice versa. |\n| `surrender()` | P1 or P2 | Voluntarily concedes — opponent wins immediately. Only valid during active combat states. |\n\n### Pure Utility Circuits\n\nThese are stateless helper functions used by the UI and internally by the combat circuits:\n\n| Circuit | Description |\n|---|---|\n| `calc_stats(hero)` | Computes a hero's combined `TotalStats` (crush/pierce dmg \u0026 def, dex bonus, weight) from their equipment. |\n| `calc_item_dmg_against(stats, stance, enemy_stats, enemy_stance)` | Calculates net damage one hero deals to another given both stances. |\n| `calc_commit_for_checking(sk, commands, stances, nonce)` | Recomputes a commit hash client-side (for UI to verify a resumed game's commit is still valid). |\n| `derive_public_key(sk)` | Derives a player's on-chain public key from their private secret key. |\n| `hack_to_hero(hero)` / `hack_to_item(index)` / `hack_to_armor(index)` | Convert integer indices to typed enums (`ITEM`, `ARMOR`, `Hero`). Used because Compact doesn't support passing enums directly from the frontend. |\n\n### Key Types\n\n- **`Hero`** — equipment loadout: `rhs`, `lhs` (weapons), `helmet`, `chest`, `skirt`, `greaves` (armor)\n- **`ITEM`** — `nothing`, `axe`, `shield`, `bow`, `sword`, `spear`\n- **`ARMOR`** — `nothing`, `leather`, `metal`\n- **`STANCE`** — `defensive` (×2 dmg), `neutral` (×5), `aggressive` (×8)\n- **`GAME_STATE`** — state machine values driving turn order\n\n\n## Deploying \u0026 Launching in Preprod \u0026 Mainnet\n\n```sh\n# Start Proof Server\ndeno task -f @pvp-arena-backend/midnight-contracts midnight-proof-server:start\n\n# Deploy Contracts\nMIDNIGHT_WALLET_MNEMONIC=\"word1 ... word12\" MIDNIGHT_NETWORK_ID=preprod MIDNIGHT_STORAGE_PASSWORD=YourPasswordMy1! deno task -f @pvp-arena-backend/midnight-contracts midnight-contract:deploy\n```\n\nOnce you have the contract address, you need to patch the frontend.\n```sh\ndeno task -f @pvp-arena-backend/midnight-contracts contract-pvp:patch-frontend:testnet\n```\n\nNow you can start the backend service.\nIf it's the first run, you should set the start block height to the current block height.\n\n```sh\ncurl -s -X POST \\\n  'https://indexer.preprod.midnight.network/api/v3/graphql' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"query\":\"{ block { height timestamp } }\"}' | jq\n\n\u003e {\n  \"data\": {\n    \"block\": {\n      \"height\": 690163,\n      \"timestamp\": 1773883812000\n    }\n  }\n}\n```\n\nand update\n```ts\n    .addParallel(\n        (networks) =\u003e (networks as any).midnight,\n        (_network, _deployments) =\u003e ({\n          name: \"parallelMidnight\",\n          type: ConfigSyncProtocolType.MIDNIGHT_PARALLEL,\n          startBlockHeight: 690163,\n          pollingInterval: 6000,\n          delayMs: 0,\n          indexer: midnightNetworkConfig.indexer,\n          indexerWs: midnightNetworkConfig.indexerWS,\n        }),\n      )\n```\n\nYour DB must be running.\n\n```sh\ndeno task -f @pvp-arena-backend/node testnet\n```\n\nNow your frontend \n```sh\ncd frontend/src/contract \u0026\u0026 yarn install \u0026\u0026 npm run build\ncd ../api \u0026\u0026 yarn install \u0026\u0026 npm run build\ncd ../phaser \u0026\u0026 yarn install \u0026\u0026 npm run build-testnet \u0026\u0026 npm run preview\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feffectstream%2Fkachina-colosseum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feffectstream%2Fkachina-colosseum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feffectstream%2Fkachina-colosseum/lists"}