Skip to content

feat(perps): sync controller from mobile#8460

Merged
abretonc7s merged 1 commit intomainfrom
feat/perps/new-sync
Apr 15, 2026
Merged

feat(perps): sync controller from mobile#8460
abretonc7s merged 1 commit intomainfrom
feat/perps/new-sync

Conversation

@abretonc7s
Copy link
Copy Markdown
Contributor

@abretonc7s abretonc7s commented Apr 15, 2026

Explanation

Syncs app/controllers/perps/ from MetaMask Mobile (commit 87ad5e48) to packages/perps-controller/src/ using the automated validate-core-sync.sh pipeline. All 9 sync steps passed with 0 suppressions.

Key changes:

  • Disk-backed cold-start cache — new perpsDiskPersistence.ts enables instant data display on launch by hydrating in-memory caches from MMKV synchronously at construction time. Adds skipTTL option to getCachedMarketDataForActiveProvider and getCachedUserDataForActiveProvider so disk-hydrated data is returned regardless of age on first render.
  • Perps decimal formatters — new perpsFormatters.ts exports shared formatting utilities (price, size, leverage, PnL, funding rate) from the controller for use by extension consumers.
  • TP/SL order fix — filters TP/SL orders by isPositionTpsl to prevent position-bound orders from disappearing after creating a market order. Distinguishes position TP/SL from normalTpsl children on pending limit orders.
  • WebSocket reconnection fix — avoids full reconnection on foreground return when the WebSocket is still alive within the grace period. Adds ForegroundPingRetryDelayMs constant.
  • Geo-block compliance — enforces compliance gate on Market Insights Long/Short actions.
  • Funding payments fix — replaces single API call with paginated fetch using fetchWindowWithAutoSplit that recursively splits windows hitting the API cap, ensuring complete results. Deduplicates at chunk boundaries.
  • Funding rate config — adds FUNDING_RATE_CONFIG constants for display formatting.
  • Cache key refactoring — extracts buildProviderCacheKey and getProviderNetworkKey helpers. Replaces private #marketCacheKey/#providerIsTestnet with shared utilities. Adds #getAggregatedCacheProviderIds to recover disk-hydrated provider snapshots before init() finishes.
  • MYX dynamic import fix — removes variable indirection for ts-bridge compatibility.

New files:

  • packages/perps-controller/src/utils/perpsDiskPersistence.ts (360 lines)
  • packages/perps-controller/src/utils/perpsFormatters.ts (624 lines)

References

  • Mobile PR chain: disk cache (#27898), formatters (#28538), TP/SL fix (#28073), WS fix (#28592), geo-block (#28678), funding fix (#28671)

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 and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Touches core PerpsController caching/preload behavior (including new disk persistence and cache-key refactors) plus funding history fetching logic; regressions could impact cold-start UI correctness or data freshness across networks/accounts.

Overview
Adds a disk-backed cold-start cache for perps market/user data. PerpsController now hydrates in-memory caches synchronously at construction, persists preload snapshots back to disk, and clears disk user data on account changes; cache reads gain an optional skipTTL to allow first-render usage of disk-hydrated data.

Refactors cache keying and aggregated cache reads. Introduces buildProviderCacheKey/getProviderNetworkKey helpers and updates aggregated reads to include provider ids inferred from disk-hydrated keys before init() completes.

Fixes and shared utilities. TP/SL lookup now filters by isPositionTpsl to avoid hiding position-bound TP/SL orders, funding history fetching switches to paginated windowed requests with recursive auto-splitting/deduping to avoid API caps, and new perpsFormatters/FUNDING_RATE_CONFIG are exported for consistent formatting.

Reviewed by Cursor Bugbot for commit b36f510. Bugbot is set up for automated code reviews on this repo. Configure here.

@abretonc7s abretonc7s requested a review from a team as a code owner April 15, 2026 08:47
Comment thread packages/perps-controller/src/PerpsController.ts
@abretonc7s abretonc7s requested a review from a team as a code owner April 15, 2026 08:58
Copy link
Copy Markdown

@cursor cursor Bot left a comment

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.

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 c33111b658fb9f5689ee75317c5c1a19a9141dce. Configure here.

Comment thread packages/perps-controller/src/PerpsController.ts
@abretonc7s abretonc7s force-pushed the feat/perps/new-sync branch 2 times, most recently from de01135 to 5941237 Compare April 15, 2026 09:27
Syncs app/controllers/perps/ from mobile commit 87ad5e48.

Changes:
- Disk-backed cold-start cache for instant data display on launch (perpsDiskPersistence.ts)
- Export perps decimal formatters to controller (perpsFormatters.ts)
- Fix TP/SL orders disappearing after creating a market order (isPositionTpsl filter)
- Avoid full WS reconnection on foreground return when socket still alive
- Enforce geo-block and compliance gate on Market Insights actions
- Fix missing latest funding payments via paginated fetch with auto-split
- Add funding rate display config constants
- Extract buildProviderCacheKey/getProviderNetworkKey helpers
- Add skipTTL option to cache read methods for disk-hydrated data
- Add diskCache mock to test fixtures
- Update CHANGELOG.md
@abretonc7s abretonc7s force-pushed the feat/perps/new-sync branch from 5941237 to b36f510 Compare April 15, 2026 09:33
@abretonc7s abretonc7s added this pull request to the merge queue Apr 15, 2026
@abretonc7s
Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-previews

Merged via the queue into main with commit 19e50c1 Apr 15, 2026
345 checks passed
@abretonc7s abretonc7s deleted the feat/perps/new-sync branch April 15, 2026 09:47
@abretonc7s
Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@abretonc7s
Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-previews

github-merge-queue Bot pushed a commit that referenced this pull request Apr 15, 2026
## Explanation

This restores the `myxModulePath` workaround for the `MYXProvider`
dynamic import in `@metamask/perps-controller` so the built package
preserves `webpackIgnore` and consumers do not statically resolve the
intentionally-unpublished MYX provider files.

This is the narrow publish fix that matches mobile source-of-truth
follow-up `MetaMask/metamask-mobile#28871` and unblocks a corrected
controller publication for the extension decimal-format adoption in
`MetaMask/metamask-extension#41558`.

## References

- Related to #8424
- Related to #8460
- Related to MetaMask/metamask-mobile#28871
- Related to MetaMask/metamask-extension#41558

## 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
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches HyperLiquid market discovery caching and WebSocket
subscription teardown logic, which can affect market availability and
live data stability. Also adjusts the MYX dynamic import path handling
to influence bundling behavior in downstream consumers.
> 
> **Overview**
> Restores the MYX provider dynamic import workaround by moving the
module path into a variable so built dist output preserves the `/*
webpackIgnore: true */` comment and extension consumers don’t statically
resolve the unpublished MYX module.
> 
> Refactors HyperLiquid DEX discovery into a new unified
`DexDiscoveryCacheManager` (with a `DexDiscoveryState` type) and updates
call sites to use the shared state for raw/validated DEX lists and TTL
behavior, reducing cache desync and avoiding rapid market-switching
429s.
> 
> Switches HyperLiquid candle snapshots to use an HTTP `InfoClient`
transport, and updates subscription teardown to explicitly
`unsubscribe()` all active subscriptions during `clearAll` to prevent
orphaned-unsubscribe `SOCKET_NOT_CONNECTED` errors during disconnect.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
3430560. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
github-merge-queue Bot pushed a commit to MetaMask/metamask-mobile that referenced this pull request Apr 16, 2026
## **Description**

This restores the `myxModulePath` workaround in mobile `PerpsController`
so the mobile source of truth matches the safe Core pattern from
`core#8424`, and it hardens `scripts/perps/validate-core-sync.sh` plus
the `perps-core-sync` skill so future syncs fail if the built Core
publish artifact loses the `webpackIgnore` safeguard again.

This branch has been refreshed onto a `main` that already includes
#28865, so no separate follow-up is still
pending for the historical candle transport fix.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
- Related to MetaMask/core#8424
- Related to MetaMask/core#8460
- Related to MetaMask/core#8473
- Related to MetaMask/metamask-extension#41558
- Refreshed onto `main` after #28865 merged

## **Manual testing steps**

```gherkin
Feature: preserve MYX publish safety during mobile-to-core sync

  Scenario: validate the sync guard on a clean Core checkout
    Given mobile is on this branch and Core is checked out locally
    When I run `bash scripts/perps/validate-core-sync.sh --core-path <core-path> --skip-test`
    Then the copied-source validation reaches the publish-artifact gate
    And the run fails if the built Core artifact does not preserve the MYX webpackIgnore safeguard

  Scenario: validate the perps historical candle transport coverage that is already present on main
    When I run `yarn jest app/controllers/perps/services/HyperLiquidClientService.test.ts --no-coverage`
    Then the TAT-2954 historical candle HTTP transport coverage passes
```

## **Screenshots/Recordings**

### **Before**

N/A - controller/source-sync change only.

### **After**

N/A - controller/source-sync change only.

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
vinnyhoward pushed a commit to MetaMask/metamask-mobile that referenced this pull request Apr 17, 2026
## **Description**

This restores the `myxModulePath` workaround in mobile `PerpsController`
so the mobile source of truth matches the safe Core pattern from
`core#8424`, and it hardens `scripts/perps/validate-core-sync.sh` plus
the `perps-core-sync` skill so future syncs fail if the built Core
publish artifact loses the `webpackIgnore` safeguard again.

This branch has been refreshed onto a `main` that already includes
#28865, so no separate follow-up is still
pending for the historical candle transport fix.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
- Related to MetaMask/core#8424
- Related to MetaMask/core#8460
- Related to MetaMask/core#8473
- Related to MetaMask/metamask-extension#41558
- Refreshed onto `main` after #28865 merged

## **Manual testing steps**

```gherkin
Feature: preserve MYX publish safety during mobile-to-core sync

  Scenario: validate the sync guard on a clean Core checkout
    Given mobile is on this branch and Core is checked out locally
    When I run `bash scripts/perps/validate-core-sync.sh --core-path <core-path> --skip-test`
    Then the copied-source validation reaches the publish-artifact gate
    And the run fails if the built Core artifact does not preserve the MYX webpackIgnore safeguard

  Scenario: validate the perps historical candle transport coverage that is already present on main
    When I run `yarn jest app/controllers/perps/services/HyperLiquidClientService.test.ts --no-coverage`
    Then the TAT-2954 historical candle HTTP transport coverage passes
```

## **Screenshots/Recordings**

### **Before**

N/A - controller/source-sync change only.

### **After**

N/A - controller/source-sync change only.

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] I've included tests if applicable
- [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
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