chore(runway): cherry-pick fix(perps): potential rate limit on close positions#25456
chore(runway): cherry-pick fix(perps): potential rate limit on close positions#25456joaoloureirop merged 3 commits intorelease/7.62.2from
Conversation
….0 cp-7.62.2 (#25438) Complete the 429 rate limiting fix for position management operations. The previous fix (commit `425beaead7`) only addressed `updatePositionTPSL()`. This PR extends the fix to `closePosition()`, `closePositions()`, and `updateMargin()` methods. **Problem:** These methods were using `skipCache: true` which forced REST API calls on every operation, leading to 429 rate limiting errors during prolonged app usage. **Solution:** - Remove `skipCache: true` from `closePositions()` and `updateMargin()` to use WebSocket cache - For `closePosition()`, add optional `position` parameter so callers can pass the live WebSocket position directly, avoiding the need to fetch positions entirely - Update `usePerpsClosePosition` hook to pass the position it already has CHANGELOG entry: Fixed rate limiting errors (429) when closing positions or updating margin after prolonged app usage Fixes: Rate limiting issues during position close/margin update operations ```gherkin Feature: Position close without rate limiting Scenario: User closes position after prolonged usage Given user has the app open for extended period (>30 minutes) And user has an open perps position When user closes the position Then the position closes successfully without 429 errors Scenario: User updates margin after prolonged usage Given user has the app open for extended period (>30 minutes) And user has an open perps position with isolated margin When user adjusts the margin Then the margin updates successfully without 429 errors Scenario: User closes all positions Given user has multiple open perps positions When user uses "close all positions" feature Then all positions close successfully without rate limiting errors ``` N/A - Bug fix for rate limiting, no UI changes N/A - Bug fix for rate limiting, no UI changes - [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. - [ ] 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 position-management flows (`closePosition`, `closePositions`, `updateMargin`) and changes them to rely on cached/WebSocket position data, which could surface edge cases if the cache is stale or mismatched, but does not alter core order-placement logic. > > **Overview** > Reduces 429 errors in perps position management by stopping forced REST position refreshes during `closePositions` and `updateMargin`, and by updating `closePosition` to accept an optional live `position` payload (with a cache-based fallback). > > Updates `usePerpsClosePosition` (and its tests) to pass the already-available position through, avoiding extra `getPositions()` calls during close flows. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit ccfc17e. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Michal Szorad <michal.szorad@consensys.net>
|
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. |
| await this.ensureBuilderFeeApproval(); | ||
|
|
||
| // Force fresh API data (not WebSocket cache) since we're about to mutate the position | ||
| const positions = await this.getPositions({ skipCache: true }); |
There was a problem hiding this comment.
Passed position parameter ignored in closePosition method
Medium Severity
The closePosition() method always calls getPositions() and finds the position by coin, completely ignoring any position parameter passed from the hook. The usePerpsClosePosition hook passes position to avoid the API call (as documented in the comment), but closePosition() doesn't extract or use params.position. This defeats the stated rate limiting fix. Compare with updatePositionTPSL() which correctly destructures and uses position: livePosition from params when available.
Additional Locations (1)
|
|
||
| // Force fresh API data (not WebSocket cache) since we're about to mutate the position | ||
| const positions = await this.getPositions({ skipCache: true }); | ||
| const positions = await this.getPositions(); |
There was a problem hiding this comment.
Stale comment contradicts new cache-using behavior
Low Severity
The comment on line 3652 states "Force fresh API data (not WebSocket cache)" but the code was changed to getPositions() without skipCache: true, which now uses the WebSocket cache. This directly contradicts the code's actual behavior. The other methods modified in this PR (closePositions() and updateMargin()) had their comments correctly updated or removed, but this one was missed.
🔍 Smart E2E Test Selection⏭️ Smart E2E selection skipped - base branch is not main (base: release/7.62.2) All E2E tests pre-selected. |
|
No release label on PR. Adding release label release-7.62.2 on PR, as PR was cherry-picked in branch 7.62.2. |
|
No release label on PR. Adding release label release-7.62.2 on PR, as PR was cherry-picked in branch 7.62.2. |


Description
Complete the 429 rate limiting fix for position management operations.
The previous fix (commit
425beaead7) only addressedupdatePositionTPSL(). This PR extends the fix toclosePosition(),closePositions(), andupdateMargin()methods.Problem: These methods were using
skipCache: truewhich forcedREST API calls on every operation, leading to 429 rate limiting errors
during prolonged app usage.
Solution:
skipCache: truefromclosePositions()andupdateMargin()to use WebSocket cache
closePosition(), add optionalpositionparameter so callerscan pass the live WebSocket position directly, avoiding the need to
fetch positions entirely
usePerpsClosePositionhook to pass the position it alreadyhas
Changelog
CHANGELOG entry: Fixed rate limiting errors (429) when closing positions
or updating margin after prolonged app usage
Related issues
Fixes: Rate limiting issues during position close/margin update
operations
Manual testing steps
Screenshots/Recordings
Before
N/A - Bug fix for rate limiting, no UI changes
After
N/A - Bug fix for rate limiting, no UI changes
Pre-merge author checklist
Docs and MetaMask Mobile
Coding
Standards.
if applicable
guidelines).
Not required for external contributors.
Pre-merge reviewer checklist
app, test code being changed).
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
Note
Medium Risk
Switches critical trading actions to rely on WebSocket-cached positions instead of forced REST fetches, which reduces rate limiting but risks acting on slightly stale position data during rapid state changes.
Overview
Reduces HyperLiquid REST pressure during position management by removing
skipCache: trueposition fetches inclosePositions(),closePosition(), andupdateMargin(), so these operations prefer the WebSocket/cache-backedgetPositions()path.This change is aimed at preventing 429 rate limiting during prolonged app usage when repeatedly closing positions or adjusting margin.
Written by Cursor Bugbot for commit a84367e. This will update automatically on new commits. Configure here.
Co-authored-by: Michal Szorad michal.szorad@consensys.net 6f89dec