Skip to content

fix(perps): Can't create a TP/SL with 6 decimals for PUMP#27901

Open
abretonc7s wants to merge 3 commits intomainfrom
fix/perps/tat-2403-0325-1528
Open

fix(perps): Can't create a TP/SL with 6 decimals for PUMP#27901
abretonc7s wants to merge 3 commits intomainfrom
fix/perps/tat-2403-0325-1528

Conversation

@abretonc7s
Copy link
Contributor

@abretonc7s abretonc7s commented Mar 25, 2026

Description

PUMP TP/SL price inputs were blocked at 5 decimal places due to two independent hardcoded limits. PUMP trades at ~$0.00186, so valid trigger prices require 6 decimal places (e.g. 0.001234).

Root cause (two layers):

  1. PerpsTPSLView passed decimals={TP_SL_VIEW_CONFIG.KeypadDecimals} (hardcoded 5) to <Keypad> — the keypad rule silently dropped the 6th digit
  2. usePerpsTPSLForm called hasExceededSignificantFigures(sanitized) with default maxSigFigs=5countSignificantFigures("0.001234") returns 6 (counts all decimal digits including leading zeros), blocking the state update

Fix: Replace both hardcoded limits with values from DECIMAL_PRECISION_CONFIG:

  • keypadDecimals is now computed dynamically from currentPrice: floor(-log10(price)) + MaxSignificantFigures, clamped to [2, MaxPriceDecimals]
  • hasExceededSignificantFigures now uses MaxPriceDecimals (=6) as the limit in both TP and SL handlers

Changelog

CHANGELOG entry: Fixed TP/SL trigger price input for low-price assets (e.g. PUMP) now accepting up to 6 decimal places

Related issues

Fixes: TAT-2403

Manual testing steps

Feature: PUMP TP/SL trigger price decimal precision

  Scenario: User can enter a 6-decimal TP price for PUMP
    Given I have an open PUMP long position
    When I navigate to the TP/SL screen
    And I focus the Take Profit price input
    And I type "0.001234" via the keypad
    Then the Take Profit price input shows "0.001234"

Screenshots/Recordings

Before

After

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.

Validation Recipe

Automated validation recipe (validate-recipe.sh)
{
  "pr": "27901",
  "title": "PUMP TP/SL trigger price accepts up to 6 decimal places",
  "jira": "TAT-2403",
  "acceptance_criteria": [
    "TP/SL trigger price input for PUMP accepts up to 6 decimal places (e.g. 0.001234)",
    "Decimal precision is dynamically driven by market price — not a hardcoded global constant",
    "Other markets (e.g. BTC) are unaffected — basic TP/SL via presets still works"
  ],
  "validate": {
    "static": ["yarn lint:tsc"],
    "runtime": {
      "pre_conditions": ["wallet.unlocked"],
      "steps": [
        { "id": "open_pump_position", "action": "flow_ref", "ref": "trade-open-market",
          "params": { "symbol": "PUMP", "side": "long", "usdAmount": "11" } },
        { "id": "wait_position_fill", "action": "wait_for",
          "expression": "Engine.context.PerpsController.getPositions().then(function(ps){var p=ps.filter(function(x){return x.symbol==='PUMP'});return JSON.stringify({count:p.length})})",
          "assert": { "operator": "gt", "field": "count", "value": 0 },
          "timeout_ms": 20000, "poll_ms": 1000 },
        { "id": "create_tpsl_preset", "action": "flow_ref", "ref": "tpsl-create",
          "params": { "symbol": "PUMP", "tpPreset": "25", "slPreset": "-10" } },
        { "id": "nav_tpsl_for_6dec_test", "action": "navigate", "target": "PerpsTPSL",
          "params": { "asset": "PUMP", "currentPrice": 0.00185, "direction": "long" } },
        { "id": "wait_tpsl_screen", "action": "wait_for", "route": "PerpsTPSL" },
        { "id": "focus_tp_input", "action": "eval_sync",
          "expression": "(function(){var hook=globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;var found=null;function walk(f){if(!f)return;var props=f.memoizedProps;if(props&&props.testID===\"perps-tpsl-tp-input\"){found=f;return;}walk(f.child);if(!found)walk(f.sibling);}if(hook&&hook.renderers){hook.renderers.forEach(function(v,k){var roots=hook.getFiberRoots?hook.getFiberRoots(k):null;if(roots)roots.forEach(function(r){if(!found)walk(r.current);});})}if(!found)return \"not-found\";var cur=found.child;while(cur){if(cur.tag===5&&cur.stateNode){var pub=cur.stateNode.canonical&&cur.stateNode.canonical.publicInstance;if(pub&&pub.focus){pub.focus();return \"focused\";}return \"no-focus-method\";}cur=cur.child;}return \"no-host\";})()",
          "assert": { "operator": "eq", "value": "focused" } },
        { "id": "clear_tp_keypad", "action": "clear_keypad", "count": 8 },
        { "id": "type_6decimal_tp_price", "action": "type_keypad", "value": "0.001234" },
        { "id": "assert_tp_6decimal_value", "action": "eval_sync",
          "expression": "(function(){var hook=globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;var found=null;function walk(f){if(!f)return;var props=f.memoizedProps;if(props&&props.testID===\"perps-tpsl-tp-input\"){found=f;return;}walk(f.child);if(!found)walk(f.sibling);}if(hook&&hook.renderers){hook.renderers.forEach(function(v,k){var roots=hook.getFiberRoots?hook.getFiberRoots(k):null;if(roots)roots.forEach(function(r){if(!found)walk(r.current);});})}if(!found)return JSON.stringify({v:\"not-found\"});return JSON.stringify({v:found.memoizedProps&&found.memoizedProps.value||\"no-value\"});})()",
          "assert": { "field": "v", "operator": "contains", "value": "001234" } },
        { "id": "check_no_blocking_errors", "action": "log_watch",
          "window_seconds": 3, "must_not_appear": ["TypeError", "RangeError"] },
        { "id": "screenshot_6decimals", "action": "screenshot", "filename": "pump-tpsl-6-decimals.png" },
        { "id": "cleanup_close_pump", "action": "flow_ref", "ref": "trade-close-position",
          "params": { "symbol": "PUMP" } }
      ]
    }
  }
}

