Skip to content

M2 P0 integration: My Radar (/app), watchlist API adapter, front cleanup - #25

Merged
solsentry merged 16 commits into
mainfrom
feat/m2-p0-integration
Sep 8, 2026
Merged

solsentry merged 16 commits into
mainfrom
feat/m2-p0-integration

Conversation

@solsentry

Copy link
Copy Markdown
Owner

Integrates the M2 P0 work (site reform, session of 2026-09-08):

  • F1a: contract-shaped watchlist adapter (src/lib/watchlist.ts), honest WatchlistPanel, TrackButton on operator/token, /app My Radar route (gated by NEXT_PUBLIC_M2_APP_OPEN=1), post-login lands there.
  • F1b: API backend for the watchlist behind NEXT_PUBLIC_WATCHLIST_API=on (credentialed fetch straight to api.solsentry.app; CORS with credentials already deployed server-side), local→API migration, watched-items events feed on /app.
  • F2: front cleanup — mock feeds/routes removed (/screen, /birdeye-radar), dead nav links dropped, NL search disabled with hint, compare/wallets delisted + noindex, "real-time" copy → "low-latency".
  • Earlier WIP: holders/pricing/Sena wiring, OperatorGraph, scan consolidation, /auth/verify allowlisted in middleware.

Prod stays locked: /app and /login are only reachable with NEXT_PUBLIC_M2_APP_OPEN=1 in the Workers build (not set). Build 43/43, lint 0 errors.

https://claude.ai/code/session_01YKY8SsyaKD5pUFj6vHPZPq

… OperatorGraph, scan consolidation

- restore default-deny middleware allowlist (was bypassed for local testing;
  merge would have published internal routes — deploy is automatic on main)
- remove fabricated 38.4%/12.1% cluster supply figures from token page
  (no such field in cluster_evidence; 19_ANTI §2 landmine)
- retire /scan surface fully: allowlist, sitemap, Footer link, AddrLink and
  AISearchBar routing (symbol search disabled), AISuggestionsCard -> /lookup
- fix debug hub page (escaped backticks never compiled)
- next build green
- Delete src/app/api/sena/chat/route.ts — SenaDrawer already calls the
  live /v1/sena/chat backend endpoint (SenaDrawer.tsx:156); no callers
  referenced the internal stub route.
- OperatorGraph node click already copied the wallet address; add a
  transient "Copied ✓" hover-tooltip state so the action has visible
  feedback, matching the CopyShareLink pattern.

Pricing page (src/app/pricing/page.tsx) audited — all figures already
sourced live from /v1/pricing via fetchPricing(); no hardcoded metrics
found, no changes needed.
Magic-link emails land on /auth/verify — without this entry the 307
redirect to / strips the token and kills sign-in. Note: web verify still
blocked by credentials:'include' vs ACAO:* CORS on the API side; beta
onboarding does not depend on this flow.
…kButton on operator/token

- src/lib/watchlist.ts: single adapter mirroring the live /v1/watchlist
  contract (id/addr/kind/label/tags/notes/alerts/created_at, count/limit,
  field caps, slot_limit error). localStorage backend under
  solsentry:watchlist with in-place migration of the legacy string[] format;
  NEXT_PUBLIC_WATCHLIST_API=on is a warned stub until F1b.
- WatchlistPanel: mock data and mock-only fields (risk sparkline, pnl,
  rug counts, avatar) removed; renders only contract fields; alias/tags/
  notes/alerts/remove wired to the adapter.
- TrackButton takes {addr, kind}, mounted on /operator/[wallet] and
  /token/[mint]; surfaces slot_limit with a link to /app.
- live-feed: hide mock-only chrome (events/min, pause, 'connect Pro') when
  fed real events — the fixed 12 events/min was an invented number.

Claude-Session: https://claude.ai/code/session_01YKY8SsyaKD5pUFj6vHPZPq
…ogin lands there

- /app: server component, redirects to /login?callback=/app when the
  solsentry_session cookie is absent; ProShell + WatchlistPanel +
  LiveFeedLive; noindex.
- middleware: /app and /login join the allowlist ONLY when
  NEXT_PUBLIC_M2_APP_OPEN=1 (owner's per-phase gate); default unchanged.
- magic-link verify honours ?callback (same-origin only), default /app.

Claude-Session: https://claude.ai/code/session_01YKY8SsyaKD5pUFj6vHPZPq
… useWatchlist hook, local→API migration on flip

- NEXT_PUBLIC_WATCHLIST_API=on calls /v1/watchlist* directly with
  credentials:"include" (the session cookie is host-only on the API host,
  so a Next proxy could never forward it; the API now grants credentialed
  CORS to the app origin). off keeps the localStorage backend.
- Adapter is async (Promise results); React consumers use useWatchlist()
  over an in-memory snapshot. Errors map to unauthenticated / slot_limit /
  api_error without throwing into the UI.
- First authenticated load with the flag on imports local items one by one
  (duplicates come back created:false; a 402 stops and keeps the rest local
  with a visible notice); the local copy is trimmed after every success so
  a retry never duplicates.
- comparison-matrix: last unqualified 'real-time' reworded.

Claude-Session: https://claude.ai/code/session_01YKY8SsyaKD5pUFj6vHPZPq
- WatchlistEventsFeed polls /v1/watchlist/events every 15s (since = last
  server_time), shows the matched watch item and links to its page; 401 →
  /login?callback=/app. Honest empty state, no sample rows.
- /app no longer checks the cookie server-side: the cookie lives on the API
  host, so the Next server would always redirect in prod. The client's 401
  handling is the gate.

Claude-Session: https://claude.ai/code/session_01YKY8SsyaKD5pUFj6vHPZPq
@solsentry
solsentry merged commit 3bc36a6 into main Sep 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant