Skip to content

Conversation

@michalconsensys
Copy link
Contributor

@michalconsensys michalconsensys commented Dec 18, 2025

This PR addresses HyperLiquid API rejections that occur when TP/SL prices exceed 5 significant figures.

Problem:

  • HyperLiquid API rejects orders with prices containing more than 5 significant figures
  • Users could type prices with excessive precision that would fail on submission
  • RoE percentage calculations could produce prices exceeding the limit

Solution:

  1. Added input validation to prevent users from typing more than 5 significant figures in TP/SL price fields
  2. Added rounding logic when prices are calculated from RoE percentages to ensure they stay within limits
  3. Added MAX_SIGNIFICANT_FIGURES constant for centralized configuration
  4. Fixed TP/SL price display in position cards to use consistent formatting (PRICE_RANGES_UNIVERSAL)

Technical changes:

  • Added three new utility functions: countSignificantFigures, hasExceededSignificantFigures, roundToSignificantFigures
  • Fixed regex bug in countSignificantFigures that incorrectly handled negative numbers (/^-?0+//^-?0*/)
  • Added comprehensive unit tests for the new validation utilities

Changelog

CHANGELOG entry: Fixed TP/SL price input validation to respect HyperLiquid's 5 significant figure limit

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-2063

Manual testing steps

Feature: TP/SL significant figure validation

  Scenario: user cannot type more than 5 significant figures
    Given user has an open perps position
    And user opens the TP/SL form

    When user types "123.45" in the Take Profit price field
    Then the input accepts the value (5 sig figs)
    
    When user tries to type "123.456" in the Take Profit price field
    Then the input blocks the 6th significant figure

  Scenario: RoE percentage calculation rounds to 5 significant figures
    Given user has an open perps position
    And user opens the TP/SL form

    When user enters a RoE percentage that would calculate to "123.456789"
    Then the price field displays the value rounded to 5 significant figures

Screenshots/Recordings

Before

User was able to enter more decimals than supported

After

Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-01-05.at.12.16.56.mov

Pre-merge author checklist

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.

Note

Ensures TP/SL prices comply with HyperLiquid’s 5 significant-figure limit across input, calculations, and display.

  • Adds MAX_SIGNIFICANT_FIGURES to DECIMAL_PRECISION_CONFIG and utilities: countSignificantFigures, hasExceededSignificantFigures, roundToSignificantFigures
  • Blocks typing beyond 5 significant figures in usePerpsTPSLForm (handleTakeProfitPriceChange/handleStopLossPriceChange), and rounds RoE-derived prices before formatting
  • Updates TP/SL display formatting in PerpsPositionCard to use PRICE_RANGES_UNIVERSAL for consistency
  • Adds comprehensive unit tests in tpslValidation.test.ts for significant-figure counting/limits and edge cases

Written by Cursor Bugbot for commit b415c15. This will update automatically on new commits. Configure here.

@github-actions
Copy link
Contributor

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.

@michalconsensys michalconsensys added the DO-NOT-MERGE Pull requests that should not be merged label Dec 18, 2025
@michalconsensys
Copy link
Contributor Author

Do not merge, this approach needs to be confirmed

@michalconsensys michalconsensys marked this pull request as ready for review December 18, 2025 16:52
@michalconsensys michalconsensys requested a review from a team as a code owner December 18, 2025 16:52
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 5, 2026

@michalconsensys michalconsensys changed the title feat(perps): add precision warning for TP/SL prices exceeding 5 significant figures feat(perps): do not allow the user to enter more decimals than the significant figures Jan 5, 2026
@michalconsensys michalconsensys changed the title feat(perps): do not allow the user to enter more decimals than the significant figures fix(perps): enforce 5 significant figure limit for TP/SL price inputs Jan 5, 2026
@metamaskbot metamaskbot added the INVALID-PR-TEMPLATE PR's body doesn't match template label Jan 5, 2026
)
return;

if (
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent price rounding between button and text handlers

The PR adds roundToSignificantFigures to the percentage button handlers (lines 725-727 and 779-781) but not to handleTakeProfitPercentageChange and handleStopLossPercentageChange. When a user types in the percentage input field, calculatePriceForRoE can return prices with up to 8 decimal places for small prices, and these are set directly via setTakeProfitPrice(price.toString()) without rounding. This allows users to bypass the 5 significant figures limit by typing percentages instead of prices, creating inconsistent behavior between button clicks and text input.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Contributor

@gambinish gambinish Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to validate that we round correctly when pressing the percent calculation buttons directly as well as when we directly update the trigger price input field

isValidStopLossPercentage,
sanitizePercentageInput,
countSignificantFigures,
hasExceededSignificantFigures,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New utility function lacks required unit tests (Bugbot Rules)

The roundToSignificantFigures function is introduced and used in production code (button handlers at lines 726 and 780) but has zero test coverage. The test file imports countSignificantFigures and hasExceededSignificantFigures but not roundToSignificantFigures. Per the BUGBOT_RULES requiring mandatory test coverage: "EVERY component MUST test: Happy path, Edge cases, Error conditions, Different code paths." This function has 6 distinct code paths (empty/whitespace, NaN/zero, integers, negative allowed decimals, within limit, needs rounding) - none are tested.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to include unit tests for roundToSignificantFigures as well

@michalconsensys michalconsensys removed the DO-NOT-MERGE Pull requests that should not be merged label Jan 5, 2026
Copy link
Contributor

@gambinish gambinish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the PR includes new utility functions to prevent a user from entering more than 5 significant digits when inputing TP/SL. But, we're still supporting asset pairs with more than 5 significant digits like MON PENGU PUMP etc.

So I run into a situation where I can't set a TP/SL to the same precision as the listed asset pair.

Are we sure that we only want to support 5 significant digits? According to the docs, it appears that we can actually support more than 5 significant digits in certain cases. https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/tick-and-lot-size#perp-price-examples

Adding this comment here for viz, but I'm happy to chat about this more in Slack

@gambinish gambinish self-requested a review January 5, 2026 20:00
@github-actions
Copy link
Contributor

github-actions bot commented Jan 5, 2026

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokePerps
  • Risk Level: medium
  • AI Confidence: 95%
click to see 🤖 AI reasoning details

All changes are contained within the Perps (Perpetuals trading) feature directory (app/components/UI/Perps/). The changes include:

  1. PerpsPositionCard.tsx: Minor UI formatting change for TP/SL price display (switching from PRICE_RANGES_MINIMAL_VIEW to PRICE_RANGES_UNIVERSAL)

  2. perpsConfig.ts: Added a new constant MAX_SIGNIFICANT_FIGURES for HyperLiquid API validation

  3. usePerpsTPSLForm.ts: Added input validation to prevent exceeding significant figures and rounding logic for calculated prices

  4. tpslValidation.ts: Added three new utility functions for significant figures counting, validation, and rounding

  5. tpslValidation.test.ts: Comprehensive unit tests for the new validation functions

These changes are focused on improving the Take Profit/Stop Loss (TP/SL) form validation to comply with HyperLiquid API requirements (max 5 significant figures). The changes are well-scoped to the Perps feature with no impact on other wallet functionality. The risk is medium because while the changes are isolated, they affect trading functionality where incorrect validation could impact user orders.

View GitHub Actions results

@gambinish
Copy link
Contributor

Actually, after reviewing this again, I think that the input validation is working as it should. It is actually valid to not be able to add a TP/SL to the same level of precision as the actual asset pair (still seems weird to me)

I'm ready to approve this, but do think that the bugbot comments are legitimate

const [integerPart, decimalPart = ''] = normalized.split('.');

// Count integer significant digits (without leading zeros)
const trimmedInteger = integerPart.replace(/^-?0+/, '') || '';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent regex between counting and rounding functions

The PR description mentions fixing a regex bug from /^-?0+/ to /^-?0*/ in countSignificantFigures, but roundToSignificantFigures uses the old buggy pattern /^-?0+/ at line 123. The 0+ quantifier requires at least one zero to match, so for a negative number like -12.345, the regex fails to match and the minus sign remains, causing integerSigFigs to incorrectly include the minus sign character. This creates inconsistent significant figure counting between the two related functions. The correct regex /^-?0*/ (used in countSignificantFigures) matches zero or more zeros and properly strips the minus sign.

Additional Locations (1)

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants