hackquest logo

LineLock — lock the line, prove the pick

Tipster records are screenshots. LineLock sells World Cup picks for 0.05 USDC via Injective x402 — the receipt IS the pre-kickoff proof; a free public ledger CLV-scores every pick, losses included.

Videos

Project image 1
Project image 2
Project image 3
Project image 4

Tech Stack

Node
Next
Solidity
Web3
TypeCheck
x402
Injective EVM
Express

Description

LineLock — lock the line, prove the pick

A pay-per-pick World Cup edge API on Injective EVM where the x402 USDC receipt IS the pre-kickoff timestamp, plus a free public ledger that CLV-scores every settled pick — losses included. Buy the next pick for 5 cents. Audit every past pick for free.

Live: https://linelock.edycu.dev/ · API: https://api.linelock.edycu.dev · Pitch deck: https://linelock.edycu.dev/pitch/ · Demo: https://youtu.be/MHHYIJkLRbo

INSPIRATION

Every World Cup tipster shows you screenshots — and screenshots are unfalsifiable. Was the pick posted before kickoff? Were the losses deleted? Nobody can prove it either way, so the entire tipping market runs on trust and survivorship bias. Meanwhile, pro syndicates don't judge themselves on win/loss at all — they track CLV (Closing Line Value): did you beat the closing price? Positive CLV over a sample is real edge, independent of variance. LineLock's bet: an x402 payment receipt on Injective is a better notary than any screenshot. The payment's block time is, by construction, an immutable pre-kickoff timestamp — so the act of selling the pick is also the act of proving when it existed.

WHAT IT DOES

One flow, made undeniable: pay x402 → edge + conviction ladder returned → receipt = pre-kickoff proof → match settles → CLV scored → public ledger row.

1. Paid edge endpoint — POST /api/edge is gated by the real @injectivelabs/x402 middleware at 0.05 USDC (50000 units) on Injective EVM mainnet (network eip155:1776, USDC 0xa00C59fF5a080D2b954d0c75e46E22a0c371235a). An unpaid call returns a live HTTP 402 with a PAYMENT-REQUIRED quote — try it right now: curl -i -X POST https://api.linelock.edycu.dev/api/edge

2. The receipt is the notary — invariant I1: a ledger row is valid only if receipt_block_time < kickoff_utc. The USDC payment tx doubles as the tamper-proof pre-kickoff timestamp, bound to the pick via pick_hash = sha256(canonical pick JSON) (invariant I2).

3. Free CLV-scored public ledger — every paid pick lands on the ledger, losses included (invariant I3): 24 settled seed rows, record 15-9, ROI +24.2%, avg CLV +2.9%, 67% beat-close. The ledger deliberately keeps wins with negative CLV and losses with positive CLV — that divergence is the whole point. Seed rows are labeled is_placeholder: true everywhere; nothing is passed off as a real receipt.

4. One-command independent audit — npm run audit -- --all re-hashes every pick, re-checks invariants I1/I2/I3/I5 and recomputes every daily Merkle root → "LEDGER PASSES". Anyone can re-verify the track record without trusting us.

5. Agents are the customers — the shipped worldcup-linelock Agent Skill teaches any AI harness the full buyer loop (MCP account_balances → pay the 402 → validate the hash → audit the ledger). Install: npx skills add https://github.com/edycutjong/linelock --skill worldcup-linelock. No API key, no signup — the 402 is the API key.

6. On-chain checkpoint contract — LedgerAnchor.sol, a ~40-line write-once daily Merkle root anchor (invariant I5): receipts prove when each pick existed; the anchor proves the ledger DB was never rewritten. (Written and tested; mainnet deployment is funding-gated and honestly labeled as such.)

HOW WE BUILT IT

- Payments — @injectivelabs/x402: injectivePaymentMiddleware(routes, options) server-side; createInjectiveClient().fetch() + parsePaymentRequired client-side (EIP-3009 USDC authorization). The 402 handshake is covered by tests using the SDK's own parser.

- API — Express + TypeScript (strict): the gated /api/edge plus free CORS-open ledger/receipt/anchor/verify routes, rate-limited (600 req/min).

- Engine — pure TypeScript modules for edge, conviction ladder, CLV math, canonical pick hashing, and Merkle trees — ~98% test coverage.

- Datafootball-data.org + the-odds-api clients with cached responses committed to the repo, so judges can run everything with an empty .env.local; closing line = last odds snapshot ≤ kickoff (invariant I4).

- Storage — SQLite (better-sqlite3) ledger repository.

- Web — Next.js 14 ledger site, 5 screens: ledger · pay/reveal · audit · agent · verify (with in-browser pick re-hashing).

- Contract — Solidity LedgerAnchor.sol, built via the official injective-evm-developer Agent Skill.

- Buyer-side Injective surfaces — MCP server tools (account_balances, usdc_native_info, address_normalize, cctp_*) driven by the shipped Agent Skill; USDC CCTP V2 wiring for Base → Injective buyer funding.

Quality and security engineering:

- Unit tests — 70 vitest tests: CLV · edge · ladder · hashing · similar-pick lookup · settle idempotency · invariants I1–I5 · the live 402 handshake; engine coverage ~98% with a coverage gate.

- E2E — 3 Playwright specs (demo-mode · ledger-flow · responsive) that run keyless in CI.

- Static quality — TypeScript strict (tsc --noEmit) + ESLint, zero warnings.

- Security — CodeQL (SAST) + Dependabot (npm root, web, actions) + TruffleHog secret scanning + npm audit.

- CI/CD — 6-stage GitHub Actions pipeline (Quality → Security → Build → E2E → Performance → Deploy), Node 20/22/24 matrix on main, concurrency-guarded, semantic-release (currently v1.1.0).

- Performance — Lighthouse CI on the built site; latency bench: 402-quote p50 ~0.5 ms, p95 ~2.6 ms.

CHALLENGES WE RAN INTO

1. The shipped x402 package differs from its docs. Public sketches show a flat injectivePaymentMiddleware({endpoint, network, asset, amount}); the shipped dist/*.d.ts actually takes a routes map + an options object, with v2 headers (PAYMENT-REQUIRED / PAYMENT-SIGNATURE / PAYMENT-RESPONSE). We pinned the build to the shipped types, verified the handshake with the SDK's own parsePaymentRequired, and documented the deviation instead of hiding it.

2. Proving a paywall without money. The ops wallet isn't funded, and we refused to fake receipts. Solution: three honest layers — the real middleware serves a live mainnet 402 quote with zero funds; a --demo flag returns the actual paid payload self-labeled receipt: null; and scripts/paid-call-smoke.ts does a balance preflight and exits rather than fabricate a tx. Every seed row is is_placeholder: true.

3. A deploy stage that can't lie either. The CI deploy job broke because GitHub's secrets context is invalid in a job-level if. Fixed by green-skipping Railway deploys when RAILWAY_TOKEN is absent — the pipeline stays green for forks and honest about what actually deployed.

WHAT WE LEARNED

A receipt is a better résumé than a screenshot. Once the payment rail itself is the notary (block time < kickoff), the honest version of the product is also the most convincing one — publishing losses, labeling placeholders, and shipping an audit command that would expose us if we cheated turned "trust me" into "verify me". And on the engineering side: always build against the shipped .d.ts, never the docs sketch.

WHAT'S NEXT

- Fund the ops wallet and land the first real paid receipt — CCTP-mint USDC to Injective, gas the facilitator, run paid-call-smoke, and flip the first ledger rows to is_placeholder: false with true Blockscout tx hashes.

- Deploy LedgerAnchor.sol to Injective EVM mainnet and start posting the daily Merkle root on-chain (the anchor script and DEPLOY.md are ready).

- Beyond the World Cup — the receipt-as-notary + CLV-ledger pattern generalizes to any timestamped prediction market: e-sports, elections, macro calls — every new sport is just a new fixtures feed.

Progress During Hackathon

Everything was built during the hackathon window — there is no pre-existing codebase.

- Jul 10–12 — core build: pinned the real @injectivelabs/x402 surface from its shipped dist/*.d.ts (verified 2026-07-12), then built the edge/CLV/ladder/hash/Merkle engine, the x402-gated Express API, the SQLite ledger, the 24-row seed settle pipeline, the audit CLI, the Next.js 14 five-screen site, the worldcup-linelock Agent Skill, and LedgerAnchor.sol — 70 vitest tests green, live local 402 handshake parsed by the SDK's own parser.

- Jul 17 — public push as github.com/edycutjong/linelock (v1.0.0): 6-stage CI green (Quality → Security → Build → E2E → Performance → Deploy, Node 20/22/24 matrix), CodeQL + Dependabot + TruffleHog, semantic-release wired.

- Jul 17 — live deploys: API on Railway at api.linelock.edycu.dev (real HTTP 402 mainnet quote on the public internet), GitHub Pages landing at linelock.edycu.dev + interactive printable pitch deck at /pitch/, wow-factor landing redesign (v1.1.0).

- Jul 17 — demo video recorded and published: https://youtu.be/MHHYIJkLRbo (2:35, the honest zero-funds cut).

Honest status: the live API serves real mainnet-targeting x402 quotes; the single thing still gated on wallet funding is a real settled paid receipt (and the on-chain anchor deploy) — the code does a balance preflight and refuses to fabricate either.

Fundraising Status

Bootstrapped, solo hackathon build. No external funding, no revenue, not currently raising. Built and deployed for the Injective Global Cup Hackathon; next milestone is product proof (first real paid x402 receipt on Injective mainnet), not a raise.

Team Leader
EEdy Cu
Project Link
Deploy Ecosystem
InjectiveInjective
Sector
AIDeFiInfra