Commit b166faf
chore(runway): cherry-pick feat(perps): force unified account (#29673)
- feat(perps): force unified account (#29492)
## **Description**
HyperLiquid is deprecating DEX Abstraction mode (~May 9). This PR forces
every Perps user onto **Unified Account** mode on app open and fixes the
withdraw + balance-display flows that were broken in the target state.
### 1. Forced migration to Unified Account
Migration paths by current abstraction mode:
- `default` / `disabled` → silently migrated via `agentSetAbstraction({
abstraction: 'u' })` — no signing prompt
- `dexAbstraction` → one-time EIP-712 prompt via `userSetAbstraction({
user, abstraction: 'unifiedAccount' })` — agent-key path is blocked by
HL for this transition
- `unifiedAccount` → no-op, cached immediately
Key details:
- Replaces deprecated `agentEnableDexAbstraction` / `userDexAbstraction`
with `agentSetAbstraction` / `userSetAbstraction` / `userAbstraction`
- Runs on perps section open (`#ensureReady()`) so users are set up
before trading
- `TradingReadinessCache` prevents repeated prompts (critical for
hardware/QR wallets); `KEYRING_LOCKED` skips the cache so it retries on
unlock
- In-flight deduplication blocks concurrent signing attempts across
provider instances
- Segment analytics: `Perp Account Setup` event tracks mode distribution
+ outcome (`already_enabled` / `migration_required` / `success` /
`failed`)
### 2. Withdraw + balance display fix (folded in from #29537)
In Unified mode, USDC collateral lives in the spot clearinghouse, so
`clearinghouseState.withdrawable` is $0 — pre-fix the withdraw screen
showed $0 max with the button disabled, and the confirm-flow alert
blocked submission.
- `accountUtils.addSpotBalanceToAccountState` folds free spot USDC into
`availableToTradeBalance` for Unified / Portfolio Margin;
`dexAbstraction` / Standard keep spot separate (fold gated on resolved
abstraction mode)
- `HyperLiquidSubscriptionService.invalidateUserAbstractionCache(addr)`
evicts stale pre-migration mode and re-aggregates immediately. Called by
`HyperLiquidProvider` after both successful migration paths so the
WS-driven aggregator doesn't serve a $0 balance for ~60s after migration
completes.
- Withdraw screen, withdraw validation, confirm-flow
insufficient-balance alert, and percentage buttons all read
`availableToTradeBalance ?? availableBalance` — fallback keeps Standard
/ legacy callers correct.
## **Changelog**
CHANGELOG entry: Fixed Hyperliquid withdraw showing $0 and being blocked
for users on Unified Account mode.
## **Related issues**
Fixes: TAT-3112 (Unified Account migration), withdrawal break tracked in
[TAT-3047](https://consensyssoftware.atlassian.net/browse/TAT-3047)
## **Manual testing steps**
```gherkin
Feature: Unified Account migration + withdraw
Scenario: First-time migration (default/disabled mode)
Given the user has never used Perps
When they open the Perps section
Then migration runs silently (no prompt)
And HIP-3 markets are visible
Scenario: dexAbstraction → unifiedAccount migration
Given the user has DEX Abstraction enabled
When they open the Perps section
Then a one-time EIP-712 signing prompt appears
When they sign
Then HIP-3 markets are visible and trades succeed
And reopening Perps does not prompt again
Scenario: Unified Account user withdraws spot-funded balance
Given the user is in Unified Mode with $0 perps withdrawable and >$0 spot USDC
When they open the Withdraw screen
Then "Available Perps balance" shows the unified value (perps + free spot USDC)
And Max enables and submission proceeds via withdraw3
And spot USDC drops by amount + fee
```
### Live validation evidence
Validated on dev1 mainnet (`0x8dc6…9003`) in the exact bug-class state:
- HL mode: `unifiedAccount` / perps `withdrawable`: $0 / spot USDC free:
$26.41
- App: `availableBalance` = $0 / `availableToTradeBalance` = $26.41
- Withdraw screen renders **"Available Perps balance: $26.41"** + Max
enabled (pre-fix would show $0 / disabled)
## **Screenshots/Recordings**
### **Before**
<!-- $0 max + disabled Max button on dev1 mainnet pre-fix -->
### **After**
<!-- $26.41 max + Max enabled + successful withdraw on dev1 mainnet -->
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
#### Performance checks (if applicable)
- [ ] I've tested on Android
- [ ] I've tested with a power user scenario
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
## **Pre-merge reviewer checklist**
- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
[TAT-3047]:
https://consensyssoftware.atlassian.net/browse/TAT-3047?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **High Risk**
> High risk because it changes Perps account-mode migration/signing flow
(including hardware-wallet behavior) and alters withdraw/payment balance
calculations that gate user funds and transaction validation.
>
> **Overview**
> Forces Perps users onto HyperLiquid **Unified Account** by replacing
deprecated DEX-abstraction checks/calls with `userAbstraction` +
`agentSetAbstraction`/`userSetAbstraction`, adding global
in-flight/cached gating, retry semantics, and new `Perp Account Setup`
analytics.
>
> Updates withdraw, confirmation, and pay-with flows to prefer
`availableToTradeBalance ?? availableBalance`, and changes spot→perps
folding to be **mode-gated** (fail-closed when abstraction mode is
unknown) so Unified/Portfolio Margin users see spendable USDC while
Standard/dexAbstraction users don’t over-report withdrawable funds.
>
> Renames cache-clearing APIs from DEX abstraction to Unified Account,
adds hardware-wallet detection to defer user-sign prompts on browse, and
expands tests/docs to cover unified-mode folding, migration paths, and
race conditions in spot/account aggregation.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e5495f9. 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: geositta <matthew.denton@consensys.net>
Co-authored-by: Nick Gambino <nicholas.gambino@consensys.net>
Co-authored-by: Arthur Breton <arthur.breton@consensys.net>
Co-authored-by: abretonc7s
<107169956+abretonc7s@users.noreply.github.com>
[cc44460](cc44460)
[TAT-3047]:
https://consensyssoftware.atlassian.net/browse/TAT-3047?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
Co-authored-by: Alejandro Garcia Anglada <aganglada@gmail.com>1 parent 2f18776 commit b166faf
31 files changed
Lines changed: 2398 additions & 604 deletions
File tree
- app
- components
- UI/Perps
- Views/PerpsWithdrawView
- hooks
- services
- utils
- Views/confirmations
- components/perps-confirmations/perps-withdraw-balance
- hooks
- alerts
- transactions
- controllers/perps
- constants
- providers
- services
- types
- utils
- core/Analytics
- docs/perps
- hyperliquid
Lines changed: 38 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
277 | 277 | | |
278 | 278 | | |
279 | 279 | | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
280 | 292 | | |
281 | 293 | | |
282 | 294 | | |
| |||
296 | 308 | | |
297 | 309 | | |
298 | 310 | | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
299 | 337 | | |
300 | 338 | | |
301 | 339 | | |
| |||
Lines changed: 10 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
111 | | - | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
112 | 115 | | |
113 | | - | |
114 | | - | |
115 | | - | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
116 | 121 | | |
117 | 122 | | |
118 | 123 | | |
| |||
154 | 159 | | |
155 | 160 | | |
156 | 161 | | |
157 | | - | |
| 162 | + | |
158 | 163 | | |
159 | 164 | | |
160 | 165 | | |
| |||
Lines changed: 22 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
207 | 207 | | |
208 | 208 | | |
209 | 209 | | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
210 | 232 | | |
211 | 233 | | |
212 | 234 | | |
| |||
Lines changed: 9 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
83 | 83 | | |
84 | 84 | | |
85 | 85 | | |
86 | | - | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
87 | 94 | | |
88 | 95 | | |
89 | 96 | | |
| |||
135 | 142 | | |
136 | 143 | | |
137 | 144 | | |
| 145 | + | |
138 | 146 | | |
139 | 147 | | |
140 | 148 | | |
| |||
Lines changed: 20 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
294 | 294 | | |
295 | 295 | | |
296 | 296 | | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
297 | 317 | | |
298 | 318 | | |
299 | 319 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
37 | | - | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
38 | 41 | | |
39 | 42 | | |
40 | 43 | | |
41 | | - | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
42 | 47 | | |
43 | 48 | | |
44 | 49 | | |
| |||
Lines changed: 17 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
84 | 101 | | |
85 | 102 | | |
86 | 103 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
31 | | - | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
32 | 34 | | |
33 | | - | |
| 35 | + | |
| 36 | + | |
34 | 37 | | |
35 | 38 | | |
36 | 39 | | |
| |||
Lines changed: 10 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| |||
919 | 919 | | |
920 | 920 | | |
921 | 921 | | |
922 | | - | |
| 922 | + | |
923 | 923 | | |
924 | 924 | | |
925 | 925 | | |
926 | 926 | | |
927 | | - | |
928 | | - | |
| 927 | + | |
| 928 | + | |
929 | 929 | | |
930 | 930 | | |
931 | 931 | | |
932 | 932 | | |
933 | 933 | | |
934 | | - | |
| 934 | + | |
935 | 935 | | |
936 | | - | |
| 936 | + | |
937 | 937 | | |
938 | | - | |
| 938 | + | |
939 | 939 | | |
940 | 940 | | |
941 | 941 | | |
942 | | - | |
| 942 | + | |
943 | 943 | | |
944 | 944 | | |
945 | 945 | | |
| |||
950 | 950 | | |
951 | 951 | | |
952 | 952 | | |
953 | | - | |
| 953 | + | |
954 | 954 | | |
955 | 955 | | |
956 | 956 | | |
957 | | - | |
| 957 | + | |
958 | 958 | | |
959 | 959 | | |
960 | 960 | | |
| |||
Lines changed: 5 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1441 | 1441 | | |
1442 | 1442 | | |
1443 | 1443 | | |
1444 | | - | |
| 1444 | + | |
1445 | 1445 | | |
1446 | | - | |
| 1446 | + | |
1447 | 1447 | | |
1448 | | - | |
| 1448 | + | |
1449 | 1449 | | |
1450 | 1450 | | |
1451 | 1451 | | |
1452 | | - | |
1453 | | - | |
| 1452 | + | |
| 1453 | + | |
1454 | 1454 | | |
1455 | 1455 | | |
1456 | 1456 | | |
| |||
0 commit comments