feat: add client id parameter into bw query#7823
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughAdds a persisted balances-watcher client ID with TTL and in-memory fallback, sends it in session and SSE requests, adds coverage for the behavior, and updates related translation entries. ChangesBalances Watcher Client ID
Translation entries
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant App
participant getBalancesWatcherClientId
participant localStorage
participant Server
App->>getBalancesWatcherClientId: request client id
getBalancesWatcherClientId->>localStorage: read or persist client id
getBalancesWatcherClientId-->>App: return client id
App->>Server: POST session with X-Client-Id
App->>Server: open SSE stream with client_id
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying explorer-dev with
|
| Latest commit: |
0f7b696
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://c3783044.explorer-dev-dxz.pages.dev |
| Branch Preview URL: | https://feat-add-client-id-for-bw.explorer-dev-dxz.pages.dev |
Deploying swap-dev with
|
| Latest commit: |
0f7b696
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://9ff318da.swap-dev-5u6.pages.dev |
| Branch Preview URL: | https://feat-add-client-id-for-bw.swap-dev-5u6.pages.dev |
fairlighteth
left a comment
There was a problem hiding this comment.
⚠️ AI Review (Codex GPT-5, worked 4m): client_id can rotate between POST and SSE
Finding: [BLOCKING] Pin the balances-watcher client_id across the POST → SSE handshake
- Location:
libs/balances-and-allowances/src/hooks/balancesWatcherSessionController.ts:128 - This one is important: the PR says the backend indexes sessions by
(chainId, owner, clientId), and the checklist requires the POSTX-Client-Idand SSEclient_idto be the same UUID. - Current code calls
getBalancesWatcherClientId()independently increateBalancesWatcherSessionandsubscribeToBalancesEvents. If the stored ID is still fresh when the POST starts but crosses the 24h TTL before the POST resolves andopenStream()runs, the POST registers the old ID while the SSE URL rotates to a new ID. - Result: the SSE stream can look up a different backend session than the one just created.
Suggested fix
- Generate/read the client ID once per session attempt and pass that same value into both helpers, or make
getBalancesWatcherClientId()cache the active tab ID so TTL is only re-evaluated on a new page load. - Add a regression test where the stored ID expires between
createBalancesWatcherSessionandsubscribeToBalancesEvents, and assert both requests still use the same ID.
Review scope and related context
- Existing review context did not cover this: CodeRabbit reported no actionable comments, and there are no review threads.
- The existing tests cover fresh storage, expired storage, POST header, and SSE query parameter separately, but not the controller boundary where the same session attempt must keep one ID across both requests.
🤖 Prompt for AI agents
Verify this finding against current code. Fix only if still valid, keep the change minimal, and validate with targeted tests.
Context:
- createSessionController calls createBalancesWatcherSession(), waits for it to resolve, then opens subscribeToBalancesEvents().
- createBalancesWatcherSession and subscribeToBalancesEvents each call getBalancesWatcherClientId() separately.
- If the 24h TTL boundary is crossed between those calls, POST and SSE can use different client IDs.
- Expected fix: pin one client ID per session attempt or cache the active tab ID until reload, then add a regression test for the TTL-boundary handshake.
Generated using the pr-review skill from the CoW Protocol skills repo.
…wswap into feat/add-client-id-for-bw
done |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
libs/balances-and-allowances/src/balancesWatcher/clientId.test.ts (1)
10-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider avoiding the non-null assertion in
loadModule.Line 14 uses
mod!to satisfy TypeScript. While this is test code (not production), the coding guidelines discourage non-null assertions in.tsfiles. Sincejest.isolateModulesruns its callback synchronously, the assignment is guaranteed, but a default initialization avoids the assertion entirely.♻️ Optional refactor to avoid non-null assertion
- let mod!: typeof import('./clientId') + let mod: typeof import('./clientId') | undefined jest.isolateModules(() => { mod = require('./clientId') }) - return mod + return mod!Alternatively, restructure to return from inside the callback via a wrapper:
function loadModule(): typeof import('./clientId') { - let mod!: typeof import('./clientId') - jest.isolateModules(() => { - mod = require('./clientId') - }) - return mod + // jest.isolateModules runs synchronously, so this is safe + const scope: { mod?: typeof import('./clientId') } = {} + jest.isolateModules(() => { + scope.mod = require('./clientId') + }) + return scope.mod! }Note: fully eliminating
!here is awkward becausejest.isolateModulesdoesn't return a value. If the team considers test files exempt from the guideline, this can be skipped.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@libs/balances-and-allowances/src/balancesWatcher/clientId.test.ts` around lines 10 - 19, Replace the non-null assertion initialization in loadModule with a safe default initialization or equivalent wrapper that avoids !, while preserving the synchronous jest.isolateModules behavior and returning the loaded clientId module.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@libs/balances-and-allowances/src/balancesWatcher/clientId.test.ts`:
- Around line 10-19: Replace the non-null assertion initialization in loadModule
with a safe default initialization or equivalent wrapper that avoids !, while
preserving the synchronous jest.isolateModules behavior and returning the loaded
clientId module.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 594f12a1-2b7d-4c62-9517-8e37199a7ee2
📒 Files selected for processing (2)
libs/balances-and-allowances/src/balancesWatcher/clientId.test.tslibs/balances-and-allowances/src/balancesWatcher/clientId.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- libs/balances-and-allowances/src/balancesWatcher/clientId.ts
✅ AI Review (Codex GPT-5, worked 4m): follow-up addressedRechecked
Result: Fixed. The first call now caches the selected ID for the tab lifetime, so the later SSE call cannot rotate away from the ID used by the POST. Rotation occurs only after a page/module reload, matching the updated PR contract. No new non-duplicate findings surfaced. 🤖 Verification notes for AI agentsGenerated using the |
Summary
Attach a browser-scoped client_id to every balances-watcher request. Backend indexes sessions by
(chainId, owner, clientId). Backend doesn't support session-id yet, the frontend pr should be merged first otherwise it breaks the session.To Test
POST /sessions/*request in DevTools Network tab has anX-Client-Idheader/sse/*/balances/*request URL includes?client_id=<uuid>query parameterclient_idvalue is used (persisted)balances-watcher-client-idexists{"id": "<uuid>", "createdAt": <timestamp>}createdAtin localStorage to a value older than 24h, refresh pageclient_id; localStorage entry is replaced with a freshcreatedAtX-Client-Id/?client_id=valueBackground
Native
EventSourcedoes not support custom request headers per the WHATWG spec. Adding a polyfill (event-source-polyfilletc.) would let us mirror the POST header on SSE but adds a runtime dependency and a known set of reconnect/readyState bugs that we do not want to trade for pure cosmetic consistency. Query string is equally opaque and equally protected by TLS; the backend already accepts both.The 1-day TTL bounds the long-term correlation window of a browser to a stable session key and gives orphan sessions on the backend an upper lifetime. Rotation happens only on the next call after a new tab opens or an existing one is refreshed, so a long-running tab keeps the same
client_idfor the whole session.Summary by CodeRabbit
X-Client-Idheader, and the balances SSE stream now includes aclient_idquery parameter.