Skip to content

feat: Perps Controller integration#40078

Open
gambinish wants to merge 313 commits intomainfrom
perps/poc-controller-integration-temp
Open

feat: Perps Controller integration#40078
gambinish wants to merge 313 commits intomainfrom
perps/poc-controller-integration-temp

Conversation

@gambinish
Copy link
Member

@gambinish gambinish commented Feb 13, 2026

Description

Summary

This PR integrates the @metamask/perps-controller package into MetaMask Extension, establishing the foundational controller layer for perpetual futures trading functionality. This branch began from a larger feature branch that included both controller integration and UI components - we've decoupled the UI in a separate downstream PR to unblock merging while using a preview package dependency.

The UI PR should go in before this one: #40076

Background

Originally developed as a comprehensive feature branch as a PoC, it included both backend controller integration and frontend UI. This quickly became bloated and difficult to manage, and was blocked to merge due to a preview-package dependency. This PR has been scoped down to focus on controller integration only.

The main blocker for merging was the dependency on a preview package (@metamask/perps-controller@0.0.0-preview-e4aa1532) which cannot be merged into main.

Core Controller Setup:

  • Added PerpsController integration via app/scripts/controllers/perps/index.ts
  • Implemented platform-specific infrastructure wiring in app/scripts/controllers/perps/infrastructure.ts
    • Connects controller to KeyringController for signing operations
    • Stubs for metrics (MetaMetrics), logging (Sentry), and performance monitoring
    • Stream manager for real-time market data
  • Integrated controller into metamask-controller.js

Dependencies:

  • Added preview package: @metamask/perps-controller@0.0.0-preview-e4aa1532 (temporary)
  • Updated LavaMoat policies for all build variants (MV2/MV3, main/beta/flask/experimental)

Architecture Notes

The PerpsController runs in the background to integrate with the messenger API for cross controller communication. Websocket streams are handled in the UI.

Migration Path

To use production package when ready:

  1. Update package.json:
    "dependencies": {
    "@metamask/perps-controller": "^1.0.0" // Replace preview version
    }

  2. Remove previewBuilds section in package.json

  3. Run yarn install and regenerate LavaMoat policies

When integrating the real @metamask/perps-controller we'll also need to remove aliases to the mock services:

  1. ✅ Install the real package: yarn add @metamask/perps-controller
  2. ✅ Remove the moduleNameMapper entries from both Jest configs
  3. ✅ Remove the webpack alias entry
  4. ✅ Remove the TypeScript paths entry
  5. ✅ Delete the entire ui/mocks/perps/perps-controller/ directory
  6. ✅ Update ui/hooks/perps/marginUtils.ts to import constants from the real package
  7. ✅ Test that all imports resolve correctly

Related Branches

Open in GitHub Codespaces

Changelog

CHANGELOG entry: Integrate Perps Controller

Related issues

Fixes:

Manual testing steps

  1. Go to this page...

Screenshots/Recordings

Before

After

Pre-merge author checklist

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.

Note

High Risk
Adds a new background controller that can initiate trading actions and typed-data signing, plus a new streaming channel into UI connections; mistakes here could affect signing safety, background stability, or data pushed to the UI. It also changes build/test/LavaMoat configuration to allow new ESM dependency trees, which can introduce bundling or policy regressions.

Overview
Integrates @metamask/perps-controller into modular controller init (new PerpsControllerInit, messenger wiring, controller/state typing updates) and adds extension-specific platform dependencies via createPerpsInfrastructure, including a geoblock fallback parsed from MM_PERPS_BLOCKED_REGIONS.

Extends metamask-controller to expose Perps background RPC methods, add perpsSignTypedData (EIP-712 v4), and introduce a per-UI-connection PerpsStreamBridge that emits perpsStreamUpdate messages and manages static/dynamic subscription lifecycles.

Removes local mocks/aliases for the perps controller and updates Jest/webpack tooling to transpile/handle new ESM dependencies; adds/updates LavaMoat policies and test nocks for geolocation endpoints.

Written by Cursor Bugbot for commit 2793e4c. This will update automatically on new commits. Configure here.

