-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
fix(perps): use USD as source of truth for order precision and validation cp-7.59.0 #22252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… loading states - Added a new state to track the optimization process for order amounts. - Introduced a wrapper function to manage the loading state during order amount optimization. - Updated relevant components to utilize the new optimization handler, ensuring a smoother user experience. - Enhanced loading state management in the PerpsAmountDisplay component to reflect the optimization status.
- Removed the state and wrapper function for tracking the optimization process during order amount adjustments. - Directly invoked the `optimizeOrderAmount` function in relevant handlers, simplifying the code and improving readability. - Updated loading state management to ensure accurate representation without the now-removed optimization state.
- Added `skipValidation` parameter to `usePerpsClosePositionValidation` and `usePerpsOrderValidation` to prevent flickering during keypad input. - Updated `PerpsClosePositionView` and `PerpsOrderView` components to utilize the new `skipValidation` feature. - Improved order amount optimization logic to avoid unnecessary re-optimizations when input is focused. - Refactored position size calculation to use rounding instead of flooring for better accuracy. This update aims to improve user experience by reducing validation interruptions during input adjustments.
|
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. |
app/components/UI/Perps/Views/PerpsOrderView/PerpsOrderView.tsx
Outdated
Show resolved
Hide resolved
- Bump version of `@nktkas/hyperliquid` from `0.25.7` to `0.25.9` in `package.json` and `yarn.lock`. - Add `@henrygd/semaphore` dependency version `0.1.0` to `yarn.lock`. - Remove the FinalizationRegistry polyfill from `shim.js` as it is no longer needed for the Hyperliquid SDK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Rounding Inconsistency Breaks Position Sizing
findHighestAmountForPositionSize calculates the highest USD amount for a given position size, but its logic assumes calculatePositionSize uses Math.floor rounding. After changing to Math.round, the function returns incorrect values. For example, with position size 0.000210 at price $50000, it returns $10, but calculatePositionSize($10, $50000) yields 0.000200, not 0.000210. This breaks order amount optimization, potentially causing orders to fail validation or execute at incorrect sizes.
app/components/UI/Perps/utils/orderCalculations.ts#L177-L192
metamask-mobile/app/components/UI/Perps/utils/orderCalculations.ts
Lines 177 to 192 in 988b2c5
| } | |
| export function findHighestAmountForPositionSize( | |
| params: HighestAmountForPositionSizeParams, | |
| ): number { | |
| const { positionSize, price, szDecimals = 6 } = params; | |
| // Calculate the exact USD value for this position size | |
| const exactUsdValue = parseFloat(positionSize.toFixed(szDecimals)) * price; | |
| // Calculate the increment that would bump to the next position size | |
| const multiplier = Math.pow(10, szDecimals); | |
| const usdIncrement = price / multiplier; | |
| // The highest amount is just before the next position size tier | |
| const highestAmount = exactUsdValue + usdIncrement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Rounding Discrepancy: Exceeding Position Limits
findHighestAmountForPositionSize calculates the highest USD amount for a given position size assuming Math.floor rounding, but calculatePositionSize now uses Math.round. With symmetric rounding, the calculated highestAmount can produce a position size one increment higher than intended. For example, with Math.round, amounts near the midpoint between two position size tiers will round up, causing findOptimalAmount to return USD amounts that map to incorrect position sizes, potentially exceeding user balance or minimum order requirements.
app/components/UI/Perps/utils/orderCalculations.ts#L168-L182
metamask-mobile/app/components/UI/Perps/utils/orderCalculations.ts
Lines 168 to 182 in 2465f34
| positionSizeNum = incrementedPositionSize; | |
| highestAmount = findHighestAmountForPositionSize({ | |
| positionSize: positionSizeNum, | |
| price, | |
| szDecimals, | |
| }); | |
| } | |
| return highestAmount.toString(); | |
| } | |
| export function findHighestAmountForPositionSize( | |
| params: HighestAmountForPositionSizeParams, | |
| ): number { | |
| const { positionSize, price, szDecimals = 6 } = params; |
- Removed the `findOptimalAmount` utility and adjusted order calculations to directly derive position size from the target USD amount. - Updated the `HyperLiquidProvider` to validate and recalculate position size based on the USD amount, ensuring slippage and price validation are handled correctly. - Enhanced order validation to prevent precision loss during recalculations by using the original USD amount for minimum order size checks. - Introduced a hybrid approach for order parameters, allowing both size and USD amount to be passed for backward compatibility. - Updated relevant components and hooks to reflect these changes, improving overall order handling and user experience.
app/components/UI/Perps/controllers/providers/HyperLiquidProvider.ts
Outdated
Show resolved
Hide resolved
- Updated ORDER_SLIPPAGE_CONFIG to define slippage tolerance in basis points instead of decimal. - Adjusted references in HyperLiquidProvider to utilize the new basis points configuration for slippage calculations. - Modified OrderParams type definition to reflect the change in default slippage representation. - Improved clarity in comments regarding slippage values and their conversions.
- Introduced slippage parameters (usdAmount, priceAtCalculation, maxSlippageBps) in the ClosePositionParams type for improved validation. - Updated the usePerpsClosePosition hook to pass slippage parameters during position closure. - Modified HyperLiquidProvider to handle slippage consistently when executing position closes. - Added ORDER_SLIPPAGE_CONFIG for default slippage tolerance in basis points, ensuring uniformity across components.
- Added slippage parameters to PerpsClosePositionView tests for improved validation during position closure. - Updated tests to handle minimal market data requirements, ensuring the component behaves correctly with incomplete data. - Removed redundant size validation tests from hyperLiquidValidation, as size checks are now integrated into the order validation logic.
- Refactored the `handleClosePosition` function to accept a single object parameter instead of multiple arguments, enhancing readability and maintainability. - Updated related tests to align with the new parameter structure, ensuring consistent behavior across the application. - Adjusted the handling of slippage parameters and tracking data for better organization and clarity in the closing position logic.
app/components/UI/Perps/Views/PerpsClosePositionView/PerpsClosePositionView.test.tsx
Outdated
Show resolved
Hide resolved
…onsistency - Introduced BigNumber for precise numerical calculations. - Updated fallback data display during loading states for better UX. - Refactored slippage handling to utilize ORDER_SLIPPAGE_CONFIG for consistency. - Improved position size calculation logic to handle undefined market data gracefully. - Added PerpsFeesDisplay component back to enhance fee visibility. - Cleaned up imports and organized code for better readability and maintainability.
app/components/UI/Perps/Views/PerpsClosePositionView/PerpsClosePositionView.tsx
Outdated
Show resolved
Hide resolved
app/components/UI/Perps/Views/PerpsClosePositionView/PerpsClosePositionView.test.tsx
Outdated
Show resolved
Hide resolved
app/components/UI/Perps/Views/PerpsOrderView/PerpsOrderView.tsx
Outdated
Show resolved
Hide resolved
…PerpsOrderView - Updated `usePerpsMarketData` to accept an object parameter for improved flexibility, allowing for automatic error toast notifications. - Refactored market data fetching in `PerpsClosePositionView` and `PerpsOrderView` to utilize the new parameter structure, ensuring consistent error handling. - Implemented fallback logic for `szDecimals` in `PerpsClosePositionView` to prevent crashes when market data is unavailable. - Cleaned up imports and organized code for better readability and maintainability.
…sClosePositionView and PerpsOrderView - Updated fallback for `szDecimals` to use `FALLBACK_SIZE_DECIMALS` to prevent crashes when market data fails to load. - Enhanced comments for clarity regarding fallback logic in both views. - Added a new constant in `perpsConfig.ts` to define the fallback size decimals. - Updated localization file to include a new required price message for better user guidance.
|


Description
This PR implements a major refactor of the Perps order handling system to address precision and validation issues. The changes establish USD as the primary source of truth for order amounts, replacing the complex
findOptimalAmountoptimization logic with a simpler, more robust approach that recalculates position sizes at execution time using fresh market prices.Key Changes
1. Migration from
findOptimalAmountto USD-as-Source-of-TruthPrevious Approach:
findOptimalAmountfunction to find the "optimal" USD amount that maximized value while maintaining the same position sizeNew Approach:
orderCalculations.ts)usePerpsOrderForm.ts)Benefits:
2. Standardized Slippage Management
New Configuration:
Improvements:
priceAtCalculationandmaxSlippageBpsfields inOrderParamsSlippage Validation Example:
3. Enhanced Order Validation
Validation Improvements:
skipValidationflag to prevent validation flash during keypad inputType System Updates:
4. Close Position Validation & Precision
Problem Addressed:
szDecimalsSolution - Full vs Partial Close Distinction:
Full Position Close (100%):
isFullCloseflag toOrderParamstypesizeparameter is omitted:isFullClose: !params.sizePartial Position Close:
currentPriceorusdAmountfor validationClose Amount Calculation Refactor:
calculateCloseAmountFromPercentageto USD as source of truthszDecimalsparameter (removed dangerous defaults)calculatePositionSizelogic for consistencyType Changes:
Files Changed:
controllers/types/index.ts- AddedisFullCloseflagutils/positionCalculations.ts- Refactored to use USD as source of truth with asset-specific precisionViews/PerpsClosePositionView/PerpsClosePositionView.tsx- AddedszDecimalshandling with loading statecontrollers/providers/HyperLiquidProvider.ts- Updated validation to skip minimum for full closes5. Position Size Calculation Changes
Rounding Behavior:
Math.floortoMath.roundincalculatePositionSizeProvider-Side Recalculation:
6. User Experience Improvements
Input Handling:
Code Cleanup:
shim.js(no longer needed by updated dependencies)findOptimalAmountandfindHighestAmountForPositionSizefunctionsMigration Path
Backward Compatibility:
sizefield still present inOrderParamsfor backward compatibilityusdAmountis not providedHybrid Approach:
Orders now pass both
usdAmount(primary) andsize(derived):Files Changed
Core Logic (276 additions, 290 deletions):
app/components/UI/Perps/controllers/providers/HyperLiquidProvider.ts(+148 lines)app/components/UI/Perps/utils/orderCalculations.ts(-149 lines)findOptimalAmountandfindHighestAmountForPositionSizeMath.floortoMath.roundfor position size calculationapp/components/UI/Perps/hooks/usePerpsOrderForm.ts(-71 lines)optimizeOrderAmountfunction and related logicapp/components/UI/Perps/hooks/usePerpsOrderValidation.ts(+28 lines)skipValidationandoriginalUsdAmountparametersUI Components:
app/components/UI/Perps/Views/PerpsOrderView/PerpsOrderView.tsx(+/-54 lines)skipValidationflag during input focususdAmountand price validation params to providerConfiguration:
app/components/UI/Perps/constants/perpsConfig.ts(+10 lines)ORDER_SLIPPAGE_CONFIGconstantapp/components/UI/Perps/constants/hyperLiquidConfig.ts(-1 line)Types & Validation:
app/components/UI/Perps/controllers/types/index.ts(+9 lines)OrderParamstype with USD-based fieldsapp/components/UI/Perps/utils/hyperLiquidValidation.ts(+9 lines)app/components/UI/Perps/utils/hyperLiquidValidation.test.ts(+29 lines)Cleanup:
shim.js(-18 lines)Changelog
CHANGELOG entry: Improved Perps order precision and validation by using USD amounts as source of truth and standardizing slippage management
Related issues
Fixes: TAT-1902 - Investigate and resolve order placement issue for specific token pairs
How this PR fixes TAT-1902:
The USD-as-source-of-truth refactor directly addresses order placement failures for specific token pairs by:
szDecimalsprecision throughout (no more hardcoded 6 decimals)This ensures orders are calculated with the most current price and correct precision for each token pair, preventing the placement failures that occurred with the previous approach.
Manual testing steps
Screenshots/Recordings
Before
After
Pre-merge author checklist
Pre-merge reviewer checklist
Technical Notes for Reviewers
Critical Changes to Review
Rounding Change in
calculatePositionSizeMath.floortoMath.roundBackward Compatibility
OrderParams.sizestill present but recalculated by providerusdAmountparameterSlippage Validation
Minimum Order Size Validation
isFullCloseflagInput Clamping Logic
Testing Recommendations
Note
Switches order/close flows to USD-as-source-of-truth with provider-side size recalculation and unified slippage, improves validation/precision, removes optimization logic, and updates hooks/tests/docs.
szDecimals(HyperLiquidProvider.ts).ORDER_SLIPPAGE_CONFIG(default 100 bps) and price-staleness validation; passusdAmount,priceAtCalculation,maxSlippageBpsthroughOrderParams.orderCalculations(calculateFinalPositionSize,calculateOrderPriceAndSize,buildOrdersArray).isFullClose; propagate slippage params in close flows.calculatePositionSize/close calculations use asset precision, round to nearest, and ensure post-rounding USD meets target.validateOrdernow validates minimums from USD, requires price for limit orders, and tolerates full closes.findOptimalAmount/related logic and old slippage fromhyperLiquidConfig.PerpsOrderView/PerpsClosePositionView: pass USD + slippage params; skip validation during input; clamp only for keypad; use market data with fallback decimals.usePerpsMarketDataaccepts{ asset, showErrorToast }and auto-toasts on errors; expose loading.usePerpsOrderValidation/usePerpsClosePositionValidation: addskipValidation, use original USD for min checks.OrderParams/ClosePositionParamswith USD/slippage/full-close fields; addDECIMAL_PRECISION_CONFIG.FALLBACK_SIZE_DECIMALSandORDER_SLIPPAGE_CONFIG.shim.js; simplify order form by dropping optimization APIs.Written by Cursor Bugbot for commit fda1210. This will update automatically on new commits. Configure here.