Skip to content

perf(perps): add coherent bootstrap snapshots - #9815

Merged
abretonc7s merged 11 commits into
mainfrom
perf/3662-perps-bootstrap-snapshots
Aug 12, 2026
Merged

perf(perps): add coherent bootstrap snapshots#9815
abretonc7s merged 11 commits into
mainfrom
perf/3662-perps-bootstrap-snapshots

Conversation

@abretonc7s

@abretonc7s abretonc7s commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

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:

  • A strict Terminal /v2/perpetuals market snapshot consumer configured through terminalApi.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/perpetuals is unavailable or invalid, existing provider behavior continues through the guarded fallback. The deprecated flat terminalApiUrl is retained for compatibility.

Validation

  • Focused Perps Jest: initial 7-suite/325-test gate passed; review corrections additionally passed the complete controller suite (110/110), standalone provider suite (33/33), and combined contract/race gate (206/206).
  • Targeted ESLint: passed on all 19 changed source/test files.
  • Prettier check and git diff --check: passed.
  • Full monorepo build and package-level Perps ESLint: passed.
  • Public Core recipe, provider fallback: passed through PerpsController.getMarketDataWithPrices() and PerpsController.getUserDataSnapshot().
  • Public Core recipe against the real local Terminal Nest/Redis /v2/perpetuals route: passed; 177 mainnet markets were accepted as terminal-global-snapshot-mark, with trends present. The same backend run returned HTTP 200 for unchanged /v1/perpetuals and complete v2 main and main,xyz snapshots.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR

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.globalSnapshotUrl is set, getMarketDataWithPrices tries 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 tagged terminal-global-snapshot-mark with sourceExpiresAt; 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/hip3ConfigVersion mismatch; 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.

@abretonc7s abretonc7s self-assigned this Aug 11, 2026
@abretonc7s
abretonc7s force-pushed the perf/3662-perps-bootstrap-snapshots branch from 4355de0 to a73cce2 Compare August 11, 2026 03:37
@abretonc7s
abretonc7s marked this pull request as ready for review August 11, 2026 07:58
@abretonc7s
abretonc7s requested review from a team as code owners August 11, 2026 07:58
@abretonc7s
abretonc7s deployed to default-branch August 11, 2026 07:58 — with GitHub Actions Active
Comment thread packages/perps-controller/src/services/TerminalMarketService.ts Outdated
@abretonc7s
abretonc7s force-pushed the perf/3662-perps-bootstrap-snapshots branch from 3378749 to 9a75d43 Compare August 11, 2026 08:33
@abretonc7s
abretonc7s enabled auto-merge August 12, 2026 02:04

@geositta geositta left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/perps-controller/src/services/TerminalMarketService.ts Outdated
@abretonc7s
abretonc7s requested a review from geositta August 12, 2026 05:29
@abretonc7s
abretonc7s force-pushed the perf/3662-perps-bootstrap-snapshots branch 2 times, most recently from d17d1c7 to c060160 Compare August 12, 2026 16:49
Comment thread packages/perps-controller/src/PerpsController.ts
@abretonc7s
abretonc7s force-pushed the perf/3662-perps-bootstrap-snapshots branch from c060160 to 86aa8c4 Compare August 12, 2026 17:54
Comment thread packages/perps-controller/src/PerpsController.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ 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.

Comment thread packages/perps-controller/src/providers/HyperLiquidProvider.ts
@abretonc7s

Copy link
Copy Markdown
Contributor Author

Final review-ready SHA: c6c4aa8c964b828e684d926b401f526296207ea9 (0 behind main). The requested body-timeout fix remains preserved. Final corrections also align exact Terminal DEX/clock/price validation, provider-instance request races, atomic TP/SL parity, and bare DEX-shorthand preload identity. Local Node 24 full build, package lint, focused controller/provider/contract suites, real Core→Nest/Redis recipe, format, and diff checks pass. Re-review requested.

@abretonc7s
abretonc7s added this pull request to the merge queue Aug 12, 2026
Merged via the queue into main with commit 0837703 Aug 12, 2026
436 checks passed
@abretonc7s
abretonc7s deleted the perf/3662-perps-bootstrap-snapshots branch August 12, 2026 23:14
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.

2 participants