Repository navigation
feat(perps): add environment_type to controller-emitted perps events on extension (split from TAT-3175) - #10899
Merged
Conversation
abretonc7s
marked this pull request as ready for review
October 20, 2026 09:04
abretonc7s
temporarily deployed
to
default-branch
October 20, 2026 09:04 — with
GitHub Actions
Inactive
Accept an optional environmentType string on TrackingData, TPSLTrackingData, and WithdrawParams. Copy it to environment_type on trade, close, cancel, order, flip, and TP/SL events, on an order edit, and on the withdrawal executed event and both withdrawal failed events. Omit the key when the field is absent. Deposit params are unchanged. The controller emits no deposit event, so the deposit clause of TAT-4006 is deferred.
Add the changelog PR-link placeholder. No pull request number exists yet.
abretonc7s
force-pushed
the
TAT-4006-feat-add-environment-type-perps-eve
branch
from
October 20, 2026 09:51
ec2db26 to
debda2c
Compare
abretonc7s
enabled auto-merge
October 20, 2026 12:03
…ironment-type-perps-eve
…ironment-type-perps-eve
geositta
approved these changes
Oct 22, 2026
SnowingFox
pushed a commit
to SnowingFox/core-1
that referenced
this pull request
Oct 24, 2026
## Explanation Major release of `@metamask/perps-controller` (`21.0.0` → `22.0.0`). - **Breaking:** testnet deposit and withdrawal routes use Arbitrum Sepolia USDC2 (`0x1baAbB04529D43a73232B713C0FE471f7c7334d5`). `USDC_ARBITRUM_TESTNET_ADDRESS` and `HYPERLIQUID_ASSET_CONFIGS.usdc.testnet` change to that address, and `withdraw` rejects the previous testnet asset ID. `depositWithConfirmation` prepares an Arbitrum Sepolia transfer to the Hyperliquid testnet bridge. ([MetaMask#10991](MetaMask#10991)) - `TrackingData`, `TPSLTrackingData`, and `WithdrawParams` accept an optional `environmentType`. Events that already copy attribution include `environment_type` when it is set. ([MetaMask#10899](MetaMask#10899)) - New export `@metamask/perps-controller/providers/lighter`, plus optional `LighterCredentials.loadProvider`, so a web client can bundle Lighter itself. `switchProvider('lighter')` reports why the provider failed to load. A missing Lighter module is debug-logged instead of sent through `logger.error`. ([MetaMask#10996](MetaMask#10996)) - The `closePositions` summary event includes `order_type: 'market'`. ([MetaMask#11027](MetaMask#11027)) - Engines allow Node.js 26. ([MetaMask#10981](MetaMask#10981)) ## References - [MetaMask#10991](MetaMask#10991) - [MetaMask#10899](MetaMask#10899) - [MetaMask#10996](MetaMask#10996) - [MetaMask#11027](MetaMask#11027) - [MetaMask#10981](MetaMask#10981) ## 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** > Major perps-controller release with breaking testnet token/bridge behavior; this PR only bumps versions but consumers picking up 22.0.0 inherit that risk. > > **Overview** > **Monorepo release 1359.0.0** that publishes **`@metamask/perps-controller` 22.0.0** and bumps **`@metamask/transaction-pay-middleware`** to depend on `^22.0.0` (plus `yarn.lock` and root package version). > > The diff is mostly versioning and changelog housekeeping; the shipped **22.0.0** behavior (already merged) includes a **breaking testnet USDC2 / Arbitrum Sepolia deposit path** change, optional **`environmentType`** on perps tracking/withdraw params, **Lighter** `loadProvider` + public provider export, **`closePositions`** analytics `order_type: 'market'`, and **Node.js 26** engine support. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8356d7d. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
Controller perps events did not record which screen started the action.
PERPS_EVENT_PROPERTY.ENVIRONMENT_TYPEalready maps toenvironment_type, and no caller copied a value onto it.TrackingData,TPSLTrackingData, andWithdrawParamsnow accept an optionalenvironmentTypestring. Trade, close, cancel, order, flip, and TP/SL events that already copy attribution includeenvironment_typewhen the string is set. An order edit includes onlyenvironment_typefromnewOrder.trackingData. It does not copyentry_point,discovery_source,perp_discovery_source, orhl_fee_rate. The withdrawalexecutedevent and both withdrawalfailedevents includeenvironment_typethe same way. When the field is absent, those events stay unchanged.The controller emits no deposit event, so deposit params are unchanged and the deposit clause of TAT-4006 is deferred.
The value is not stored on withdrawal requests, and it is not sent to the venue. Later withdrawal completion events still omit it, because they no longer have the original params.
Extension still has to pass
getEnvironmentType()frombuildTrackingData,buildTpslTrackingData, and the withdraw call site. That is not enough on its own.createMetrics().trackPerpsEventinapp/scripts/controllers/perps/infrastructure.tscallstrackEventwithout options, andbuildTrackEventPayloadinapp/scripts/controllers/analytics/analytics.tsspreads the properties, then setsenvironment_typetooptions.environmentType, which defaults tobackground.trackPerpsEventmust passproperties.environment_typeas theenvironmentTypeoption, or the Core value is overwritten. Deposit call sites have nothing to pass until a registered deposit event exists. That client work follows this package release.A client recipe builds
PerpsControllerwith a real messenger. It callsplaceOrder,updatePositionTPSL, andwithdrawwithenvironmentTypeset tosidepanel, then again without the field. The messenger capturesAnalyticsController:trackEvent. The sidepanel calls emitenvironment_type=sidepanel. The calls without the field omit the key.depositWithConfirmationemits no controller analytics event. Unit tests still cover order edits.References
Validation Recipe
recipe.json (16 nodes — Perps environment_type through PerpsController)
{ "$schema": "https://farmslot.io/schemas/recipe-v1.schema.json", "title": "Perps environment_type through PerpsController", "description": "Drives PerpsController the way Extension does. A real Messenger receives AnalyticsController:trackEvent. placeOrder, updatePositionTPSL, and withdraw run with environmentType sidepanel, then again without it. The HyperLiquid SDK is replaced at the network boundary. depositWithConfirmation is a guard: the controller emits no deposit analytics event, so the field has nothing to attach to.", "proofTargets": [ { "id": "AC-1", "kind": "acceptance", "proofMode": "state", "claim": "Core (`@metamask/perps-controller`): accept an optional `environmentType` in `TrackingData` / `TPSLTrackingData` and in the withdraw/deposit params. Emit it as `PERPS_EVENT_PROPERTY.ENVIRONMENT_TYPE` (the key already exists)." }, { "id": "AC-2", "kind": "acceptance", "proofMode": "state", "claim": "When `environmentType` is absent, event properties are unchanged; unit tests cover `environmentType` present and absent on trade, TP/SL, withdraw and deposit events." } ], "workflow": { "entry": "build-controller", "nodes": { "build-controller": { "action": "command", "intent": "Compile @metamask/perps-controller so the client import matches this checkout", "cmd": "yarn workspace @metamask/perps-controller run build", "timeout_ms": 300000, "next": "run-trade-present" }, "run-trade-present": { "action": "command", "intent": "placeOrder with trackingData.environmentType sidepanel", "timeout_ms": 120000, "allow_failure": true, "next": "assert-trade-present" }, "assert-trade-present": { "action": "assert_output", "intent": "The trade event includes environment_type sidepanel", "source": "run-trade-present", "stream": "stdout", "contains": "PROOF trade present event=\"Perp Trade Transaction\" environment_type=sidepanel", "proves": [ "AC-1", "AC-2" ], "next": "run-trade-absent" }, "run-trade-absent": { "action": "command", "intent": "placeOrder with no environmentType", "timeout_ms": 120000, "next": "assert-trade-absent" }, "assert-trade-absent": { "action": "assert_output", "intent": "The trade event omits environment_type", "source": "run-trade-absent", "stream": "stdout", "contains": "PROOF trade absent event=\"Perp Trade Transaction\" environment_type_absent", "proves": [ "AC-2" ], "next": "run-tpsl-present" }, "run-tpsl-present": { "action": "command", "intent": "updatePositionTPSL with trackingData.environmentType sidepanel", "timeout_ms": 120000, "allow_failure": true, "next": "assert-tpsl-present" }, "assert-tpsl-present": { "action": "assert_output", "intent": "The TP/SL event includes environment_type sidepanel", "source": "run-tpsl-present", "stream": "stdout", "contains": "PROOF tpsl present event=\"Perp Risk Management\" environment_type=sidepanel", "proves": [ "AC-1", "AC-2" ], "next": "run-tpsl-absent" }, "run-tpsl-absent": { "action": "command", "intent": "updatePositionTPSL with no environmentType", "timeout_ms": 120000, "next": "assert-tpsl-absent" }, "assert-tpsl-absent": { "action": "assert_output", "intent": "The TP/SL event omits environment_type", "source": "run-tpsl-absent", "stream": "stdout", "contains": "PROOF tpsl absent event=\"Perp Risk Management\" environment_type_absent", "proves": [ "AC-2" ], "next": "run-withdraw-present" }, "run-withdraw-present": { "action": "command", "intent": "withdraw with environmentType sidepanel", "timeout_ms": 120000, "allow_failure": true, "next": "assert-withdraw-present" }, "assert-withdraw-present": { "action": "assert_output", "intent": "The withdrawal event includes environment_type sidepanel", "source": "run-withdraw-present", "stream": "stdout", "contains": "PROOF withdraw present event=\"Perp Withdrawal Transaction\" environment_type=sidepanel", "proves": [ "AC-1", "AC-2" ], "next": "run-withdraw-absent" }, "run-withdraw-absent": { "action": "command", "intent": "withdraw with no environmentType", "timeout_ms": 120000, "next": "assert-withdraw-absent" }, "assert-withdraw-absent": { "action": "assert_output", "intent": "The withdrawal event omits environment_type", "source": "run-withdraw-absent", "stream": "stdout", "contains": "PROOF withdraw absent event=\"Perp Withdrawal Transaction\" environment_type_absent", "proves": [ "AC-2" ], "next": "run-deposit-none" }, "run-deposit-none": { "action": "command", "intent": "depositWithConfirmation emits no controller analytics event", "timeout_ms": 120000, "next": "assert-deposit-none" }, "assert-deposit-none": { "action": "assert_output", "intent": "Deposit has no controller analytics event to carry environment_type", "source": "run-deposit-none", "stream": "stdout", "contains": "PROOF deposit none analytics_events=0", "next": "done" }, "done": { "action": "end", "status": "pass" } } } }Validation Logs
Run: f55b84c3-a90f-4b8d-948e-3dc70f183593
Runner: @metamask/recipe-runner
Runner revision: unknown
Recipe digest: sha256:8fd47e936c57d84ed2da64dca6e1be55c83e94d4ec8b2f4cf3e0444aa405ba56
Full output (16/16 passed, pass)
Checklist
Publication approval
Arthur · person · arthur · 2026-10-20T07:54:16.756Z
Package:
4f15b6a70f50d82a11d9a97ff1fb1438c92d52e3201c259f59dde77012781528. Visual receipts: none.Accepted review findings
Accepted by Arthur (arthur) at 2026-10-20T07:54:16.756Z.
Head:
ec2db26d96db4155d25123b57288d67d721d9108. Findings digest:sha256:5795a70a7ce39001832b15612a6eecc12ebc28451c1768adc0d5b40e8ab1c8f7.Reason:
Accepted findings:
Note
Low Risk
Analytics-only optional fields and property spreading; no trading, withdrawal routing, or persistence behavior changes.
Overview
Adds optional
environmentTypeonTrackingData,TPSLTrackingData, andWithdrawParamsso clients can tag which UI surface started a perps action.A shared
environmentTypePropertyhelper maps that value to the existingenvironment_typeanalytics key and is omitted when unset. Trading flows that already spread attribution (trade, close, cancel, flip, TP/SL, etc.) now includeenvironment_typewhen provided; order edit events only addenvironment_typefromnewOrder.trackingData, not other attribution fields.withdraw()adds it on executed and failed withdrawal events; later withdrawal status/completion paths are unchanged.Unit tests cover present vs absent
environment_typefor place order, edit order, TP/SL, and withdraw.Reviewed by Cursor Bugbot for commit 03ed916. Bugbot is set up for automated code reviews on this repo. Configure here.