On-chain reputation for every Normie. A 0–100 score for all 10,000 Normies across four evidence-linked dimensions. Hover any card to see what's changed since the original — pixel-by-pixel drift, twin matches, AP yield potential.
Built for the Normies Hackathon.
- NormieRank — a credit score per token: rarity + pedigree + drift + AP yield, each with auditable evidence.
- Identity drift — Hamming distance between a Normie's current and original bitmap, surfaced on hover and in detail view.
- Twin finder — for any customized Normie, finds tokens whose original art most resembles its current state. Pre-computed top-3 per token.
- AP Market Map — Sankey of Action Point flows from burners to recipients, top-leaderboards, burn-tier pressure.
- Next.js 16 (App Router) + TypeScript + Tailwind v4
- SQLite (better-sqlite3) + Drizzle ORM
- d3-sankey for the AP flow viz
- Pure server components; bitmap-level Hamming distance via XOR + popcount on
Buffer
npm install
npm run db:migrate
npm run ingest # full crawl, ~7h at 58 rpm. resumes from cursor on crash.
npm run twins:compute # computes top-3 twins per live token. re-run after ingest.
npm run devA few helpful scripts:
npm run ingest:status— cursor + countersnpm run backfill— recovers any tokens that hit transientfetch failederrorsnpm run twins:compute— recompute twins after more tokens are ingested
The full ingest takes ~7h because the API is rate-limited to 60 rpm. Cursor is persisted in data/normies.db — kill and resume freely.
Each Normie's score is the sum of four 0–25 dimensions:
| Dimension | Method | Evidence |
|---|---|---|
| Rarity | inverse log frequency, summed across 8 trait categories | per-trait frequency %, rarest trait |
| Pedigree | owner's portfolio depth (singleton / collector / serious / whale) | owner address, holdings, whale flag |
| Drift | Hamming distance between current and original pixels (capped curve) | pixels changed, drift %, customized flag |
| AP Yield | level + AP balance (log) + burn-tier pressure (pixel count) | level, AP, pixel count, tier index |
Every score on the detail page exposes the full evidence object as JSON. Methodology is open and auditable — that's the point.
/— ranked grid; filter bylive / customized / whale-held, sort byrank / drift / AP / id/normie/:id— full breakdown: traits, dimensions, drift, twin grid, burns received, raw evidence/market— AP Sankey + top recipients/burners + burn tiers
- Pixels stored as
BLOB(200)rather than 1600-char strings — 8× smaller, makes Hamming distance an XOR+popcount over uint8 chunks (~20k normie pairs/second). - Burned tokens (1,776 of them) detected up-front via
/history/burned-tokens; the per-token ingest skips/ownerfor those (the API 500s on burned token owner lookup). totalActions, nottransferredActionPoints, is the real AP value in/history/burnsrows. The other field is reserved for a different mechanic and is mostly zero.- Rate limiter is a serial token-bucket gate; chained promises avoid race conditions across concurrent calls.
MIT, per the hackathon submission terms.