fix(perps): Can't create a TP/SL with 6 decimals for PUMP#27901
fix(perps): Can't create a TP/SL with 6 decimals for PUMP#27901abretonc7s wants to merge 3 commits intomainfrom
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
🔍 Smart E2E Test Selection⏭️ Smart E2E selection skipped - draft PR All E2E tests pre-selected. |
|
✅ E2E Fixture Validation — Schema is up to date |
|
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.
| return; | ||
|
|
||
| if ( | ||
| hasExceededSignificantFigures(sanitized) && |
There was a problem hiding this comment.
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.





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
After
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 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.
PerpsTPSLViewnow derivesKeypaddecimalsdynamically fromcurrentPrice(clamped byDECIMAL_PRECISION_CONFIG), andusePerpsTPSLFormrelaxes significant-figure blocking to useDECIMAL_PRECISION_CONFIG.MaxPriceDecimalsfor 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.