Commit 03f318a
fix: cherry-pick 429 rate limiting fix with coin naming convention (#25443)
## **Description**
Cherry-pick of commit 425beae (Nick's 429 rate limiting fix) to
release/7.62.2 branch.
This hotfix addresses HyperLiquid WebSocket rate limiting issues (429
errors) that occur during rapid market switching or TP/SL updates. The
fix introduces cache-first patterns to reduce API weight and avoid
hitting rate limits.
**Key changes:**
- Add optional `position` parameter to `updatePositionTPSL` to skip REST
API fetch when WebSocket data is available
- Implement `getOrFetchPrice` helper for WebSocket-first price retrieval
(0 weight vs 20 weight)
- Add atomic cache getter `getOrdersCacheIfInitialized()` to prevent
race conditions
- Add `getOrFetchFills` for cache-first fills retrieval
- Move `positionOpenedTimestamp` calculation into
`useHasExistingPosition` hook
- Add `currentPositionRef` sync in PerpsMarketDetailsView to prevent
stale closure issues
**Conflict resolution notes:**
The main branch uses `symbol` naming convention while release/7.62.2
uses `coin`. All conflicts were resolved by keeping the `coin` naming
convention while adopting the cache-first optimization patterns.
## **Changelog**
CHANGELOG entry: Fixed rate limiting issues (429 errors) when rapidly
switching markets or updating TP/SL orders
## **Related issues**
Fixes: Rate limiting issues on HyperLiquid API during rapid market
navigation
## **Manual testing steps**
```gherkin
Feature: Rate limiting prevention for Perps
Scenario: User rapidly switches between markets
Given user has the Perps feature enabled
And user is viewing a market details page
When user rapidly navigates between different markets (BTC -> ETH -> SOL -> BTC)
Then no 429 rate limit errors should appear
And market data should load correctly for each market
Scenario: User updates TP/SL via stop loss prompt banner
Given user has an open position without stop loss
And the stop loss prompt banner is visible
When user taps "Set Stop Loss" on the banner
Then the stop loss should be set successfully
And no rate limit errors should occur
Scenario: User edits existing TP/SL on a position
Given user has an open position with TP/SL set
When user navigates to modify TP/SL
And user updates the stop loss price
Then the update should succeed without 429 errors
```
## **Screenshots/Recordings**
### **Before**
N/A - Bug fix for rate limiting, no visual changes
### **After**
N/A - Bug fix for rate limiting, no visual changes
## **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.
## **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]
> **Medium Risk**
> Touches perps trading/provider logic (`updatePositionTPSL`,
order/price/fill retrieval) and async UI state around stop-loss actions,
so regressions could impact TP/SL updates or stale-data handling, but
changes are bounded and add explicit fallbacks/tests.
>
> **Overview**
> **Goal:** reduce HyperLiquid REST API weight (and 429s) during rapid
market switching and TP/SL operations by preferring WebSocket caches.
>
> Adds cache-first primitives in `HyperLiquidSubscriptionService` (fills
cache + atomic `getOrdersCacheIfInitialized`) and `HyperLiquidProvider`
(`getOrFetchPrice`, `getOrFetchFills`), and refactors provider call
sites to use these helpers with stricter invalid-price validation and
single-DEX REST fallbacks.
>
> Updates TP/SL flow to pass live WebSocket `position` into
`updatePositionTPSL` (avoiding a REST positions fetch), uses cached
orders to cancel existing TP/SL when available, and surfaces
partial-failure feedback in `PerpsOrderView` when order succeeds but
TP/SL update fails.
>
> Moves `positionOpenedTimestamp` derivation into
`useHasExistingPosition` (WebSocket fills first, REST historical
fallback), and hardens `PerpsMarketDetailsView` stop-loss banner
interactions against stale closures/market switches; the banner UI
switches from a `Switch` to a "Set" button with a delayed success
checkmark + fade-out. Tests and test IDs are updated accordingly.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0edee81. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>1 parent cb0aa6e commit 03f318a
16 files changed
Lines changed: 1585 additions & 313 deletions
File tree
- app/components/UI/Perps
- Views
- PerpsMarketDetailsView
- PerpsOrderView
- components/PerpsStopLossPromptBanner
- controllers
- providers
- types
- hooks
- services
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
472 | 472 | | |
473 | 473 | | |
474 | 474 | | |
475 | | - | |
| 475 | + | |
| 476 | + | |
476 | 477 | | |
477 | 478 | | |
478 | 479 | | |
| |||
Lines changed: 73 additions & 62 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
252 | 252 | | |
253 | 253 | | |
254 | 254 | | |
255 | | - | |
| 255 | + | |
256 | 256 | | |
257 | | - | |
| 257 | + | |
258 | 258 | | |
259 | 259 | | |
260 | 260 | | |
261 | | - | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
| 261 | + | |
| 262 | + | |
266 | 263 | | |
267 | 264 | | |
268 | | - | |
269 | | - | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
270 | 277 | | |
271 | 278 | | |
272 | 279 | | |
| |||
568 | 575 | | |
569 | 576 | | |
570 | 577 | | |
| 578 | + | |
571 | 579 | | |
572 | 580 | | |
573 | 581 | | |
| |||
600 | 608 | | |
601 | 609 | | |
602 | 610 | | |
603 | | - | |
604 | | - | |
605 | | - | |
606 | | - | |
607 | | - | |
608 | | - | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
609 | 614 | | |
610 | 615 | | |
611 | 616 | | |
| |||
834 | 839 | | |
835 | 840 | | |
836 | 841 | | |
| 842 | + | |
837 | 843 | | |
838 | 844 | | |
839 | 845 | | |
| |||
924 | 930 | | |
925 | 931 | | |
926 | 932 | | |
| 933 | + | |
927 | 934 | | |
928 | 935 | | |
929 | 936 | | |
| |||
975 | 982 | | |
976 | 983 | | |
977 | 984 | | |
| 985 | + | |
978 | 986 | | |
979 | 987 | | |
980 | 988 | | |
| |||
1011 | 1019 | | |
1012 | 1020 | | |
1013 | 1021 | | |
| 1022 | + | |
1014 | 1023 | | |
1015 | 1024 | | |
1016 | 1025 | | |
| |||
1075 | 1084 | | |
1076 | 1085 | | |
1077 | 1086 | | |
| 1087 | + | |
1078 | 1088 | | |
1079 | 1089 | | |
1080 | 1090 | | |
| |||
1692 | 1702 | | |
1693 | 1703 | | |
1694 | 1704 | | |
1695 | | - | |
1696 | | - | |
1697 | | - | |
1698 | | - | |
| 1705 | + | |
| 1706 | + | |
| 1707 | + | |
| 1708 | + | |
| 1709 | + | |
| 1710 | + | |
| 1711 | + | |
1699 | 1712 | | |
1700 | 1713 | | |
1701 | 1714 | | |
| |||
1718 | 1731 | | |
1719 | 1732 | | |
1720 | 1733 | | |
| 1734 | + | |
1721 | 1735 | | |
1722 | 1736 | | |
1723 | | - | |
1724 | | - | |
1725 | | - | |
1726 | | - | |
1727 | | - | |
1728 | | - | |
1729 | | - | |
1730 | | - | |
1731 | | - | |
1732 | | - | |
1733 | | - | |
1734 | | - | |
1735 | | - | |
1736 | | - | |
1737 | | - | |
1738 | | - | |
1739 | | - | |
1740 | | - | |
1741 | | - | |
1742 | | - | |
1743 | | - | |
1744 | | - | |
1745 | | - | |
1746 | | - | |
1747 | | - | |
1748 | | - | |
1749 | | - | |
1750 | | - | |
1751 | | - | |
1752 | | - | |
1753 | | - | |
1754 | | - | |
1755 | | - | |
1756 | | - | |
1757 | | - | |
1758 | | - | |
1759 | | - | |
1760 | | - | |
1761 | | - | |
| 1737 | + | |
| 1738 | + | |
| 1739 | + | |
| 1740 | + | |
| 1741 | + | |
| 1742 | + | |
| 1743 | + | |
| 1744 | + | |
| 1745 | + | |
| 1746 | + | |
| 1747 | + | |
| 1748 | + | |
| 1749 | + | |
| 1750 | + | |
| 1751 | + | |
| 1752 | + | |
| 1753 | + | |
| 1754 | + | |
| 1755 | + | |
| 1756 | + | |
1762 | 1757 | | |
1763 | 1758 | | |
1764 | | - | |
1765 | | - | |
| 1759 | + | |
| 1760 | + | |
| 1761 | + | |
| 1762 | + | |
| 1763 | + | |
| 1764 | + | |
| 1765 | + | |
| 1766 | + | |
| 1767 | + | |
| 1768 | + | |
| 1769 | + | |
| 1770 | + | |
| 1771 | + | |
| 1772 | + | |
| 1773 | + | |
| 1774 | + | |
| 1775 | + | |
| 1776 | + | |
| 1777 | + | |
1766 | 1778 | | |
1767 | 1779 | | |
1768 | 1780 | | |
| |||
1775 | 1787 | | |
1776 | 1788 | | |
1777 | 1789 | | |
1778 | | - | |
| 1790 | + | |
1779 | 1791 | | |
1780 | 1792 | | |
1781 | 1793 | | |
1782 | | - | |
1783 | 1794 | | |
1784 | 1795 | | |
1785 | 1796 | | |
| |||
0 commit comments