Uh oh!
There was an error while loading. Please reload this page.
perf(perps): add coherent bootstrap snapshots - #9815
Conversation
4355de0 to
a73cce2CompareUh oh!
There was an error while loading. Please reload this page.
3378749 to
9a75d43Compare
geositta
left a comment
There was a problem hiding this comment.
Requesting changes. The identity, freshness, completeness, and lifecycle guards are implemented and tested, but requesting that the snapshot path remain time bounded through body consumption.
Uh oh!
There was an error while loading. Please reload this page.
d17d1c7 to
c060160CompareUh oh!
There was an error while loading. Please reload this page.
c060160 to
86aa8c4CompareUh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c6c4aa8. Configure here.
Uh oh!
There was an error while loading. Please reload this page.
abretonc7s
commented
Aug 12, 2026
Final review-ready SHA: |
Uh oh!
There was an error while loading. Please reload this page.
## Description Targets Perps preload measurements to their named trace IDs, exposes a post-hydration controller construction timestamp to clients, and removes the wallet address from user-preload trace data. This is the minimal Core contract required by the Perps loading dashboard; market and account bootstrap behavior is unchanged. ## Changelog - Added optional Perps performance hooks for controller construction and explicit trace-targeted measurements. - Removed wallet addresses from Perps user-preload traces. ## Validation - Focused PerpsController Jest: 3 passed - Targeted ESLint: passed - Prettier and git diff checks: passed - Repository pre-push lint is locally blocked by unrelated untracked harness overlays and tsc cache files; GitHub CI is the clean full-repository gate. ## Related Follow-up to MetaMask#9815. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Telemetry and optional DI hooks only; preload and trading paths are unchanged aside from trace targeting and PII removal from traces. > > **Overview** > Extends the Perps observability contract for the loading dashboard without changing market or account bootstrap behavior. > > **`PerpsPerformance`** gains an optional **`onControllerConstructed`** callback, invoked once after synchronous disk hydration in the constructor with `performance.now()` (no Sentry write at construct time). > > **`PerpsTracer.setMeasurement`** is typed as an overload that accepts an optional fourth **`id`** argument; market and user preload paths now pass the same **`traceId`** used when opening those named traces so durations attach to the correct span. > > **User data preload** no longer puts **`userAddress`** on the `Perps User Data Preload` trace `data` or in debug logs tied to that flow, reducing PII in telemetry while fetch behavior is unchanged. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 308f4c8. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->

Explanation
Perps cold start currently assembles market and account data through independent provider requests. This makes first content sensitive to request ordering, cache identity, and WebSocket readiness.
This PR adds two opt-in bootstrap paths:
/v2/perpetualsmarket snapshot consumer configured throughterminalApi.globalSnapshotUrl. It validates schema, provider/network/DEX identity, freshness, completeness, units, trends, and payload size, then falls back exactly once to HyperLiquid.PerpsController.getUserDataSnapshot(), which returns positions, open orders, and account state as one address/network/HIP-3/DEX-scoped result while reusing each DEX clearinghouse response.Market and account preloading now run independently. Cache writes are discarded if account, provider, network, HIP-3 configuration, or DEX identity changes during the request. Existing live-price WebSocket subscriptions remain authoritative after bootstrap.
Configuration remains optional. Without
terminalApi.globalSnapshotUrl, or when/v2/perpetualsis unavailable or invalid, existing provider behavior continues through the guarded fallback. The deprecated flatterminalApiUrlis retained for compatibility.Validation
git diff --check: passed.PerpsController.getMarketDataWithPrices()andPerpsController.getUserDataSnapshot()./v2/perpetualsroute: passed; 177 mainnet markets were accepted asterminal-global-snapshot-mark, with trends present. The same backend run returned HTTP 200 for unchanged/v1/perpetualsand complete v2mainandmain,xyzsnapshots.References
Checklist
Note
Medium Risk
Touches trading UI bootstrap, cache identity, and account-scoped data with many race guards; misconfiguration or validation bugs could cause stale or empty first paint, but behavior falls back to existing provider paths when snapshots are off or rejected.
Overview
Perps cold start now has two opt-in bootstrap paths so first paint is less sensitive to request ordering and partial caches.
When
terminalApi.globalSnapshotUrlis set,getMarketDataWithPricestries a schema-v2 Terminal global snapshot first: strict validation (identity, fingerprint, freshness, completeness, payload size, per-market fields/trends), then a single fallback to HyperLiquid. Accepted snapshot rows are taggedterminal-global-snapshot-markwithsourceExpiresAt; market cache reads honor that expiry plus HIP-3/DEX identity, not only wall-clock TTL.getUserDataSnapshot()fetches positions, open orders, and account state in one Hyperliquid bundle (multi-DEX clearinghouse reuse), validates the captured address/network/HIP-3/DEX identity, coalesces in-flight requests, and atomically updates memory + serialized disk cache. Cached user/market data fail closed without a selected EVM address or on address/DEX/hip3ConfigVersionmismatch; account switches invalidate via address guards instead of wiping the whole cache.Preload runs market and user refresh in parallel (no longer user-after-market), queues trailing runs, and drops writes when context races. Standalone Hyperliquid provider ops are tracked so disconnect waits for in-flight work; subscriptions can discover enabled DEXes from the provider. Legacy
terminalApiUrl/ metadata enrichment still work when the global snapshot path is not configured.Reviewed by Cursor Bugbot for commit f66b4a9. Bugbot is set up for automated code reviews on this repo. Configure here.