fix(perps): Can't create a TP/SL with 6 decimals for PUMP#27901
Conversation
|
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
Update all roundToSignificantFigures calls in usePerpsTPSLForm to use DECIMAL_PRECISION_CONFIG.MaxPriceDecimals (6) instead of the default MaxSignificantFigures (5), matching the hasExceededSignificantFigures validation limit already updated in this PR.
keypadDecimals is price-based (e.g. 2 for BTC at ~$50k), but the shared Keypad instance was applying it to both price and percentage inputs. Switch to MaxSignificantFigures for percentage-focused inputs so RoE % inputs always allow up to 5 decimal places.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
Tag selection rationale:
No shared components, navigation, controllers, or infrastructure are affected. Risk is low as this is a targeted bug fix for decimal precision in a specific Perps sub-feature. Performance Test Selection: |
|
✅ E2E Fixture Validation — Schema is up to date |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #27901 +/- ##
==========================================
- Coverage 82.60% 82.60% -0.01%
==========================================
Files 4839 4839
Lines 124418 124420 +2
Branches 27726 27728 +2
==========================================
- Hits 102774 102773 -1
Misses 14580 14580
- Partials 7064 7067 +3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|




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):
PerpsTPSLViewpasseddecimals={TP_SL_VIEW_CONFIG.KeypadDecimals}(hardcoded5) to<Keypad>— the keypad rule silently dropped the 6th digitusePerpsTPSLFormcalledhasExceededSignificantFigures(sanitized)with defaultmaxSigFigs=5—countSignificantFigures("0.001234")returns 6 (counts all decimal digits including leading zeros), blocking the state updateFix: Replace both hardcoded limits with values from
DECIMAL_PRECISION_CONFIG:keypadDecimalsis now computed dynamically fromcurrentPrice:floor(-log10(price)) + MaxSignificantFigures, clamped to[2, MaxPriceDecimals]hasExceededSignificantFiguresnow usesMaxPriceDecimals(=6) as the limit in both TP and SL handlersChangelog
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
Screenshots/Recordings
Before
before.mp4
After
after.mp4
Pre-merge author checklist
Pre-merge reviewer checklist
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 and rounding; main risk is unintended precision/rounding differences for some markets when entering prices via keypad or percentage conversions.
Overview
Fixes TP/SL trigger price entry for very low-priced perps assets by removing hardcoded 5-decimal limits.
PerpsTPSLViewnow computeskeypadDecimalsdynamically fromcurrentPrice(clamped byDECIMAL_PRECISION_CONFIG) and only applies it to price inputs (percentage inputs keep existing precision).usePerpsTPSLFormupdates price validation and all RoE→price rounding to useDECIMAL_PRECISION_CONFIG.MaxPriceDecimals, and adds tests ensuring 6-decimal TP/SL prices (e.g.0.001234) are accepted.Written by Cursor Bugbot for commit 620a45c. This will update automatically on new commits. Configure here.