Note

Low Risk
Low risk UI/input-validation change limited to TP/SL price entry precision; main risk is unintended decimal allowance impacting other assets’ trigger-price inputs.

Overview
Fixes TP/SL trigger price entry for low-price perps markets by removing hardcoded 5-decimal limits.

PerpsTPSLView now derives Keypad decimals dynamically from currentPrice (clamped by DECIMAL_PRECISION_CONFIG), and usePerpsTPSLForm relaxes significant-figure blocking to use DECIMAL_PRECISION_CONFIG.MaxPriceDecimals for both TP and SL price handlers. Tests are extended to assert 6-decimal TP/SL inputs (e.g. 0.001234) are accepted.

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

@abretonc7s abretonc7s added DO-NOT-MERGE Pull requests that should not be merged team-perps Perps team labels Mar 25, 2026
@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.

PUMP trades at ~$0.002, requiring 6 decimal places for valid trigger
prices. Two independent hardcoded limits were blocking the 6th digit:

1. PerpsTPSLView passed decimals={TP_SL_VIEW_CONFIG.KeypadDecimals} (=5)
   to <Keypad>. Fixed: compute keypadDecimals dynamically from currentPrice
   using floor(-log10(price)) + MaxSignificantFigures, clamped to
   [2, MaxPriceDecimals].

2. usePerpsTPSLForm called hasExceededSignificantFigures(sanitized) with
   default maxSigFigs=5. countSignificantFigures counts all decimal digits
   including leading zeros, so "0.001234" scored 6 > 5 and was blocked.
   Fixed: pass MaxPriceDecimals (=6) as the limit.

Fixes: TAT-2403
@abretonc7s abretonc7s added the type-bug Something isn't working label Mar 25, 2026
@metamaskbot metamaskbot added the INVALID-PR-TEMPLATE PR's body doesn't match template label Mar 25, 2026
@github-actions
Copy link
Contributor

🔍 Smart E2E Test Selection

⏭️ Smart E2E selection skipped - draft PR

All E2E tests pre-selected.

View GitHub Actions results

@github-actions
Copy link
Contributor

E2E Fixture Validation — Schema is up to date
18 value mismatches detected (expected — fixture represents an existing user).
View details

@sonarqubecloud
Copy link

@metamaskbot metamaskbot removed the INVALID-PR-TEMPLATE PR's body doesn't match template label Mar 25, 2026
@abretonc7s abretonc7s marked this pull request as ready for review March 25, 2026 12:55
@abretonc7s abretonc7s requested a review from a team as a code owner March 25, 2026 12:55
@abretonc7s abretonc7s removed the DO-NOT-MERGE Pull requests that should not be merged label Mar 25, 2026
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

return;

if (
hasExceededSignificantFigures(sanitized) &&
Copy link

Choose a reason for hiding this comment

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

Percentage-to-price rounding still limited to 5 sig figs

Medium Severity

The PR raised the hasExceededSignificantFigures limit from default MaxSignificantFigures (5) to MaxPriceDecimals (6), but all roundToSignificantFigures calls in the same hook still use the default of 5. For PUMP (~$0.00186), manually typing "0.001234" is now accepted, but selecting a TP/SL via percentage input or preset buttons calculates a price that gets truncated to "0.00123" — losing precision for the exact asset this PR targets. The comments on those lines even say "Round to 5 significant figures to match input validation," but input validation now allows 6.

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.

This is a good point 🧠

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

Labels

size-S team-perps Perps team type-bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants