Inspiration

Prediction markets ask people to put a price on the future. But what happens when someone already knows the answer? At VTHacks 14 we asked a simple question: could we check for conflicts of interest before a trade happens, instead of only investigating suspicious activity afterward? Real markets handle this with policy documents and after-the-fact enforcement. We wanted the restrictions to live in the trade path itself — evaluated on every trade, before money moves, with a receipt that can't be rewritten. The name is playful; the problem behind it is serious.

What it does

Not An Insider is a prediction market gated by verified identity. Traders register as ANS (Agent Name Service) agents and declare their affiliations. Every trade is cryptographically signed in the browser and then passes six enforcement gates, in order:

  1. Signature — canonical payload signed client-side; the server verifies against the ANS-registered public key and never sees a private key.
  2. Replay protection — each nonce is accepted exactly once.
  3. Live ANS registry — the trader's registration must be ACTIVE and unexpired at trade time, not just at signup.
  4. Affiliation + age — a trader affiliated with a market's restricted party is blocked; minors are barred from every market outright.
  5. Solvency — the wallet must actually cover the trade.
  6. Timing — trades near declared material events are flagged.

Any gate fails: the trade is BLOCKED, no money moves, and the block itself is written into a hash-chained audit trail alongside every allowed trade. Each entry carries hashPrev/hash, so replaying the chain exposes any edit or deletion. Positions re-price live, and a signed close-out sells the whole position back to the pool at the current displayed price — because a restricted identity should always be able to exit, just never to enter.

The demo example: four agents, each with their own ANS registration and validation tokens. trader1 (Eleanor, VA politician household) is banned from 2 of the 9 markets — the Virginia governor election and the congressional-map market — because of her household's political affiliation. trader2 (Marcus, VT athletics) is banned from 2 of 9 — both Hokies game markets — because of his athletics affiliation. trader3 (Timmy, age 5) is banned from all 9 because the age gate bars minors outright. trader4 (Dario, Anthropic staff) is banned from 3 of 9 — the three Claude Opus release-date markets — because of his staff affiliation. A clean account trades all 9.

How we built it

Next.js + TypeScript API routes, with HTML/CSS/JS pages. Supabase PostgreSQL stores identities, markets, nonces, and decisions; the audit chain and pool accounting are stored procedures. Identity runs on GoDaddy's ANS registry: each demo trader is a registered agent (ans://v1.0.0.<name>.not-an-insider-just-lucky.biz), and gate 3 is a live registry lookup, not a cached flag. Money runs on the Capital One Nessie API: buys move wallet → pool, close-outs refund pool → wallet. Pricing is parimutuel off pool shares; an empty pool quotes 50¢. Polymarket's public API provides live reference markets; we never execute orders there. Clients sign with WebCrypto. We collaborated over GitHub, tested with Vitest, and deployed to Vercel with server-side environment variables.

Challenges we ran into

Payment coordination was the hardest part. A payment request and a database update are separate operations, so handling partial failures reliably requires more than a successful API response — the system has to fail closed when a rail is down, and money must never move on a maybe. The second challenge was keeping the price a position marks at identical to the price it settles at, while live P/L re-marks every 10 seconds. Finally, making the six gates agree on what a trade means: identity validation, market rules, account state, and payment handling were built somewhat independently and had to converge on one definition of "allowed."

Accomplishments that we're proud of

The audit trail records blocked trades too — you can watch a prohibited trade get rejected and see its receipt, and any judge can re-verify the chain. Both external integrations are real and working tonight, not stubs:

  • ANS: every demo trader is a registered agent in GoDaddy's registry, and gate 3 validates lifecycle status live on each trade.
  • Nessie: real ledger movement today on the market pool account from our example trades — buys posted as Bought $2,500 on 'Will Virginia Tech win its next Hokies game?' (one of our demo markets), close-outs posted back as Refund of 2 cleared trades on account closure. The profile page shows the wallet's live balance and ledger.

We also shipped a public deployment where the API docs describe exactly the five endpoints that exist — GET /api/markets, GET /api/agents/:id, POST /api/trades, POST /api/positions/close, GET /api/audit — and a judge can open any GET in a browser tab and get live JSON.

What we learned

Identity verification and permission to trade are different problems: a valid signature establishes control of a key, not eligibility for a market. We also learned that frontend state is not a security boundary, payment success is not the same as transaction completion, and enforcement that lives outside the transaction path is decoration — the hard part isn't checking boxes, it's ordering them so money never moves on a maybe.

What's next for Not An Insider

Affiliations are currently declared, not attested — the honest soft spot of this prototype. The growth path is employer- and league-issued attestations, with ANS revocation as the consequence layer. Beyond that: resolved-market settlement, partial position closes, and richer explanations of trade decisions for users. Longer term, we want to explore how identity-aware screening could make prediction markets more transparent without claiming to eliminate every form of insider activity.

Built with: Next.js · Supabase · Capital One Nessie API · GoDaddy ANS · Polymarket API · WebCrypto


See it work (judge verification path)

Live site: https://anti-insiderz.vercel.app

  1. Log in as Dario (Anthropic staff) → try to buy an Anthropic market → BLOCKED, reason shown, receipt in the audit log.
  2. Buy the simulated 5-minute index as a clean account → "all six checks passed" → money visibly moves on Nessie.
  3. Profile page → live P/L ticking every 10s → Close position → wallet refunded, CLOSED entry appears.
  4. Log in as Timmy (age 5) → every market refuses him.
  5. Open /api/markets in a tab → live JSON, same numbers the UI shows.
Persona Affiliation Access score Can trade
Dario (trader4) anthropic-staff 67/100 6 of 9 — banned from the three Claude Opus release-date markets
Marcus (trader2) vt-athletics 78/100 7 of 9 — banned from both Hokies game markets
Eleanor (trader1) va-politician-household 78/100 7 of 9 — banned from the VA governor + congressional map markets
Timmy (trader3) — (age 5) 0/100 none — age gate bars every market

Nessie - runnable live for judges

We can simulate the whole money flow live in front of judges:

  • Attach a wallet. Each persona links a real Nessie sandbox account; the profile page shows its live balance.
  • Take money. A buy moves funds wallet -> pool and posts to the account ledger immediately.
  • Log everything. Every buy, refund, deposit and withdrawal lands as its own Nessie ledger entry with amount, description and timestamp - a judge can watch a new entry appear seconds after a demo trade.
  • Refund on exit. A signed close-out moves the payout pool -> wallet and posts a matching refund entry.
  • Tonight's example trades are already sitting on the pool account ledger ("NAI market pool") if a judge wants history, and the profile page reads the same ledger live.

ANS evidence

  • One registration.json per trader in agents/ — each shows the ans:// name, GoDaddy registry links (api.ote-godaddy.com/v1/agents/<uuid>), and ACME validation records.
  • lib/providers.ts → AnsHttpRegistry: live lookup per trade, requires lifecycle status ACTIVE, rejects expired registrations.

Built With

Share this project:

Updates

Submission history