Commit 43130d6
authored
fix(perps): BRENTOIL shows up in the 'explore crypto' section (#27699)
## **Description**
BRENTOIL (Brent Crude Oil) and 14 other recently added HIP-3 assets
appeared in the "Explore Crypto" section because they were missing from
the `HIP3_ASSET_MARKET_TYPES` mapping in `hyperLiquidConfig.ts`. Without
a `marketType`, the crypto filter (`!m.marketType`) incorrectly captured
them.
**Root cause:**
`app/controllers/perps/constants/hyperLiquidConfig.ts:305` — 15 HIP-3
assets added to HyperLiquid's xyz DEX were not mapped in the app's asset
classification config.
**Fix:** (1) Added all 15 missing assets to `HIP3_ASSET_MARKET_TYPES`
with correct categories. (2) Added `&& !m.isHip3` guard to the crypto
filter in `usePerpsHomeData` as defense-in-depth against future unmapped
HIP-3 assets.
## **Changelog**
CHANGELOG entry: Fixed miscategorization of BRENTOIL and other
non-crypto instruments appearing in the "Explore Crypto" section on
Perps Home
## **Related issues**
Fixes:
[TAT-2672](https://consensyssoftware.atlassian.net/browse/TAT-2672)
## **Manual testing steps**
```gherkin
Feature: Perps Home market categorization
Scenario: BRENTOIL appears in Commodities, not Explore Crypto
Given the user is on the Perps Home screen
When the market data loads
Then BRENTOIL should appear in the "Commodities" section
And BRENTOIL should NOT appear in the "Explore Crypto" section
And BTC, ETH, SOL remain in the "Explore Crypto" section
```
## **Screenshots/Recordings**
### **Before**
https://github.com/user-attachments/assets/60b1f75c-823e-4788-8173-dd58629a323c
### **After**
https://github.com/user-attachments/assets/a2235b45-8a40-4f23-b0ca-aad8d12506aa
## **Validation Recipe**
<details>
<summary>Automated validation recipe (validate-recipe.sh)</summary>
```json
{
"pr": "27699",
"title": "BRENTOIL excluded from Explore Crypto section",
"jira": "TAT-2672",
"acceptance_criteria": [
"BRENTOIL does not appear in the Explore Crypto section",
"Other non-crypto instruments are excluded from Explore Crypto",
"Filter logic enforced at data level, not manual exclusion",
"BRENTOIL appears in Commodities section",
"No crypto markets removed from Explore Crypto"
],
"validate": {
"static": ["yarn lint:tsc"],
"runtime": {
"pre_conditions": ["CDP connected", "Wallet unlocked on Wallet route"],
"steps": [
{
"id": "nav_perps",
"description": "Navigate to perps home",
"action": "navigate",
"target": "Perps"
},
{
"id": "wait_load",
"description": "Wait for market data to load",
"action": "wait",
"ms": 3000
},
{
"id": "check_brentoil_not_in_crypto",
"description": "BRENTOIL must not be in crypto markets (markets without marketType)",
"action": "eval_async",
"expression": "Engine.context.PerpsController.getMarketDataWithPrices().then(function(markets) { var cryptoMarkets = markets.filter(function(m) { return !m.marketType; }); var hasBrent = cryptoMarkets.some(function(m) { return (m.symbol || '').indexOf('BRENTOIL') >= 0; }); return JSON.stringify({hasBrentInCrypto: hasBrent, cryptoCount: cryptoMarkets.length}); })",
"assert": { "operator": "eq", "field": "hasBrentInCrypto", "value": false }
},
{
"id": "check_brentoil_in_commodities",
"description": "BRENTOIL must be in commodities section",
"action": "eval_async",
"expression": "Engine.context.PerpsController.getMarketDataWithPrices().then(function(markets) { var commodities = markets.filter(function(m) { return m.marketType === 'commodity'; }); var hasBrent = commodities.some(function(m) { return (m.symbol || '').indexOf('BRENTOIL') >= 0; }); return JSON.stringify({hasBrentInCommodities: hasBrent, commodityCount: commodities.length}); })",
"assert": { "operator": "eq", "field": "hasBrentInCommodities", "value": true }
},
{
"id": "check_no_hip3_in_crypto",
"description": "No HIP-3 markets should appear in crypto section",
"action": "eval_async",
"expression": "Engine.context.PerpsController.getMarketDataWithPrices().then(function(markets) { var hip3InCrypto = markets.filter(function(m) { return !m.marketType && m.isHip3; }); return JSON.stringify({hip3InCryptoCount: hip3InCrypto.length, symbols: hip3InCrypto.map(function(m) { return m.symbol; })}); })",
"assert": { "operator": "eq", "field": "hip3InCryptoCount", "value": 0 }
},
{
"id": "check_crypto_markets_exist",
"description": "Crypto markets still exist in Explore Crypto",
"action": "eval_async",
"expression": "Engine.context.PerpsController.getMarketDataWithPrices().then(function(markets) { var crypto = markets.filter(function(m) { return !m.marketType && !m.isHip3; }); var hasBTC = crypto.some(function(m) { return m.symbol === 'BTC'; }); var hasETH = crypto.some(function(m) { return m.symbol === 'ETH'; }); return JSON.stringify({cryptoCount: crypto.length, hasBTC: hasBTC, hasETH: hasETH}); })",
"assert": { "operator": "eq", "field": "hasBTC", "value": true }
},
{
"id": "check_all_hip3_categorized",
"description": "All HIP-3 markets have a marketType assigned",
"action": "eval_async",
"expression": "Engine.context.PerpsController.getMarketDataWithPrices().then(function(markets) { var uncategorized = markets.filter(function(m) { return m.isHip3 && !m.marketType; }); return JSON.stringify({uncategorizedCount: uncategorized.length, symbols: uncategorized.map(function(m) { return m.symbol; })}); })",
"assert": { "operator": "eq", "field": "uncategorizedCount", "value": 0 }
},
{
"id": "check_no_errors",
"description": "No errors in Metro logs",
"action": "log_watch",
"window_seconds": 10,
"must_not_appear": ["TypeError", "undefined is not an object"]
}
]
}
}
}
```
</details>
## **Pre-merge author checklist**
- [x] I've followed MetaMask Contributor Docs and Coding Standards
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [ ] I've documented my code using JSDoc format if applicable
- [x] I've applied the right labels on the PR
## **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.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Low Risk**
> Low risk UI/data-filtering change that only affects how perps markets
are categorized and displayed; behavior is covered by new unit tests
guarding HIP-3 filtering in both trending and search results.
>
> **Overview**
> Prevents HIP-3 xyz DEX instruments (e.g., `xyz:BRENTOIL`) from being
treated as crypto on Perps Home by **excluding HIP-3 markets** from the
crypto `perpsMarkets` list (including search results).
>
> Expands `HIP3_ASSET_MARKET_TYPES` to classify newly added xyz assets
across *equity/commodity/forex*, and adds unit tests to ensure HIP-3
markets don’t appear under **Explore Crypto** while correctly showing
under their respective sections.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f35150d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->1 parent 5a86bf1 commit 43130d6
3 files changed
Lines changed: 114 additions & 2 deletions
File tree
- app
- components/UI/Perps/hooks
- controllers/perps/constants
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
486 | 486 | | |
487 | 487 | | |
488 | 488 | | |
| 489 | + | |
| 490 | + | |
| 491 | + | |
| 492 | + | |
| 493 | + | |
| 494 | + | |
| 495 | + | |
| 496 | + | |
| 497 | + | |
| 498 | + | |
| 499 | + | |
| 500 | + | |
| 501 | + | |
| 502 | + | |
| 503 | + | |
| 504 | + | |
| 505 | + | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
| 522 | + | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
489 | 585 | | |
490 | 586 | | |
491 | 587 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
182 | 182 | | |
183 | 183 | | |
184 | 184 | | |
185 | | - | |
| 185 | + | |
186 | 186 | | |
187 | 187 | | |
188 | 188 | | |
| |||
321 | 321 | | |
322 | 322 | | |
323 | 323 | | |
324 | | - | |
| 324 | + | |
325 | 325 | | |
326 | 326 | | |
327 | 327 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
335 | 335 | | |
336 | 336 | | |
337 | 337 | | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
338 | 351 | | |
339 | 352 | | |
340 | 353 | | |
| |||
345 | 358 | | |
346 | 359 | | |
347 | 360 | | |
| 361 | + | |
| 362 | + | |
348 | 363 | | |
349 | 364 | | |
350 | 365 | | |
351 | 366 | | |
| 367 | + | |
352 | 368 | | |
353 | 369 | | |
354 | 370 | | |
| |||
0 commit comments