From 3302a78536865c0ef0c2467ba2c8fd42ef70eb2a Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 7 Sep 2026 09:11:53 +0200 Subject: [PATCH] Update CLAUDE.md: real backend connection replaces the mock lock toggle Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01YXiHuScXrjxBh7yFGAPq3B --- CLAUDE.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 92e92b9..20274e7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -79,9 +79,17 @@ A site adapter's contract: `matches` (URL pattern), `findBuyElements()`, `getCon ## Lock state contract -The lock/unlock state is a simple typed interface: `{ locked: boolean, reason?: string, scope: 'buy-only' | 'full-block' }`. For v1 (no real backend yet), this is driven by a mock/dev toggle (e.g. via popup or `browser.storage`). The background script must expose a single isolated seam (`getLockState()` / `setLockState()`) where the real WebSocket client will later plug in — do not scatter lock-state reads/writes across modules. +The lock/unlock state is a simple typed interface: `{ locked: boolean, reason?: string, scope: 'buy-only' | 'full-block' }`. **Implemented**: the background script (`src/background/lock-state.ts`) exposes the single isolated seam (`getLockState()` / `applyLockState()`) — nothing else reads or writes lock state directly. `applyLockState()` is called exclusively by the real WS client (`src/background/ws-client.ts`) on an incoming `lock_state` message; there is no mock/dev toggle anymore since a real backend exists (the popup used to have one — removed once the backend connection landed). -Note the naming mismatch with the wire protocol below: the frontend's internal `LockScope` uses kebab-case (`'buy-only' | 'full-block'`), while the wire protocol (§ "WebSocket protocol") uses snake_case (`"buy_only" | "full_block"`). The future WebSocket client is exactly where that translation belongs — inside the `getLockState()`/`setLockState()` seam, not leaked into content scripts or the popup. +Note the naming mismatch with the wire protocol below: the frontend's internal `LockScope` uses kebab-case (`'buy-only' | 'full-block'`), while the wire protocol (§ "WebSocket protocol") uses snake_case (`"buy_only" | "full_block"`). `ws-client.ts` is exactly where that translation happens — not leaked into content scripts or the popup. + +## Backend connection (implemented) + +- `src/shared/config.ts` — `BACKEND_HTTP_URL`/`BACKEND_WS_URL`, currently hardcoded to `localhost:3000` (dev only; `host_permissions` in `wxt.config.ts` must stay in sync with whatever host is configured here). +- `src/background/identity.ts` — **stub wallet**: a locally-generated ed25519 keypair (via `tweetnacl`), persisted in `browser.storage.local`, used as a stand-in for a real Solana wallet signature. This is deliberately temporary — real wallet integration means bridging into the page's injected `window.solana` provider on axiom.trade (content script + page-context script), which hasn't been built yet. `getIdentity()`/`sign()` is the seam that swap plugs into. +- `src/background/backend-client.ts` — the REST auth flow (`POST /auth/nonce` → sign → `POST /auth/verify` → session token), persisted via `getSessionToken()`. +- `src/background/ws-client.ts` — the WS client described above: connects to `/ws?token=...`, reconnects with the protocol's suggested backoff, force-refreshes the session token on `4001`/`auth_expired` before retrying. +- `src/background/connection-status.ts` — separate from lock state; the popup surfaces this (connecting/connected/disconnected/auth-error) alongside the lock state so a broken connection isn't silently indistinguishable from "unlocked". ## WebSocket protocol (backend wire contract) @@ -153,7 +161,7 @@ Single source of truth for the wire protocol between the Nexa backend (Rust/Axum ## Non-goals for this milestone -- No real backend/WebSocket connection (mock state only) — see "WebSocket protocol" above for the wire contract to implement against when this milestone is picked up. +- Real wallet signing (Phantom et al. via axiom.trade's injected `window.solana`) — auth currently uses a stub local keypair, see "Backend connection" above. - No cost-basis tracking logic (backend concern). - No full-site-block implementation beyond a stub module. - No threshold-setting UI (placeholder link only).