fix(perps): recover HIP-3 DEX discovery on transient failure + guard deposit Arbitrum check cp-7.68.0#27127
Conversation
…d deposit flow - HyperLiquidProvider: on transient perpDexs() fetch failure, return [null] without caching so the next #ensureReady() call retries DEX discovery instead of reusing a stale degraded result. Added #dexDiscoveryComplete flag so #ensureReady resets its promise and re-runs #buildAssetMapping until discovery succeeds — trading on main DEX continues uninterrupted in the meantime. Flag is cleared on disconnect for clean reconnection. - usePerpsBalanceTokenFilter: call ensureArbitrumNetworkExists() before depositWithConfirmation() in handlePerpsDepositPress, matching the existing guard in usePerpsHomeActions. Fixes "Invalid chain ID 0xa4b1" for users without Arbitrum configured who tap "Add funds" from the pay-with modal.
|
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. |
Align test mocks with provider behavior: buildAssetMapping uses metaAndAssetCtxs (not meta) to populate cache. Add metaAndAssetCtxs to placeOrder retry, closePosition TP/SL, and builder fee tests. Expect metaAndAssetCtxs in getMarkets test. Update invalid-meta tests to expect asset-not-found when metaAndAssetCtxs returns no valid universe.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
| this.#cachedMetaByDex.clear(); | ||
| this.#cachedSpotMeta = null; | ||
| this.#perpDexsCache = { data: null, timestamp: 0 }; | ||
| this.#dexDiscoveryComplete = false; |
There was a problem hiding this comment.
Race condition: disconnect flag overwritten by completing IIFE
Low Severity
#dexDiscoveryComplete = false is set on line 7339 before awaiting pendingReady on lines 7363–7366. If the in-flight #ensureReadyPromise IIFE completes during that await, its #buildAssetMapping() sets #dexDiscoveryComplete = true, overwriting the reset. After disconnect, the flag stays true, so the next reconnect skips #buildAssetMapping() entirely — the cleared #cachedMetaByDex is never repopulated and stale #symbolToAssetId entries persist. This is inconsistent with #clientsInitialized, which is correctly reset after the awaits at line 7381.
Additional Locations (1)
…uidProvider tests - Mock usePerpsNetworkManagement to prevent test hang - Fix allowlist test by matching useSelector call order - Await async handlePerpsDepositPress in Add funds test - Format HyperLiquidProvider.test.ts
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
Tag selection rationale:
The changes are medium risk because:
Performance Test Selection: |
The committed fixture schema is out of date. To update, comment: |
|





Description
Addresses two perps issues identified via Sentry analysis (branch: fix/perps/sentry-analysis).
Issue 1: HIP-3 DEX discovery not retried after transient failure
Root cause: When
perpDexs()fails transiently (WS drop during init),#fetchValidatedDexsInternalwas caching[null](main DEX only). On the next#ensureReady()call, the cache hit returned the stale degraded result — HIP-3 markets stayed unavailable for the entire session.Fix:
[null]without caching so the next call retries#dexDiscoveryCompleteflag: whenfalse,#ensureReady()resets its promise after each init so every subsequent trading call (closePosition,placeOrder, etc.) retries DEX discovery#dexDiscoveryComplete = true— no more retriesdisconnect()for clean reconnectionNote: the upstream fix preventing the permanent provider brick (commit
29d300597d, already inmain) should be cherry-picked to 7.67.4. This PR adds the retry logic on top.Issue 2: "Invalid chain ID 0xa4b1" on deposit from pay-with modal
Root cause:
usePerpsBalanceTokenFilter.handlePerpsDepositPresscalleddepositWithConfirmation()directly without first callingensureArbitrumNetworkExists(). Users without Arbitrum in their network list hitNetworkController.findNetworkClientIdByChainIdthrowing on chain0xa4b1(Arbitrum One — HyperLiquid's bridge chain). The guard existed inusePerpsHomeActionsbut was missing from this second entry point.Fix: Call
ensureArbitrumNetworkExists()beforedepositWithConfirmation()inhandlePerpsDepositPress, matching the existing pattern inusePerpsHomeActions.This error predates 7.67 — it became visible due to improved Sentry tagging in Feb 2026 (commits
30f8e72cc4/61a2be3e9d). Not a regression, low volume (~170 users).Changelog
CHANGELOG entry: null
Related issues
Fixes: (Sentry: METAMASK-MOBILE-5JCV, METAMASK-MOBILE-5G4T, METAMASK-MOBILE-5JGC, METAMASK-MOBILE-5H0A)
Manual testing steps
Screenshots/Recordings
Before
N/A — logic fix, no UI change
After
N/A — logic fix, no UI change
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Medium Risk
Touches perps provider initialization/caching and the deposit entrypoint, which can affect market availability and deposit/trading flows if the retry/caching logic misbehaves. Changes are contained and covered by updated unit tests, but they run in core perps paths.
Overview
Improves perps reliability by making HIP-3 DEX discovery recoverable after transient
perpDexs()failures: degraded fallback results are no longer cached, a new#dexDiscoveryCompleteflag tracks whether discovery succeeded with real data, and#ensureReady()now rebuilds/retries the asset/DEX mapping on subsequent calls until discovery completes (reset ondisconnect()).Fixes a deposit crash from the token selector by ensuring Arbitrum is present/enabled via
usePerpsNetworkManagement.ensureArbitrumNetworkExists()before navigating to the perps deposit flow and callingdepositWithConfirmation(). Tests were updated to mock the new network guard and to stubmetaAndAssetCtxsinHyperLiquidProvidertest clients to match the new initialization behavior.Written by Cursor Bugbot for commit 625b999. This will update automatically on new commits. Configure here.