gambinish and others added 21 commits February 6, 2026 15:50
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39889?quickstart=1)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] 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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **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.
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39895?quickstart=1)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] 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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches perps order submission and TP/SL update paths and introduces
optimistic stream override logic; mistakes could cause incorrect UI
state or wrong parameters being sent to the controller.
> 
> **Overview**
> Improves perps TP/SL UX by replacing the auto-close unit
toggle/read-only gain-loss display with **bidirectional price/percent
inputs** plus preset % buttons, using `entryPrice` (when modifying a
position) for accurate calculations and adding new i18n strings for
labels/actions.
> 
> Extends the perps market detail position card with an **expandable
Auto Close editor** that saves TP/SL via `updatePositionTPSL`,
immediately reflects changes by pushing data into the stream with
**optimistic TP/SL overrides**, and refetches on tab visibility as a
safety net.
> 
> Hardens order/position flows by cleaning comma-formatted numeric
strings before API calls, preventing form resets caused by streaming
object churn, and adding a pending-order state that disables the order
form until the new position appears in the live stream (with timeout
fallback).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c70e20b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39951?quickstart=1)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] 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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Introduces new margin-adjustment UI that calls `perps-controller` to
update position margin and pushes fresh positions into the stream;
incorrect calculation/validation could lead to confusing or risky UX
(though core trading logic remains in the controller).
> 
> **Overview**
> Adds a new **Perps “Edit Margin” expandable** on the market detail
page, letting users switch between *Add*/*Remove* margin, enter an
amount (with presets), see updated liquidation price/distance, and
submit changes via `controller.updateMargin` (refreshing positions in
the stream and showing errors/risk warnings).
> 
> Introduces `usePerpsMarginCalculations` + `marginUtils` to compute max
addable/removable amounts, projected liquidation metrics, and removal
risk levels (mirroring controller config thresholds), and wires new i18n
strings for the margin UI.
> 
> Also tightens related perps UI behavior/tests: margin vs auto-close
expanders are mutually exclusive, modify-mode leverage slider now
enforces a minimum leverage equal to the existing position, home
positions list shows leverage, and several tests/baselines/mocks are
updated (including removing noisy console logs).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
54b61b2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Nick Gambino <gambinish@users.noreply.github.com>
…k/metamask-extension into perps/poc-controller-integration
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39962?quickstart=1)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] 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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **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.
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39971?quickstart=1)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] 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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **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.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches the perps market detail page with new live price subscription
logic and a 1s interval timer, which could affect rendering/performance
or cleanup behavior if mismanaged; otherwise changes are primarily
UI/formatting.
> 
> **Overview**
> Improves the perps market detail UI by adding **info tooltips** for
Funding Rate and Open Interest, plus a new **Oracle Price** row
populated from a live `subscribeToPrices` stream update.
> 
> Adds a per-second UTC **funding countdown** shown alongside the
funding rate, and polishes formatting/styling: available balance now
displays the numeric value, ROE uses percent formatting, size/margin
values are reformatted, and CTA button variants/styles are adjusted
(swap primary/secondary and remove custom long/short coloring).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
36d3d81. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39972?quickstart=1)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] 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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **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.
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/39999?quickstart=1)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] 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-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **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.
@github-actions
Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@socket-security
Copy link

socket-security bot commented Feb 13, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​metamask/​perps-controller@​1.0.0721008389100
Addedws@​8.19.09810010088100
Updatedviem@​2.44.4 ⏵ 2.46.299 +1100100 +197100

View full report

@socket-security
Copy link

socket-security bot commented Feb 13, 2026

Caution

MetaMask internal reviewing guidelines:

  • Do not ignore-all
  • Each alert has instructions on how to review if you don't know what it means. If lost, ask your Security Liaison or the supply-chain group
  • Copy-paste ignore lines for specific packages or a group of one kind with a note on what research you did to deem it safe.
    @SocketSecurity ignore npm/PACKAGE@VERSION
Action Severity Alert  (click "▶" to expand/collapse)
Block Medium
System shell access: npm @inquirer/external-editor in module child_process

Module: child_process

Location: Package overview

From: ?npm/@metamask/perps-controller@1.0.0npm/@inquirer/external-editor@2.0.3

ℹ Read more on: This package | This alert | What is shell access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should avoid accessing the shell which can reduce portability, and make it easier for malicious shell access to be introduced.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@inquirer/external-editor@2.0.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @metamask/perps-controller in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: package.jsonnpm/@metamask/perps-controller@1.0.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@metamask/perps-controller@1.0.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @myx-trade/sdk in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: ?npm/@metamask/perps-controller@1.0.0npm/@myx-trade/sdk@0.1.265

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@myx-trade/sdk@0.1.265. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm @nktkas/hyperliquid in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: ?npm/@metamask/perps-controller@1.0.0npm/@nktkas/hyperliquid@0.30.3

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@nktkas/hyperliquid@0.30.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm ethers in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: ?npm/@metamask/perps-controller@1.0.0npm/ethers@6.16.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/ethers@6.16.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm ethers in module net

Module: net

Location: Package overview

From: ?npm/@metamask/perps-controller@1.0.0npm/ethers@6.16.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/ethers@6.16.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm ethers in module http

Module: http

Location: Package overview

From: ?npm/@metamask/perps-controller@1.0.0npm/ethers@6.16.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/ethers@6.16.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm ethers in module https

Module: https

Location: Package overview

From: ?npm/@metamask/perps-controller@1.0.0npm/ethers@6.16.0

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/ethers@6.16.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm micro-eth-signer in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: ?npm/@metamask/perps-controller@1.0.0npm/micro-eth-signer@0.18.1

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/micro-eth-signer@0.18.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Block Medium
Network access: npm wretch in module globalThis["fetch"]

Module: globalThis["fetch"]

Location: Package overview

From: ?npm/@metamask/perps-controller@1.0.0npm/wretch@2.11.1

ℹ Read more on: This package | This alert | What is network access?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should remove all network access that is functionally unnecessary. Consumers should audit network access to ensure legitimate use.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/wretch@2.11.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn Low
Potential code anomaly (AI signal): npm ethers is 100.0% likely to have a medium risk anomaly

Notes: The analyzed code fragment appears to be a conventional ABI interface utility (likely from a library like ethers.js) used to parse, encode, and decode Ethereum function calls, events, and errors. There is no evidence of malicious behavior such as data exfiltration, remote control, or code injection. Minor anomalies (typo in an error message and a partially commented/unfinished block) are present but do not constitute malicious activity. Overall security risk from this fragment is low, assuming it is used as intended within a trusted library context.

Confidence: 1.00

Severity: 0.60

From: ?npm/@metamask/perps-controller@1.0.0npm/ethers@6.16.0

ℹ Read more on: This package | This alert | What is an AI-detected potential code anomaly?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: An AI system found a low-risk anomaly in this package. It may still be fine to use, but you should check that it is safe before proceeding.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/ethers@6.16.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 13, 2026

✨ Files requiring CODEOWNER review ✨

👨‍🔧 @MetaMask/extension-platform (1 files, +34 -0)
  • 📁 test/
    • 📁 e2e/
      • 📁 fixtures/
        • 📄 onboarding-fixture.json +34 -0

🕵️ @MetaMask/extension-privacy-reviewers (1 files, +1 -0)
  • 📄 privacy-snapshot.json +1 -0

👨‍🔧 @MetaMask/perps (4 files, +901 -0)
  • 📁 app/
    • 📁 scripts/
      • 📁 controllers/
        • 📁 perps/
          • 📄 infrastructure.test.ts +79 -0
          • 📄 infrastructure.ts +176 -0
          • 📄 perps-stream-bridge.test.ts +494 -0
          • 📄 perps-stream-bridge.ts +152 -0

📜 @MetaMask/policy-reviewers (8 files, +1700 -0)
  • 📁 lavamoat/
    • 📁 browserify/
      • 📁 beta/
        • 📄 policy.json +231 -0
      • 📁 experimental/
        • 📄 policy.json +231 -0
      • 📁 flask/
        • 📄 policy.json +231 -0
      • 📁 main/
        • 📄 policy.json +231 -0
    • 📁 webpack/
      • 📁 mv2/
        • 📁 beta/
          • 📄 policy.json +194 -0
        • 📁 experimental/
          • 📄 policy.json +194 -0
        • 📁 flask/
          • 📄 policy.json +194 -0
        • 📁 main/
          • 📄 policy.json +194 -0

Tip

Follow the policy review process outlined in the LavaMoat Policy Review Process doc before expecting an approval from Policy Reviewers.


🧪 @MetaMask/qa (1 files, +34 -0)
  • 📁 test/
    • 📁 e2e/
      • 📁 fixtures/
        • 📄 onboarding-fixture.json +34 -0

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 3, 2026

Builds ready [8d3560a]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account30126532727327327
total30126532727327327
Confirm Txconfirm_tx606360556070560656070
total606360556070560656070
Bridge User Actionsbridge_load_page1901802007194200
bridge_load_asset_picker2112022227212222
bridge_search_token71570173111725731
total1162110112516312231251
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup16211376212210416681792
load13621132178511014231533
domContentLoaded13551127174210914161519
domInteractive3419142262992
firstPaint1657444887231352
backgroundConnect25023131113257271
firstReactRender21145972232
initialActions207125
loadScripts1121888149210811811286
setupStore1473661824
numNetworkReqs312290192781
Power User HomeuiStartup21231458650176321133672
load12871143177214613141645
domContentLoaded12751133176214413071637
domInteractive3519148203681
firstPaint1887446486261341
backgroundConnect46528836044333641002
firstReactRender24164772738
initialActions104113
loadScripts1033904150014110571388
setupStore1573661630
numNetworkReqs63351492669125
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2192192200220220
srpButtonToSrpForm95959509595
confirmSrpToPwForm22212312323
pwFormToMetricsScreen16151601616
metricsToWalletReadyScreen16151601616
doneButtonToHomeScreen6136056185617618
openAccountMenuToAccountListLoaded2927291229481329342948
total3910389539251339213925
Onboarding New WalletcreateWalletToSocialScreen2192182211220221
srpButtonToPwForm1041021051105105
createPwToRecoveryScreen888088
skipBackupToMetricsScreen40364954249
agreeButtonToOnboardingSuccess16151711617
doneButtonToAssetList60157763023625630
total99096310212410141021
Asset DetailsassetClickToPriceChart42374744547
total42374744547
Solana Asset DetailsassetClickToPriceChart81759168191
total81759168191
Import Srp HomeloginToHomeScreen2137206722758321292275
openAccountMenuAfterLogin53495525555
homeAfterImportWithNewWallet2663253627508027052750
total49834781516712750355167
Send TransactionsopenSendPageFromHome19162431824
selectTokenToSendFormLoaded20182222122
reviewTransactionToConfirmationPage8478458502848850
total8868808904889890
SwapopenSwapPageFromHome1089211710116117
fetchAndDisplaySwapQuotes289028872892228922892
total3024299830622430273062
🌐 Dapp Page Load Benchmarks

Current Commit: 8d3560a | Date: 3/3/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.04s (±42ms) 🟡 | historical mean value: 1.06s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 733ms (±40ms) 🟢 | historical mean value: 743ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 81ms (±11ms) 🟢 | historical mean value: 85ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.04s 42ms 1.02s 1.36s 1.08s 1.36s
domContentLoaded 733ms 40ms 709ms 1.04s 766ms 1.04s
firstPaint 81ms 11ms 60ms 176ms 92ms 176ms
firstContentfulPaint 81ms 11ms 60ms 176ms 92ms 176ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: -63.33 KiB (-1.18%)
  • ui: 27.91 KiB (0.33%)
  • common: 2.51 MiB (23.04%)

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 4, 2026

Builds ready [5530f02]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2662592756266275
total2662592756266275
Confirm Txconfirm_tx6067600362077760966207
total6067600362077760966207
Bridge User Actionsbridge_load_page23718631949254319
bridge_load_asset_picker23813929359289293
bridge_search_token72470574818733748
total12221097144912912541449
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup15211264182511716071703
load12871060150310713781457
domContentLoaded12801055149110513701439
domInteractive3017139212776
firstPaint181651248135223354
backgroundConnect24322045924246262
firstReactRender18124552029
initialActions1010123
loadScripts1052826126210611441220
setupStore1473161728
numNetworkReqs312298212290
Power User HomeuiStartup18351510235815118912115
load12661129188415612501709
domContentLoaded12511123179714912411701
domInteractive3820145233992
firstPaint198781750181243365
backgroundConnect33729244628350384
firstReactRender24165682541
initialActions107113
loadScripts100488015261479891440
setupStore1674981831
numNetworkReqs57351592659127
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2222212241222224
srpButtonToSrpForm101991032102103
confirmSrpToPwForm23232302323
pwFormToMetricsScreen16161701717
metricsToWalletReadyScreen18181801818
doneButtonToHomeScreen61760165622611656
openAccountMenuToAccountListLoaded30172905315711231483157
total40593910418311041404183
Onboarding New WalletcreateWalletToSocialScreen2202182222222222
srpButtonToPwForm1081021134112113
createPwToRecoveryScreen989099
skipBackupToMetricsScreen36363713737
agreeButtonToOnboardingSuccess16161701617
doneButtonToAssetList50348152420522524
total89286291826917918
Asset DetailsassetClickToPriceChart47415554855
total47415554855
Solana Asset DetailsassetClickToPriceChart74717837578
total74717837578
Import Srp HomeloginToHomeScreen2049197321175520832117
openAccountMenuAfterLogin39364124141
homeAfterImportWithNewWallet28112556311418628873114
total48244714494910749114949
Send TransactionsopenSendPageFromHome18181911919
selectTokenToSendFormLoaded19182012020
reviewTransactionToConfirmationPage8498488511851851
total8878858881888888
SwapopenSwapPageFromHome12410713710130137
fetchAndDisplaySwapQuotes289028892894228902894
total3016299630301230203030
🌐 Dapp Page Load Benchmarks

Current Commit: 5530f02 | Date: 3/3/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.07s (±42ms) 🟡 | historical mean value: 1.06s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 733ms (±40ms) 🟢 | historical mean value: 742ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 83ms (±11ms) 🟢 | historical mean value: 83ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.07s 42ms 1.04s 1.37s 1.10s 1.37s
domContentLoaded 733ms 40ms 706ms 1.03s 762ms 1.03s
firstPaint 83ms 11ms 64ms 172ms 92ms 172ms
firstContentfulPaint 83ms 11ms 64ms 172ms 92ms 172ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: -63.33 KiB (-1.18%)
  • ui: 27.91 KiB (0.33%)
  • common: 2.51 MiB (23.04%)

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 4, 2026

Builds ready [143ed9f]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2742712773275277
total2742712773275277
Confirm Txconfirm_tx608160746088660886088
total608160746088660886088
Bridge User Actionsbridge_load_page20918025225220252
bridge_load_asset_picker21920023613222236
bridge_search_token72170873610724736
total1145112111882611381188
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup15181277200210915631713
load12821061171510513181472
domContentLoaded12771056170910513131465
domInteractive2916117212591
firstPaint1496751272192273
backgroundConnect23721626811244260
firstReactRender201310092132
initialActions107124
loadScripts1054841145810210841239
setupStore1474971725
numNetworkReqs312296192380
Power User HomeuiStartup18051501247317218532172
load12511138206416212281701
domContentLoaded12391125203516112201694
domInteractive36201412534104
firstPaint175771718173187315
backgroundConnect33529047735345408
firstReactRender25156292642
initialActions109113
loadScripts99188817031509671408
setupStore1754892034
numNetworkReqs58341502659124
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2202172221221222
srpButtonToSrpForm94939629696
confirmSrpToPwForm22212202222
pwFormToMetricsScreen15151601616
metricsToWalletReadyScreen16151701617
doneButtonToHomeScreen6106076195609619
openAccountMenuToAccountListLoaded2930291329702429212970
total3907388939472338973947
Onboarding New WalletcreateWalletToSocialScreen2202172222221222
srpButtonToPwForm1071051112108111
createPwToRecoveryScreen999099
skipBackupToMetricsScreen37363813838
agreeButtonToOnboardingSuccess16151711717
doneButtonToAssetList57849468572637685
total96888810787210251078
Asset DetailsassetClickToPriceChart47474704747
total47474704747
Solana Asset DetailsassetClickToPriceChart74688357383
total74688357383
Import Srp HomeloginToHomeScreen2150212721731921732173
openAccountMenuAfterLogin47385885558
homeAfterImportWithNewWallet2818277028724728592872
total51434832556325652925563
Send TransactionsopenSendPageFromHome22172942529
selectTokenToSendFormLoaded19182002020
reviewTransactionToConfirmationPage8468448482847848
total8878818925892892
SwapopenSwapPageFromHome1201081308123130
fetchAndDisplaySwapQuotes290328922911829112911
total3044301930802530543080

Dapp page load benchmarks: data not available.

Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: -63.33 KiB (-1.18%)
  • ui: 28.44 KiB (0.34%)
  • common: 2.51 MiB (23.04%)

@Gudahtt
Copy link
Member

Gudahtt commented Mar 4, 2026

I don't think we can merge this as-is. The amount of code we're adding here is enormous, in large part due to the bizarre architectural choices made. And the bundle size has increased a huge amount (the common bundle is 23% larger, which will slow down page load).

Please revise this to be structured more similarly to our other features, with a clearer separation between the UI and the background (so that the UI bundle doesn't end up with this massive size increase)

abretonc7s and others added 2 commits March 4, 2026 11:53
)

## Description

This PR implements **Path 2** from the streaming architecture
discussion: move WebSocket ownership from the UI to the background
process, eliminating the dual-controller problem flagged in
[#40078](#40078).

### The Problem (from #40078 review)

The current architecture creates two `PerpsController` instances — one
in the background and one in the UI — resulting in:
- Two independent WebSocket connections to HyperLiquid
- Split controller authority / two state machines
- Risk of race conditions and data inconsistency

### Path 2: Custom JSON-RPC Notification Channel

Background subscribes to HyperLiquid WebSocket via `PerpsController`,
then emits `perpsStreamUpdate` notifications over the existing
`outStream` connection. The UI handles them alongside `sendUpdate` in
`ui/index.js`.

```
Background PerpsController (WebSocket owner)
  → subscribeToPositions/Orders/Account/Prices/OrderBook/Candles
  → emitPerpsUpdate(channel, data) → outStream.write({ method: 'perpsStreamUpdate' })
    ↓ (only when perpsSubscriberCount > 0)
UI ui/index.js onNotification
  → getPerpsStreamManager().handleBackgroundUpdate({ channel, data })
    ↓
PerpsDataChannel.pushData() → React subscribers (direct, no Redux, no debounce)
```

### What Changed

| Area | Change |
|---|---|
| `metamask-controller.js` | Subscribe background controller to all 6
channels on connection setup; emit `perpsStreamUpdate` notifications;
track per-connection subscriber count via `perpsSubscriberChange` |
| `ui/index.js` | Route `perpsStreamUpdate` →
`PerpsStreamManager.handleBackgroundUpdate()` |
| `getPerpsController.ts` | **Remove UI `PerpsController` instantiation
entirely** — no `new PerpsController()`, no messenger, no streaming
controller |
| `createPerpsControllerFacade.ts` | Remove all streaming methods; all
operations delegate to background |
| `PerpsStreamManager.ts` | Add `prices`/`orderBook` channels;
`handleBackgroundUpdate()` for all 6 channels; initial REST `connectFn`
for positions/orders/account; eager cache clear on account switch |
| `CandleStreamChannel.ts` | Add `pushFromBackground()` |
| `usePerpsLivePrices` / `usePerpsLiveOrderBook` | Migrate from direct
controller subscribe → `usePerpsChannel` pattern |
| `usePerpsStreamManager` | Clear caches synchronously on account switch
to prevent stale-data flash |

### Key Properties

- **No Redux overhead** for high-frequency data (prices, orderBook,
candles)
- **No debounce** — data reaches React components directly via
`PerpsDataChannel.pushData()`
- **Component-scoped**: only UI connections with `perpsSubscriberCount >
0` receive stream data
- **Single WebSocket**: one connection per HyperLiquid endpoint, owned
by background
- **Cache preserved** across navigation; cleared on account switch

### Tests

193 tests passing across 12 suites. All perps provider and hook tests
updated to match new architecture.

## Changelog

CHANGELOG entry: null

## Related

- Base PR: #40078 (PerpsController integration)
- Architecture discussion: Path 2 from streaming ownership thread

---------

Co-authored-by: Nicholas Gambino <nicholas.gambino@consensys.net>
@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 4, 2026

Builds ready [30bd5e1]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2792722875281287
total2792722875281287
Confirm Txconfirm_tx6049599561274760646127
total6049599561274760646127
Bridge User Actionsbridge_load_page2422412431243243
bridge_load_asset_picker19414127247213272
bridge_search_token74169782247764822
total1183108113359312191335
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup15101261190611815571777
load12721054164110813151480
domContentLoaded12631048156610513081473
domInteractive2817110202489
firstPaint225731577266242425
backgroundConnect22319927214227258
firstReactRender19116162028
initialActions402372313
loadScripts1058841135910411081260
setupStore1464271725
numNetworkReqs312292202283
Power User HomeuiStartup260414596154133128995647
load12251061171814812411581
domContentLoaded12071044171014312271569
domInteractive37181552536108
firstPaint19981509104273391
backgroundConnect81226845469428022794
firstReactRender25165672741
initialActions1013113
loadScripts98882714701399991341
setupStore1774782033
numNetworkReqs71261582884127
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2202182232221223
srpButtonToSrpForm95939619696
confirmSrpToPwForm22212202222
pwFormToMetricsScreen15151601516
metricsToWalletReadyScreen17161801818
doneButtonToHomeScreen6055996167606616
openAccountMenuToAccountListLoaded2922289929331429332933
total389938873912939023912
Onboarding New WalletcreateWalletToSocialScreen2212162263222226
srpButtonToPwForm1051031072105107
createPwToRecoveryScreen888088
skipBackupToMetricsScreen35353603536
agreeButtonToOnboardingSuccess16161601616
doneButtonToAssetList571491761105607761
total960874114310710201143
Asset DetailsassetClickToPriceChart1181091349124134
total1181091349124134
Solana Asset DetailsassetClickToPriceChart907711015105110
total907711015105110
Import Srp HomeloginToHomeScreen1941186820446419302044
openAccountMenuAfterLogin443360104860
homeAfterImportWithNewWallet2641257327989225972798
total48114487524730150865247
Send TransactionsopenSendPageFromHome20132752527
selectTokenToSendFormLoaded19192001920
reviewTransactionToConfirmationPage8488468512847851
total8918898921892892
SwapopenSwapPageFromHome49405665456
fetchAndDisplaySwapQuotes269326902697326972697
total2746273027561027512756
🌐 Dapp Page Load Benchmarks

Current Commit: 30bd5e1 | Date: 3/4/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.07s (±77ms) 🟡 | historical mean value: 1.05s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 758ms (±74ms) 🟢 | historical mean value: 740ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 83ms (±10ms) 🟢 | historical mean value: 82ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.07s 77ms 1.03s 1.39s 1.29s 1.39s
domContentLoaded 758ms 74ms 719ms 1.06s 972ms 1.06s
firstPaint 83ms 10ms 68ms 164ms 96ms 164ms
firstContentfulPaint 83ms 10ms 68ms 164ms 96ms 164ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 2.35 MiB (44.88%)
  • ui: -679 Bytes (-0.01%)
  • common: 91.16 KiB (0.82%)

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 4, 2026

Builds ready [7088a27]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account31730633210318332
total31730633210318332
Confirm Txconfirm_tx6114608361402461346140
total6114608361402461346140
Bridge User Actionsbridge_load_page28324931928300319
bridge_load_asset_picker22418826327239263
bridge_search_token7617537686765768
total1248116613145312601314
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup14701177185510615111665
load123598815739612731416
domContentLoaded122898315469412681410
domInteractive3116132212783
firstPaint1506946377204266
backgroundConnect22819632920235263
firstReactRender19134052035
initialActions105114
loadScripts101779113479210561192
setupStore1363651520
numNetworkReqs322289203084
Power User HomeuiStartup17601367276120318012066
load11921038176416911861663
domContentLoaded11741021175116511641634
domInteractive41191592740109
firstPaint202801639169258334
backgroundConnect31127652132319360
firstReactRender24166192543
initialActions106113
loadScripts94881415101609331410
setupStore1674771829
numNetworkReqs60381562856135
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2202162232222223
srpButtonToSrpForm93919419394
confirmSrpToPwForm21212102121
pwFormToMetricsScreen15151501515
metricsToWalletReadyScreen16161601616
doneButtonToHomeScreen75260710851908481085
openAccountMenuToAccountListLoaded291429062922629182922
total3906389439321539023932
Onboarding New WalletcreateWalletToSocialScreen2192182211221221
srpButtonToPwForm1071051091109109
createPwToRecoveryScreen888088
skipBackupToMetricsScreen35353713537
agreeButtonToOnboardingSuccess16151711617
doneButtonToAssetList69148111152548531115
total1079868150025512511500
Asset DetailsassetClickToPriceChart12210913911129139
total12210913911129139
Solana Asset DetailsassetClickToPriceChart945511322111113
total945511322111113
Import Srp HomeloginToHomeScreen20441913222412021392224
openAccountMenuAfterLogin593498268298
homeAfterImportWithNewWallet2445243124732024732473
total45884409473411546524734
Send TransactionsopenSendPageFromHome23183152831
selectTokenToSendFormLoaded26184293242
reviewTransactionToConfirmationPage8478458481847848
total8908838996892899
SwapopenSwapPageFromHome35323723537
fetchAndDisplaySwapQuotes267826752680226802680
total271227102713127132713
🌐 Dapp Page Load Benchmarks

Current Commit: 7088a27 | Date: 3/4/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.05s (±47ms) 🟡 | historical mean value: 1.06s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 740ms (±66ms) 🟢 | historical mean value: 745ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 93ms (±133ms) 🟢 | historical mean value: 82ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.05s 47ms 1.03s 1.40s 1.06s 1.40s
domContentLoaded 740ms 66ms 715ms 1.32s 751ms 1.32s
firstPaint 93ms 133ms 64ms 1.41s 88ms 1.41s
firstContentfulPaint 93ms 133ms 64ms 1.41s 88ms 1.41s
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 2.35 MiB (44.88%)
  • ui: -680 Bytes (-0.01%)
  • common: 91.16 KiB (0.82%)

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 4, 2026

Builds ready [810ffe2]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account429272561128530561
total429272561128530561
Confirm Txconfirm_tx605860566063360636063
total605860566063360636063
Bridge User Actionsbridge_load_page25222928724274287
bridge_load_asset_picker18613823640215236
bridge_search_token74269781344768813
total1180106913029312331302
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup15501302187011915971776
load13011060159910813391497
domContentLoaded12931055156910813351493
domInteractive3218120212889
firstPaint188761226135243319
backgroundConnect24220835920246276
firstReactRender21124662236
initialActions107123
loadScripts1069843135510711011282
setupStore1474071725
numNetworkReqs322291192882
Power User HomeuiStartup240614579960143121654822
load12651082187216913181658
domContentLoaded12451077178716213001647
domInteractive3621123213693
firstPaint228861257144297357
backgroundConnect791270728912133842892
firstReactRender25175582742
initialActions106114
loadScripts1020863153615110721395
setupStore1774481834
numNetworkReqs72391672785132
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2192172212221221
srpButtonToSrpForm96969609696
confirmSrpToPwForm23222412324
pwFormToMetricsScreen16161601616
metricsToWalletReadyScreen17161811718
doneButtonToHomeScreen689601865106761865
openAccountMenuToAccountListLoaded2920290629421329232942
total39833877416510940534165
Onboarding New WalletcreateWalletToSocialScreen2192182201220220
srpButtonToPwForm1081061111109111
createPwToRecoveryScreen888088
skipBackupToMetricsScreen36363703737
agreeButtonToOnboardingSuccess16161701617
doneButtonToAssetList6246226252625625
total101010081013210131013
Asset DetailsassetClickToPriceChart1169715421123154
total1169715421123154
Solana Asset DetailsassetClickToPriceChart877110314101103
total877110314101103
Import Srp HomeloginToHomeScreen21742018239313522472393
openAccountMenuAfterLogin493866115666
homeAfterImportWithNewWallet2827279928511928332851
total50904913528312351465283
Send TransactionsopenSendPageFromHome20192222222
selectTokenToSendFormLoaded18172012020
reviewTransactionToConfirmationPage8498478543849854
total8888858954886895
SwapopenSwapPageFromHome37363913739
fetchAndDisplaySwapQuotes268926892689026892689
total272627252728127262728
🌐 Dapp Page Load Benchmarks

Current Commit: 810ffe2 | Date: 3/4/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.04s (±44ms) 🟡 | historical mean value: 1.06s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 735ms (±66ms) 🟢 | historical mean value: 745ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 84ms (±43ms) 🟢 | historical mean value: 83ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.04s 44ms 1.01s 1.39s 1.09s 1.39s
domContentLoaded 735ms 66ms 708ms 1.33s 779ms 1.33s
firstPaint 84ms 43ms 64ms 512ms 88ms 512ms
firstContentfulPaint 84ms 43ms 64ms 512ms 88ms 512ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 2.35 MiB (44.89%)
  • ui: -1.03 KiB (-0.01%)
  • common: 91.29 KiB (0.82%)

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 4, 2026

Builds ready [ea536b7]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2702612786273278
total2702612786273278
Confirm Txconfirm_tx6061604660781160706078
total6061604660781160706078
Bridge User Actionsbridge_load_page2452372525245252
bridge_load_asset_picker17513922635207226
bridge_search_token7057017083707708
total1124106512145711661214
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup13931153173511514411625
load116496014019611911352
domContentLoaded115795513939511871340
domInteractive2716115182569
firstPaint209641185211216364
backgroundConnect20819030614211231
firstReactRender18113342026
initialActions105124
loadScripts96676912049510001150
setupStore147128131523
numNetworkReqs3122103212288
Power User HomeuiStartup247815139323127424114483
load12971120205817213181697
domContentLoaded12791094197216813021685
domInteractive42212332940104
firstPaint2078745389287340
backgroundConnect793282780311694302838
firstReactRender26166172838
initialActions1011114
loadScripts1035879168815710631436
setupStore1884872032
numNetworkReqs69361552683124
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2192172201219220
srpButtonToSrpForm94939519595
confirmSrpToPwForm22212212222
pwFormToMetricsScreen16151711617
metricsToWalletReadyScreen17161701717
doneButtonToHomeScreen868610118525811741185
openAccountMenuToAccountListLoaded28332488314228631033142
total4064402641013141014101
Onboarding New WalletcreateWalletToSocialScreen2182172202220220
srpButtonToPwForm1071051081108108
createPwToRecoveryScreen981111011
skipBackupToMetricsScreen37354123941
agreeButtonToOnboardingSuccess16151811718
doneButtonToAssetList58049768064605680
total9698881067609871067
Asset DetailsassetClickToPriceChart1091051133110113
total1091051133110113
Solana Asset DetailsassetClickToPriceChart1151101183118118
total1151101183118118
Import Srp HomeloginToHomeScreen20241895217011020882170
openAccountMenuAfterLogin44365054850
homeAfterImportWithNewWallet28442567307320830443073
total50144851515310050645153
Send TransactionsopenSendPageFromHome22173052530
selectTokenToSendFormLoaded19191901919
reviewTransactionToConfirmationPage8478468471847847
total8928839016896901
SwapopenSwapPageFromHome41355274752
fetchAndDisplaySwapQuotes268726842690226872690
total272927212736627342736
🌐 Dapp Page Load Benchmarks

Current Commit: ea536b7 | Date: 3/4/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.06s (±47ms) 🟡 | historical mean value: 1.05s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 743ms (±42ms) 🟢 | historical mean value: 740ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 82ms (±15ms) 🟢 | historical mean value: 82ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.06s 47ms 1.02s 1.38s 1.11s 1.38s
domContentLoaded 743ms 42ms 714ms 1.04s 798ms 1.04s
firstPaint 82ms 15ms 64ms 212ms 92ms 212ms
firstContentfulPaint 82ms 15ms 64ms 212ms 92ms 212ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 2.35 MiB (44.89%)
  • ui: -9.41 KiB (-0.11%)
  • common: 91.28 KiB (0.82%)

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 4, 2026

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Mar 5, 2026

Builds ready [2793e4c]
⚡ Performance Benchmarks
👆 Interaction Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Load New Accountload_new_account2712652744273274
total2712652744273274
Confirm Txconfirm_tx6094606261242161076124
total6094606261242161076124
Bridge User Actionsbridge_load_page26120730835287308
bridge_load_asset_picker22518927030228270
bridge_search_token73970677529759775
total12331111141311212881413
🔌 Startup Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Standard HomeuiStartup14611235185810814991678
load12291045160010112581415
domContentLoaded1221101915959912511405
domInteractive2917118192781
firstPaint1627543283214373
backgroundConnect22319426914229247
firstReactRender20134662131
initialActions106123
loadScripts101681113819910461204
setupStore1475471624
numNetworkReqs312289192283
Power User HomeuiStartup17191372223615017911950
load11661038172714811481574
domContentLoaded11491029171614111341537
domInteractive37191502536103
firstPaint1796853189243294
backgroundConnect30626741426316359
firstReactRender23167482436
initialActions107114
loadScripts92681014861389131297
setupStore1664871926
numNetworkReqs58371562756128
🧭 User Journey Benchmarks
BenchmarkMetricMean (ms)Min (ms)Max (ms)Std Dev (ms)P75 (ms)P95 (ms)
Onboarding Import WalletimportWalletToSocialScreen2192182190219219
srpButtonToSrpForm93939409394
confirmSrpToPwForm21212102121
pwFormToMetricsScreen15151501515
metricsToWalletReadyScreen16151601616
doneButtonToHomeScreen67760278063693780
openAccountMenuToAccountListLoaded291029032914429122914
total3926387139684239653968
Onboarding New WalletcreateWalletToSocialScreen2212172243224224
srpButtonToPwForm1101081122110112
createPwToRecoveryScreen989089
skipBackupToMetricsScreen38344443944
agreeButtonToOnboardingSuccess16151811718
doneButtonToAssetList51248954521508545
total91187696533904965
Asset DetailsassetClickToPriceChart1151061299119129
total1151061299119129
Solana Asset DetailsassetClickToPriceChart937611115108111
total937611115108111
Import Srp HomeloginToHomeScreen22332017254719723502547
openAccountMenuAfterLogin543277197677
homeAfterImportWithNewWallet25392392274113326512741
total48264542513624149785136
Send TransactionsopenSendPageFromHome22172632526
selectTokenToSendFormLoaded18171801818
reviewTransactionToConfirmationPage8458438471846847
total8878818976889897
SwapopenSwapPageFromHome32263643436
fetchAndDisplaySwapQuotes2689267627011026972701
total2722270227351227302735
🌐 Dapp Page Load Benchmarks

Current Commit: 2793e4c | Date: 3/5/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.06s (±40ms) 🟡 | historical mean value: 1.05s ⬆️ (historical data)
  • domContentLoaded-> current mean value: 743ms (±37ms) 🟢 | historical mean value: 740ms ⬆️ (historical data)
  • firstContentfulPaint-> current mean value: 83ms (±11ms) 🟢 | historical mean value: 82ms ⬆️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.06s 40ms 1.02s 1.34s 1.08s 1.34s
domContentLoaded 743ms 37ms 713ms 1.01s 770ms 1.01s
firstPaint 83ms 11ms 68ms 184ms 88ms 184ms
firstContentfulPaint 83ms 11ms 68ms 184ms 88ms 184ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 2.45 MiB (47.58%)
  • ui: 453 Bytes (0.01%)
  • common: 376 Bytes (0%)

Copy link

@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 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

msgParams,
SignTypedDataVersion.V4,
);
},
Copy link

Choose a reason for hiding this comment

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

Unguarded signing bypasses user approval flow

High Severity

perpsSignTypedData directly calls KeyringController:signTypedMessage without any user approval, input validation, or confirmation dialog. This bypasses the standard SignatureController approval flow that all other typed-data signing operations use. The method accepts arbitrary msgParams with no validation that the data is actually a Perps trade operation, creating an unguarded EIP-712 signing surface accessible to any code running in the UI context.

Fix in Cursor Fix in Web

}
}
}
}
Copy link

Choose a reason for hiding this comment

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

Bridge destroy doesn't reset state causing potential double-unsub

Low Severity

destroy() calls all unsub functions but never clears #staticUnsubs, #dynamicUnsubs, or resets #activated. After destruction, isActive can still return true, and if activateStreaming() is called, #replaceSubscription will invoke already-called unsub functions from #dynamicUnsubs without try-catch protection, risking an unhandled exception.

Additional Locations (1)

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants