Commit bab8514
fix(perps): when opening perps quickly after wallet open, the app display $0 for 24h volume and OI (#34844)
## **Description**
Opening Perps immediately after wallet unlock could show **$0.00** for
24h volume and open interest while price, funding, and the order book
were already live. `usePerpsMarketStats` subscribed before the Perps
client was initialized and never retried, then formatted missing values
as `$0.00`.
This waits for `isInitialized` before subscribing (same pattern as
`usePerpsPrices`) and shows `PERPS_CONSTANTS.FallbackPriceDisplay` until
volume and open interest arrive. Confirmed zeros still format as `$0`.
## **Changelog**
CHANGELOG entry: Fixed 24h volume and open interest showing $0.00 when
opening Perps right after unlock
## **Related issues**
Fixes:
[TAT-3765](https://consensyssoftware.atlassian.net/browse/TAT-3765)
## **Manual testing steps**
```gherkin
Feature: Perps market stats after a fast open
Scenario: user opens a market immediately after unlocking
Given the wallet is locked on the fixture account
And Perps is enabled
When the user unlocks and opens BTC market details immediately
Then 24h volume is a real market figure, not $0.00
And open interest is a real market figure, not $0.00
```
## **Screenshots/Recordings**
Fast Perps open: 24h volume and open interest load as real figures
instead of $0.00.
<table>
<tr><td colspan="2"><strong>Fast Perps open no longer shows fake $0.00
for 24h volume and open interest</strong></td></tr>
<tr>
<td align="center" valign="top" width="50%"><em>Before</em><br/><img
src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/main/fixes/34844/before-evidence-ac1-volume.png?sha=3ba9856c812db52a"
alt="before" width="320" /></td>
<td align="center" valign="top" width="50%"><em>After</em><br/><img
src="https://raw.githubusercontent.com/abretonc7s/mm-mobile-farm-artifacts/main/fixes/34844/after-ac1-volume.png?sha=62fb4f8ca25281cd"
alt="after" width="320" /></td>
</tr>
</table>
## **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)).
Not required for external contributors.
#### Performance checks (if applicable)
- [x] I've tested on Android
- Ideally on a mid-range device; emulator is acceptable
- [x] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [x] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example
For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).
## **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.
## **Validation Recipe**
<details>
<summary>recipe.json</summary>
```json
{
"$schema": "https://farmslot.io/schemas/recipe-v1.schema.json",
"title": "Perps 24h volume and open interest are not fake zeros after a fast open",
"description": "Unlock, open BTC market detail immediately, and prove 24h volume and open interest render real market stats instead of $0.00. Requires an unlocked fixture wallet with Perps enabled. Lite market details is used so both figures are fully on screen; they come from the same usePerpsMarketStats hook as the Pro stats bar.",
"workflow": {
"entry": "setup-status",
"nodes": {
"setup-status": {
"action": "app.status",
"intent": "Confirm the mobile bridge is reachable before opening Perps",
"next": "setup-cdp"
},
"setup-cdp": {
"action": "cdp.target",
"required": true,
"timeout_ms": 15000,
"intent": "Confirm the React Native debug bridge is reachable",
"next": "setup-restart"
},
"setup-restart": {
"action": "app.lifecycle",
"command": "restart",
"settle_ms": 3000,
"runtime_ready_timeout_ms": 60000,
"intent": "Restart the app so Perps opens from a fresh wallet-launch state",
"next": "setup-unlock"
},
"setup-unlock": {
"action": "metamask.wallet.ensure_unlocked",
"intent": "Unlock the wallet so Perps can be opened immediately after launch",
"target_timeout_ms": 45000,
"unlock_timeout_ms": 45000,
"next": "setup-navigate-market"
},
"setup-navigate-market": {
"action": "ui.navigate",
"page": "perps-market",
"market": "BTC",
"intent": "Open the BTC Perps market detail screen",
"next": "setup-wait-header"
},
"setup-wait-header": {
"action": "ui.wait_for",
"test_id": "perps-market-header",
"expected": "present",
"timeout_ms": 20000,
"intent": "Confirm BTC market details finished opening after the fast launch",
"next": "setup-wait-scroll"
},
"setup-wait-scroll": {
"action": "ui.wait_for",
"test_id": "perps-market-details-scroll-view",
"expected": "present",
"timeout_ms": 15000,
"intent": "Confirm the Lite market details scroll surface is ready",
"next": "ac1-scroll-stats"
},
"ac1-scroll-stats": {
"action": "ui.scroll",
"test_id": "perps-market-details-scroll-view",
"offset": 1050,
"settle": true,
"timeout_ms": 15000,
"intent": "Confirm 24h volume and open interest can be read on the market stats card",
"next": "ac1-wait-volume"
},
"ac1-wait-volume": {
"action": "ui.wait_for",
"text": "24h volume",
"expected": "present",
"timeout_ms": 15000,
"intent": "Confirm the 24h volume label is on the BTC market stats card",
"next": "ac1-screenshot-volume"
},
"ac1-screenshot-volume": {
"action": "ui.screenshot",
"label": "AC1: 24h volume on market stats card",
"intent": "Show that 24h volume is a real market figure rather than $0.00",
"next": "ac2-wait-oi-label"
},
"ac2-wait-oi-label": {
"action": "ui.wait_for",
"text": "Open interest",
"expected": "present",
"timeout_ms": 10000,
"intent": "Confirm the open interest label is on the BTC market stats card",
"next": "ac2-wait-oi-icon"
},
"ac2-wait-oi-icon": {
"action": "ui.wait_for",
"test_id": "perps-market-details-open-interest-info-icon",
"expected": "present",
"timeout_ms": 10000,
"intent": "Confirm the open interest row is mounted on the stats card",
"next": "ac2-screenshot-oi"
},
"ac2-screenshot-oi": {
"action": "ui.screenshot",
"label": "AC2: open interest on market stats card",
"intent": "Show that open interest is a real market figure rather than $0.00",
"next": "done"
},
"done": {
"action": "end",
"status": "pass"
}
}
}
}
```
</details>
## **Recipe Workflow**
<details>
<summary>workflow.mmd</summary>
```mermaid
flowchart TD
setup-status --> setup-cdp
setup-cdp --> setup-restart
setup-restart --> setup-unlock
setup-unlock --> setup-navigate-market
setup-navigate-market --> setup-wait-header
setup-wait-header --> setup-wait-scroll
setup-wait-scroll --> ac1-scroll-stats
ac1-scroll-stats --> ac1-wait-volume
ac1-wait-volume --> ac1-screenshot-volume
ac1-screenshot-volume --> ac2-wait-oi-label
ac2-wait-oi-label --> ac2-wait-oi-icon
ac2-wait-oi-icon --> ac2-screenshot-oi
ac2-screenshot-oi --> done
```
</details>
[TAT-3765]:
https://consensyssoftware.atlassian.net/browse/TAT-3765?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Localized Perps UI hook behavior and display formatting with unit
tests; no auth, payments, or shared infrastructure changes.
>
> **Overview**
> Fixes **24h volume and open interest** showing fake **$0.00** when
Perps is opened right after wallet unlock.
>
> `usePerpsMarketStats` now waits on **`isInitialized`** from
`usePerpsConnection` before calling `subscribeToPrices`, matching
`usePerpsPrices`, so an early no-op subscribe is retried once the client
is ready. Until volume and open interest arrive, the UI uses
**`PERPS_CONSTANTS.FallbackPriceDisplay`** instead of formatting missing
values as `$0.00`; confirmed **zero** values still render as **`$0`**.
>
> Tests mock `usePerpsConnection` and cover init gating, post-init
subscribe, fallback display, and real zeros.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
bbf72c4. 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: Cursor <cursoragent@cursor.com>1 parent c0a4be3 commit bab8514
2 files changed
Lines changed: 147 additions & 17 deletions
Lines changed: 127 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
14 | 18 | | |
15 | 19 | | |
16 | 20 | | |
17 | 21 | | |
18 | 22 | | |
| 23 | + | |
19 | 24 | | |
20 | 25 | | |
| 26 | + | |
21 | 27 | | |
22 | 28 | | |
23 | 29 | | |
24 | 30 | | |
25 | 31 | | |
26 | 32 | | |
27 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
28 | 44 | | |
29 | 45 | | |
30 | 46 | | |
| |||
138 | 154 | | |
139 | 155 | | |
140 | 156 | | |
141 | | - | |
142 | | - | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
143 | 161 | | |
144 | 162 | | |
145 | 163 | | |
| |||
225 | 243 | | |
226 | 244 | | |
227 | 245 | | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 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 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
228 | 352 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
| |||
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| 17 | + | |
16 | 18 | | |
17 | 19 | | |
18 | 20 | | |
| |||
41 | 43 | | |
42 | 44 | | |
43 | 45 | | |
| 46 | + | |
44 | 47 | | |
45 | 48 | | |
46 | 49 | | |
| |||
57 | 60 | | |
58 | 61 | | |
59 | 62 | | |
60 | | - | |
61 | | - | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
62 | 66 | | |
63 | | - | |
| 67 | + | |
64 | 68 | | |
65 | 69 | | |
66 | 70 | | |
| |||
114 | 118 | | |
115 | 119 | | |
116 | 120 | | |
117 | | - | |
| 121 | + | |
118 | 122 | | |
119 | 123 | | |
120 | 124 | | |
| |||
135 | 139 | | |
136 | 140 | | |
137 | 141 | | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | | - | |
143 | | - | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
148 | 154 | | |
149 | 155 | | |
150 | 156 | | |
| |||
0 commit comments