Show up every day. Win the week.
MiniStreak is a weekly on-chain transaction streak competition on Celo. Pay 0.10 USDT to enter, send any outgoing transaction each day to keep your streak alive, and split the pot at week's end. Built for MiniPay.
Live demo: ministreak-fe.vercel.app · Repository: github.com/djokerops/ministreak
- Open in MiniPay — the app auto-connects your wallet. No "Connect Wallet" button, no signatures.
- Enter the round — pay 0.10 USDT to join this week's pot. Weekly rounds run Monday 00:00 → Sunday 23:59 UTC.
- Build your streak — send any outgoing transaction each day (not a self-send). The oracle picks it up and extends your streak.
- Climb the board — ranked by longest streak, then tx count, then unique recipients. Ties broken by cumulative USDT volume.
- Miss a day, you're out — streak resets to zero. Show back up the next round.
- Round resolves — winners split the pot 50 / 30 / 20 (minus a 5% protocol fee). Fewer than 3 players? All entry fees are refunded automatically.
- MiniPay-native — auto-connect via injected provider, no
personal_sign/eth_signTypedData, USDT/USDC/USDm only (no CELO surfaced in the UI) - Pseudonym identity — deterministic readable aliases (
BraveTiger-7F2A) instead of raw0x…addresses across the wallet badge and leaderboard - Balance-aware entry CTA — detects low USDT and routes to MiniPay's
add_cashdeeplink; if you hold USDC or USDm instead, shows a "swap to USDT first" explainer - Celo Builder Code attribution — every on-chain action tags calldata with the issued code
celo_0xd7zeusvia@gigahierz/builder-codes(ERC-8021) - Oracle-backed streak validation — off-chain scanner verifies daily activity from public RPC, submits on-chain proofs through a role-gated
StreakOracle - Refund path — if fewer than 3 players enter, the vault refunds every entry; no need to claim
- Subgraph indexing — The Graph provides fast leaderboard reads with on-chain RPC fallback
- Light editorial theme — cream paper aesthetic, deep forest + gold accents, readable type at proper sizes (no pixel font)
(subject to change)
The on-chain layer is two contracts (no proxies, no upgradeability — fixed once deployed):
MiniStreak— vault that holds entry fees, tracks per-player streak/tx-count/uniqueness, resolves payouts. Role-gatedORACLE_ROLEfor streak submissions.StreakOracle— thin attestation contract that the off-chain oracle calls to record validated daily activity. Forwards to the vault viarecordStreak.- Token: USDT (6 decimals). Unowned-pixel-style payment? No — flat 0.10 USDT entry, vault custodies the pot.
- Round: 7 days, Monday 00:00 → Sunday 23:59 UTC. New round opens automatically.
- Payout: 50 / 30 / 20 of the distributable pot, after a 5% protocol fee to the treasury.
- Tiebreaker: cumulative USDT volume across qualifying daily transactions.
Mainnet (Celo, chain ID 42220)
| Contract | Address |
|---|---|
| MiniStreak vault | 0xcd125da0EC85c8414D39fa94011b607C2A5f17e5 |
| StreakOracle | 0x2c08420187F96a69E0aB64a1507282786E4f474e |
| USDT | 0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e |
The repo is a polyglot monorepo: Solidity (Hardhat), Next.js, a Node oracle, and a subgraph. Each package installs independently.
# 1. Smart contracts — compile + test
cd contracts
npm install
npm run compile
npm test
# 2. Frontend — Next.js dev server
cd ../frontend
npm install
NEXT_TELEMETRY_DISABLED=1 npm run dev # http://localhost:3000
# 3. Oracle service — local scanner
cd ../oracle-service
npm install
npm run dev
# 4. Subgraph (optional — frontend falls back to RPC reads)
cd ../subgraph
npm installEach package has its own .env.example. Copy to .env and fill in deployer/oracle private keys and RPC URLs.
cd contracts
npm run deploy:sepolia # Celo Sepolia testnet
npm run deploy:mainnet # Celo Mainnet
npm run verify:sepolia # Blockscout verification (no API key required)
npm run verify:mainnet # Celoscan verificationAfter deploying, copy the addresses into frontend/.env.local (NEXT_PUBLIC_VAULT_ADDRESS, NEXT_PUBLIC_ORACLE_ADDRESS, NEXT_PUBLIC_USDT_ADDRESS, NEXT_PUBLIC_CHAIN_ID).
contracts/ Solidity + Hardhat (TypeScript)
src/
MiniStreak.sol Vault: entries, streaks, payouts
StreakOracle.sol Role-gated attestation forwarder
MockERC20.sol USDT mock for tests / local node
scripts/
deploy.ts Network-aware deploy (sepolia / mainnet)
deploy-local.ts Hardhat local node deployment
verify.ts Blockscout / Celoscan verification
test/
MiniStreak.test.ts Hardhat + chai (48 tests, all passing)
deployments/ Per-network address manifests (committed)
frontend/ Next.js 14 App Router
app/
page.tsx Home — pot, timer, streak, leaderboard top 5, how to play
leaderboard/page.tsx Full standings + per-round stats
terms/page.tsx Terms of Service (placeholder)
privacy/page.tsx Privacy Policy (placeholder)
api/oracle/route.ts Vercel cron endpoint (daily streak scan)
api/health/route.ts Liveness probe
components/
EntryButton.tsx Pay-to-enter CTA with balance-aware states
Leaderboard.tsx Hairline-divided rows, medals on top 3
StreakCard.tsx Day-counter with "today's in" pill
RoundTimer.tsx Live countdown to round close
WalletBadge.tsx MiniPay auto-connect, pseudonym pill
BottomNav.tsx Home / Board tabs
Footer.tsx Inline Terms · Privacy · Support links
hooks/
useEnterRound USDT approve + enterRound, gas-buffered
useEntryEligibility Reads USDT/USDC/USDm balances → ready/swap/deposit
useLeaderboard Subgraph query with on-chain RPC fallback
useCurrentRound,
usePlayerStats,
useTodayStreak On-chain reads via wagmi
lib/
contracts.ts Addresses + ABIs + deeplinks
pseudonym.ts FNV-1a hash → readable alias
builderCode.ts ERC-8021 attribution suffix (celo_0xd7zeus)
wagmi.ts Chain config (Celo / Sepolia / local)
oracle-service/ Node.js + cron streak scanner
src/
scanner.ts Pulls outgoing txs per player via Celo RPC
submitter.ts Validates + calls StreakOracle.recordStreak
db.ts SQLite — dedupe submitted (player, day) pairs
config.ts Loads env, validates required vars
index.ts Cron loop (default: hourly)
subgraph/ The Graph hosted indexer
schema.graphql PlayerEntered, StreakRecorded, RoundResolved
src/mapping.ts Event handlers → entities
docs/superpowers/ Implementation plans + design specs
- Framework: Next.js 14 (App Router, RSC where possible)
- Language: TypeScript end-to-end (Solidity for contracts)
- Styling: Tailwind CSS + CSS variables, custom utilities for pills/cards
- Fonts: DM Sans (app), Fraunces (legal pages), JetBrains Mono (addresses)
- Wallet: wagmi v2 + viem v2, injected for MiniPay, WalletConnect optional fallback
- Smart contracts: Solidity 0.8.20, Hardhat 2.22, OpenZeppelin 5.x,
viaIR: true - Oracle: Node + ethers v6, SQLite for de-duplication, node-cron for scheduling (or Vercel cron in production)
- Indexer: The Graph (hosted), GraphQL queries from the frontend
- Chain: Celo Mainnet (42220) / Celo Sepolia (11142220) — legacy tx mode required
- Deployment: Vercel (frontend), self-hosted oracle or Vercel cron, The Graph Studio (subgraph)
- Font: DM Sans (400 / 500 / 600 / 700) across the app — Fraunces stays on
/termsand/privacy - Light theme (no dark mode):
- Paper background
#FAF6ECwith a subtle dot-grain pattern - Paper tint
#F3EDD8for the pot hero, timer cells, and "How to play" card - Ink
#1B1A17primary,#6B6452secondary,#A8A192faint - Forest green
#1B6B3Ffor primary actions and active states; deep#0F4A2Aon hover - Trophy gold
#B8842Bfor low-balance warnings and accent highlights - Coral
#C44536for error states
- Paper background
- Cards: surface white with hairline
#E5DEC8borders + soft warm shadow, or paper-tint variant for muted blocks - Buttons: rounded-full pills, full width,
inline-flex justify-centerso both<button>and<a>center identically - Numbers: tabular nums + tight letter-spacing for the pot, streak, and timer
- Layout: 360-px-first, max-width 28rem centered, generous vertical rhythm