fix(perps): address bugbot findings on Core PR #7941#26110
Conversation
- toggleTestnet: check InitializationState.Failed after init() and rollback isTestnet on failure (matching switchProvider pattern) - depositWithConfirmation: replace never-resolving promise with Promise.resolve(transactionMeta.id) when placeOrder=true
|
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. |
Hoist currentDepositId before try block so it is accessible in the outer catch. When a pre-submission error occurs (e.g. missing networkClientId), the deposit request is now marked as 'failed' instead of staying permanently 'pending' in state. Added test verifying the deposit request status on networkClientId lookup failure.
Prevent standalone preload from leaking WebSocket providers by caching the HyperLiquidProvider instance across standalone calls and cleaning it up at lifecycle boundaries (init, disconnect, toggleTestnet, etc.). Reorder switchProvider() to check "already active" before validating the providers map, so it returns a no-op success before init().
Add uuidv4() fallback for currentDepositId which TypeScript cannot narrow inside the update() callback after the variable was hoisted to let binding with string | undefined type.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #26110 +/- ##
==========================================
- Coverage 81.19% 81.08% -0.11%
==========================================
Files 4398 4399 +1
Lines 113804 113996 +192
Branches 24448 24492 +44
==========================================
+ Hits 92404 92438 +34
- Misses 15012 15138 +126
- Partials 6388 6420 +32 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
…cription Register all 34 PerpsControllerActions via registerMethodActionHandlers() so inter-controller communication works through the messenger in core. Store the RemoteFeatureFlagController:stateChange subscription handle and clean it up in disconnect() to prevent leaks.
… and account switch - Remove feature-flag unsubscribe from disconnect() so geo-blocking and HIP-3 flag changes keep propagating after reconnect cycles - Add deposit request lifecycle tracking for the deposit+order flow so requests transition from pending to completed/failed/cancelled - Clear cached user data when switching to a non-EVM account group to prevent stale positions/orders from the previous EVM account
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
These changes are isolated to the Perps feature domain and don't affect core Engine initialization or other controllers. The test file adds comprehensive coverage for the new functionality. Tag selection rationale:
Performance Test Selection: |
|
| // Migrate old persisted data without accountAddress | ||
| this.#migrateRequestsIfNeeded(); | ||
|
|
||
| this.messenger.registerMethodActionHandlers( |
There was a problem hiding this comment.
Why do we need this?
There was a problem hiding this comment.
This exposes PerpsController methods (placeOrder, cancelOrder, getPositions, etc.) via the messenger pattern so other controllers/services can call them through action handlers instead of needing a direct reference to the controller instance. It's the standard BaseController approach for inter-controller communication - keeps things decoupled.
There was a problem hiding this comment.
basically we didnt need it outside of core, but when putting in core and want to share wiht other controllers we need it.



Description
Defensive hardening for edge cases in
PerpsControllersurfaced by static analysis on Core PR #7941. None of these bugs are currently triggerable in production — the app works correctly today — but all represent latent issues that could bite under future changes or unusual network conditions.What changed
1.
toggleTestnet()— false success on silent init failureperformInitialization()catches errors internally and setsInitializationState.Failedinstead of throwing.toggleTestnet()was not checking for this, so it could return{ success: true }even when the network switch failed. This patch:InitializationState.Failedcheck afterawait this.init()isTestnetto its previous value on failure2.
depositWithConfirmation()— never-resolving promise whenplaceOrder=trueThe
placeOrderpath creatednew Promise(() => {})— a promise that can never be GC'd and would hang any consumer who awaits it. Replaced withPromise.resolve(transactionMeta.id)for proper fire-and-forget semantics.3.
depositWithConfirmation()— failed deposits remain permanently pendingdepositWithConfirmationadds a pending entry tostate.depositRequestsbefore validatingnetworkClientId. If the validation throws, the deposit request staysstatus: 'pending'forever. This patch marks the deposit request asfailedin the outer catch when a pre-submission error occurs.4. Feature flag listener lost after disconnect
disconnect()unsubscribedRemoteFeatureFlagController:stateChangebut no reconnect path re-subscribed. After disconnect → reconnect, geo-blocking and HIP-3 flag changes stopped propagating. The feature-flag subscription is a controller-lifetime concern (not session-lifetime), so we removed the unsubscribe fromdisconnect()entirely — the subscription now lives for the full controller lifecycle.5.
depositWithConfirmation()— deposit+order request stays pending foreverWhen
placeOrder=true, theif (!placeOrder)guard skips the.then()/.catch()lifecycle block that transitions the deposit request tocompleted/failed. No other handler exists for this path. Added anelse ifbranch that attaches lifecycle tracking toaddResult.result(the real transaction promise) for the deposit+order flow.6. Non-EVM account switch leaves stale cache
The account-change handler only cleared cached user data when
currentAddressis truthy. Switching to an account group with no EVM account (e.g., Bitcoin-only) skipped cache clearing, leaving stale positions/orders visible. Restructured the condition so cache is always cleared when the account group changes, with preload guarded separately behindif (currentAddress).Changelog
CHANGELOG entry: null
Related issues
Fixes: bugbot findings from Core PR #7941
Manual testing steps
These are defensive fixes for edge cases not reachable through normal UI flows. Verification is via unit tests.
Screenshots/Recordings
N/A — no UI changes, logic-only hardening.
Pre-merge author checklist
Pre-merge reviewer checklist