尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗A daily typing competition living inside MiniPay (Opera's wallet) on Celo — race a 45-second passage, get ranked by speed and accuracy, and the daily #1 wins the USDT prize pool, paid on-chain.
Live: typerush.fun
Built in Colombia
TypeRush is a casual mobile typing game with real stablecoin prizes, running inside MiniPay
on Celo mainnet. From a home lobby the player picks a mode (es/en) and a daily challenge,
then types a passage against a 45-second timer. The app measures WPM, accuracy, errors,
corrections and a final score, and ranks every player against everyone else who raced the same
mode that day.
The whole interface is bilingual (Spanish/English) and independent from the typing mode: you can read the app in English while typing a Spanish passage, or vice versa.
window.ethereum, alongside external wallets
(RainbowKit/wagmi) and an optional embedded wallet via Privy.Each mode (es/en) has a set of challenges built from curated passages. A race lasts 45 seconds;
per-character feedback marks correct/incorrect input live. Score is computed as:
mistakePenalty = Math.max(0.7, 1 - mistakeCount * 0.03) // soft penalty, up to −30%
score = Math.round(wpm * accuracy * progress * mistakePenalty * 100) // wpm = (correctChars / 5) / minute
The player's best score per challenge is kept in localStorage; every ranked race is also
persisted to Supabase for the leaderboard and profile history.
The entry fee, the pool and the payout are handled entirely on-chain by TypeRushGameV3,
deployed and verified on Celo mainnet (chainId 42220).
| Contract | TypeRushGameV3 |
| Address | 0xD8287809e0D68E7e50D0D962f11Eb72150F48d39 |
| Network | Celo mainnet · chainId 42220 |
| Entry token | USDT (0.10 per paid play) |
| Protocol fee | 20% of each entry (the rest funds the pool) |
| Payout model | Push — the operator calls settle(day, mode, winner, tokens) and the prize leaves for the winner's wallet in that same transaction. There is no separate claim step. |
settle only pays a wallet that actually has a recorded play for that day/mode on-chain
(played[day][mode][winner]), and rollover moves an unplayed pool forward untouched so a quiet
day never drains the prize. A seeding job tops each mode's pool up to a floor of 0.30 USDT so
the lobby never shows an empty pot.
Contract source lives in contracts/src/TypeRushGameV3.sol; see contracts/README.md for the
Foundry build/test/deploy workflow.
The live ranking for the open round is read from the same table the settlement robot uses
(v3_results, filtered by the contract's own currentDay()), so what the UI shows and what the
contract will actually pay always agree. Each player is ranked by their best race of the day; no
wallet address is ever sent to the browser — only an opaque per-round identifier, since who played
is already public on-chain. Historial and Perfil also show past rounds and a wallet's own results
history.
NEXT_PUBLIC_PRIVY_APP_ID is configured; without
it the app simply runs on MiniPay + external wallets.Every race, free or paid, is backed by a signed on-chain transaction, and scoring is fully server-authoritative:
play(mode, token) on the contract./api/plays reads the transaction receipt and only accepts a PlayRecorded log emitted by the
game contract itself — player, day, mode and free/paid all come from that log, never from the
client. Only after that check does the server hand back the passage to type./api/results recomputes WPM/accuracy/score from the stored passage, with plausibility clamps
(WPM ceiling, typed length can't exceed the passage, elapsed time is clamped to the race length,
plays expire).lib/settleV3.ts, invoked by /api/cron/settle-v3 on a Vercel cron
(00:10 / 00:25 / 00:45 UTC — 7:10 / 7:25 / 7:45 p.m. Colombia) and mirrored by a GitHub Actions
backup (settle-v3.yml, scripts/settle-v3.mjs). It picks the day's #1 per mode from
v3_results, calls settle() (or rollover() if nobody played), and tracks each attempt's state
(pending/processing/broadcast/paid/failed/rollover) so a transaction that was sent but not yet
confirmed is never retried as if it failed.scripts/seed-v3.mjs (GitHub Actions workflow seed-v3.yml, hourly) tops up
each mode's USDT pool to the floor once the previous day is settled. It only ever tops up — running
it more than once cannot add money twice.contracts/)next/fontnpm install # first time only
npm run dev # http://localhost:3000
By default the app is fail-closed like production: it expects a real wallet signature and a
configured Supabase project. To try a race locally without either, copy .env.example to
.env.local and set NEXT_PUBLIC_APP_ENV=development — races then run with no charge, no
ranking and no signing (lib/devPractice.ts). Never set this in a deployed environment: it would
let anyone play for free.
Build / type-check:
npm run build
Lint:
npm run lint
Unit tests (no external dependencies) and end-to-end checks:
npm test
npm run test:e2e
MiniPay requires HTTPS and a real device (emulators don't work). Expose your local server:
npx ngrok http 3000
Open the HTTPS ngrok URL on a phone with MiniPay installed, in Developer Mode → Use Testnet/Load
Test Page — the wallet injects window.ethereum automatically.
app/
layout.tsx — fonts, metadata, viewport
page.tsx — lobby + game states (idle → countdown → racing → finished)
historial/ — past rounds + winners history
perfil/ — wallet, alias, preferences, personal results
api/ — plays, results, ranking, history, settlement cron, welcome gas
components/
lobby/ — daily challenge card, leaderboard preview, how-to-play
profile/ — profile card, wallet balances, prizes, activity
CountdownScreen · RaceScreen · TypeField · Track · StatBlock · ResultScreen
RoundRanking · FullRanking · PlayV3Button · ClaimBanner · AppShell · BottomNav
hooks/
useTypeRush.ts — game state machine
useModeRanking.ts — live ranking of the open round
usePrizePools.ts — on-chain pool amounts + countdown to the daily close
lib/
i18n/ — UI language (independent from the typing mode)
game.ts — pure scoring logic + local best-score storage
passages.ts — modes, challenges and passage text
contractsV3.ts · playV3.ts · poolsV3.ts · settleV3.ts — GameV3 wiring
gamePeriod.ts — the daily reset window
winners.ts · leaderboard.ts · history.ts · roundRanking.ts
wallet.ts · walletSession.ts · operator.ts · supabase.ts
scripts/
settle-v3.mjs · seed-v3.mjs — the settlement and seeding robots
contracts/ — Foundry project: TypeRushGameV3 (active contract)
supabase/ — SQL schema, applied by hand in the Supabase SQL editor
Made with 💚 for the Celo / MiniPay ecosystem.