Skip to content

anasdevv/market-screen

Repository files navigation

GOAL Markets

A live play-money market where every World Cup footballer is a tradeable stock in one globally-consistent market. Price moves from two forces: the crowd buying/selling along a bonding-curve AMM, and live match events (a goal spikes the player's "fundamental"). The hard guarantee — no double-spend, exactly-once settlement, and strong consistency through a goal-moment write spike — is the product.

Live: region A (us-east-1) https://goal-markets.vercel.app · region B (us-east-2) https://hkazvhm6ry.us-east-2.awsapprunner.com

Architecture

Client → Vercel Edge → Vercel Functions (API)
                          ├─ DynamoDB        rate-limit counters (fail-open)
                          ├─ Aurora DSQL     STAGE 1: reserve (per-user tx)         ┐ active-active
                          └─ SQS FIFO ──────→ Lambda settler ── STAGE 2: settle ────┘ multi-region
                             (group=player_id)  (per-player writer, us-east-1)         (us-east-1 + us-east-2,
EventBridge → Ops Lambda  → DSQL (windowed leaderboard rollup + reconcile)              witness us-west-2)
EventBridge → Feed Lambda → football-data.org top-scorers → goal events → SQS FIFO
OTel (@vercel/otel + settler) → AWS X-Ray (traceparent rides the SQS message)
  • Aurora DSQL — strongly consistent, serverless, active-active multi-region. The ACID core (balance, settlement, holdings). OCC: clashing writers to a row abort at COMMIT (retry). Money is numeric, PKs are UUIDv7 (no sequences/FK/triggers).
  • SQS FIFO + Lambda settlerMessageGroupId = player_id makes the platform the lock: one in-flight message per player → one writer of the hot player_state row → 0 OCC conflicts under the goal-moment stampede. Idempotent via UNIQUE(fills.order_id).
  • Two-stage settlement — intake reserves on the user's own rows (no double-spend) and enqueues; the settler replays the bonding curve and writes the authoritative state. Append-only orders/fills → no write contention on the spike.
  • Reads are served from a cached current_price / leaderboard rollup (~1s stale, poll-friendly).
  • Multi-region — both regional endpoints are one strongly-consistent logical DB; region A is on Vercel, region B is the same app on AWS App Runner; the settler stays single-region so single-writer-per-player is global.
  • Live goal feed — a goal-feed Lambda (EventBridge, 1/min) polls football-data.org's free top-scorers endpoint and diffs each player's cumulative goal count; a rise means he scored, so it enqueues a goal event to that player's SQS group. It also mirrors in-play matches into a live_matches read model for the UI ticker.
  • Keyless — no long-lived AWS keys at runtime: Vercel assumes an IAM role via OIDC federation, App Runner uses an instance role, the Lambdas use execution roles, and DSQL authenticates with short-lived scoped IAM tokens (the runtime app role holds DML only).

Full design write-up, with diagrams: WRITEUP.md.

Develop

pnpm install
cp .env.local.example .env.local   # set DSQL_HOST etc. (see below); AWS creds via `aws login`
pnpm dev                            # http://localhost:3000
pnpm dev:otel                       # dev server with OpenTelemetry → X-Ray

Env (local uses your aws login creds; prod is keyless — Vercel assumes a role via AWS_ROLE_ARN/OIDC, App Runner uses its instance role): DSQL_HOST, AWS_REGION, SQS_QUEUE_URL, RATELIMIT_TABLE, DSQL_USER (app runtime / admin migrations), FOOTBALL_DATA_API_KEY (live goal feed).

Ops scripts: pnpm db:migrate (Umzug), pnpm db:seed, pnpm build:lambda, pnpm smoke, pnpm loadtest.

Deploy (CI/CD)

Push to main → everything ships, only what changed:

  • Region A — Vercel auto-deploys via its GitHub integration.
  • AWS.github/workflows/deploy.yml (GitHub OIDC → goal-ci role, no stored keys):
    • infra/migrations/** → apply DSQL migrations
    • lambda/** or lib/** → rebuild + redeploy the settler/ops Lambdas
    • app code → build + push the region-B container to ECR → App Runner auto-deploys

So a schema or API change is just a commit — no manual deploys.

About

A live play-money market where every World Cup footballer is a tradeable stock — one globally-consistent market on Aurora DSQL, settled exactly-once through the goal-moment write spike. AWS × Vercel H0.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors