Part B → main (re-route after stacked-base merge)#3
Merged
Conversation
The watcher fetched /api/markets?limit=500 (volume-ranked), so an alert armed from a market-detail page on a market outside the top 500 silently never fired while the button still showed Alerting. Now fetches exactly the armed markets via a new /api/markets?ids= branch (getMarketsByIds) -- any snapshot market is covered and the app-wide 60s top-500 refetch is gone. Also reconcile the persisted fired-set against removed alerts so it stays bounded and re-armed alerts can fire again. Findings H1, M3, L3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The per-IP limit keyed on the leftmost X-Forwarded-For entry, which is client-controlled and trivially spoofable to dodge the Etherscan-quota guard. Prefer x-real-ip (Vercel-set), fall back to the closest-trusted XFF hop. Also bound the hits map (prune expired windows + cap) so a churn of distinct IPs cannot grow it unbounded on a warm instance. Findings M2, L4. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
useLiveMidMap called setMids on every WS book/price-change message, forcing a full screener re-render + react-table re-sort per message; and never pruned mids for tokens that rotated out of the subscribed set (stale frozen values + unbounded Map growth). Stage mid changes and flush once per ~800ms (one re-render per burst; live cadence unchanged -- verified mids still tick in-browser), and prune on subscription change. Memoize PmBar, the live cell. Findings H2, M4, M5, partial H3. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy-this-fill and the title link pointed at /markets/[slug] for every followed-wallet trade, 404-ing whenever the wallet traded a non-crypto market absent from Auspex's snapshot, and the Copy button silently no-op'd. Resolve each trade's token via useMarketLookup: crypto markets keep the in-app link + Copy; everything else links out to Polymarket. Also let the row wrap on mobile so the title is not crushed. Findings M1, M10, L1, L15. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
next/font/google was disabled to avoid a build-time network fetch, so the ss01/cv11/tabular-nums type system silently fell back to system-ui in production. Adopt the geist package (local next/font assets, no build-time network) and wire GeistSans/GeistMono .variable onto <html>; globals.css already consumes --font-geist-sans/-mono. Verified rendering as GeistSans in-browser. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add /.well-known/security.txt (RFC 9116; security@auspex.to) and /llms.txt for AI discoverability. Bump --muted-2 #5d6478 -> #7a8195 so the 10px uppercase labels clear WCAG AA on the dark surfaces. From the mass-readiness sweep (Part B). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Curated starter views (Closing soon, Near trigger, Biggest movers, Deepest books, High clarity, Most traded) that compose the table's existing sorts + the Live toggle via URL state, lowering the screener's cold-start cost. From the competitive sweep (Part B). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a Compact toggle (lib/useDensity, localStorage) that tightens MarketTable row padding so users fit more rows per screen -- the dense-screener 'more rows' ask from the sweep. Desktop table for now; mobile cards unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rity) MIN/MAX inputs for 24h volume, order-book depth, distance-to-trigger, and clarity (RC) -- all fields already on TableRow, applied client-side in the existing filter memo. Active-count badge; integrates with Clear filters + Save view. Completes the screener power-features track (presets + density + filters). From the competitive sweep (Part B). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Upgrade the detail-page Rule card into a resolution-transparency block: rule summary + settles-by source + resolution deadline + the UMA optimistic-oracle mechanism and dispute-window framing, linking to Polymarket for live oracle status. Uses existing snapshot data only; surfaces the mechanism + lifecycle phase rather than a fabricated dispute status. Makes the Clarity (RC) score the antidote to Polymarket's top user complaint. From the competitive sweep (Part B). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…aution) Derive heuristic trader tags from the already-computed wallet P&L + recent trades (win rate, traded notional, profitability, activity, history length) and surface them as a 'Trader profile' chip row on the wallet page. Includes deliberate caution tags (New wallet, Underwater) so the read isn't one-sided -- the 'who's worth copying' signal layer over the existing scorecard tiles. Pure deriveTraderTags in walletPnl. Per-entry tags on the leaderboard would need a server-side stats endpoint (100 wallets x trades infeasible client-side) -- deferred. From the competitive sweep (Part B). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Show the per-share price ($0.72) next to the dominant implied % on the market-detail header (a YES share's price IS its probability). Non-traders read odds; traders see the executable price. Screener rows stay %-only by design (density). From the competitive sweep (Part B). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Top YES/NO holders by position size on market detail, each linking the wallet tracker (social proof + a path to follow big positions). New /api/holders route resolves the CTF conditionId from the slug via gamma-api (regex-extracted -- gamma returns occasionally-malformed JSON with raw control chars), then fetches Polymarket's holders feed; every holder validated (address + finite amount). No Python pipeline change needed. YES/NO labeled by clob-token match with array-order fallback (the response's per-group outcomeIndex is unreliable -- reads 0 for both outcomes). Verified end-to-end. Was deferred as data-blocked; unblocked here. From the competitive sweep (Part B). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…olume + edge) Fetch both Polymarket leaderboards (/profit + /volume) once and merge by wallet, so each card shows realized profit, volume traded, and return-on-volume efficiency, plus cheap tags (Whale / High edge / Grinder / In the red). Profit/Volume tabs now re-rank client-side (no refetch). Turns the single-metric list into a 'who's worth copying' surface without a per-wallet /trades fan-out -- win-rate per entry still needs a cached server precompute (deliberately not added). Verified in-browser: 50 cards, 14 with full overlap metrics, tags render, no console errors. From the competitive sweep (Part B). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a Most competitive Quick Screen that ranks markets by closeness to a 50/50 coin-flip. Implemented as an alternate sort in sortParam (shareable URL state): when active, Screener pre-sorts rows and hands the table an empty SortingState, which both the desktop react-table and mobile list preserve as-is; clicking any column header sets a real sort and exits competitive mode. Verified in-browser: top rows within 2% of 50/50, no errors. Closes the deferred competitive-sort item -- only the infra-gated win-rate precompute now remains. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Polymarket's leaderboard API has no win-rate (it needs each wallet's /trades), so a GitHub Actions job (every 6h) computes it for the ~86 top-profit+volume wallets via the canonical computeWalletPnl (imported from lib/walletPnl, not reimplemented -> no drift) and commits ui/public/leaderboard-stats.json. LeaderboardView fetches it best-effort and shows a gated Win metric + a Sharp tag. Win-rate is profit-rate on closed (sold) positions only -- held-to-resolution wins aren't counted, so it skews low; gated at >=10 closed + tooltipped so thin samples don't mislead. Script skips the write when stats are unchanged (no no-op deploys). Verified end-to-end: ran locally (86 wallets), file serves 200, 16 cards show win-rate, Sharp tag renders. Operator-approved infra addition (batched /trades fan-out, 6h cadence). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Routes the 11 Part B commits to
main. PR #2 merged into the fix branch (its stacked base) rather thanmainbecause PR #1 was merged without--delete-branch, so GitHub didn't auto-retarget. PR #1's fixes are already onmainby content, so this diffs to Part B only (verified: trust signals, screener power-features, resolution-transparency, Top Holders, leaderboard win-rate, etc.).Production build clean; PR #1 already live and smoke-tested.
🤖 Generated with Claude Code