From a7f2cb0f6bace8795bf4e1b830db89b03a393dd9 Mon Sep 17 00:00:00 2001 From: Gojv-byte Date: Sat, 26 Sep 2026 22:18:07 +0100 Subject: [PATCH] Add slippage impact override protection --- src/components/common/BuySellKeyFlow.tsx | 39 +++++++++-- .../common/PriceImpactOverrideCheckbox.tsx | 27 ++++++++ src/components/common/PriceImpactWarning.tsx | 8 +-- .../common/TradeConfirmationModal.tsx | 6 +- src/components/common/TradeDialog.tsx | 36 +++++++++-- .../common/__tests__/BuySellKeyFlow.test.tsx | 16 +++++ .../TradeDialog.slippageControls.test.tsx | 64 ++++++++++++++++++- .../TradeDialog.slippageTolerance.test.tsx | 6 +- .../useSlippageTolerancePreference.test.tsx | 41 ++++++++++++ src/hooks/useSlippageTolerancePreference.ts | 35 ++++++++++ ...DetailPage.buyKeyFlow.integration.test.tsx | 5 ++ ...gPage.buyFlowEndToEnd.integration.test.tsx | 49 ++++++++++++-- 12 files changed, 304 insertions(+), 28 deletions(-) create mode 100644 src/components/common/PriceImpactOverrideCheckbox.tsx create mode 100644 src/hooks/__tests__/useSlippageTolerancePreference.test.tsx create mode 100644 src/hooks/useSlippageTolerancePreference.ts diff --git a/src/components/common/BuySellKeyFlow.tsx b/src/components/common/BuySellKeyFlow.tsx index 2c9132a6..5ebf4566 100644 --- a/src/components/common/BuySellKeyFlow.tsx +++ b/src/components/common/BuySellKeyFlow.tsx @@ -7,16 +7,16 @@ import { } from '@/utils/keyPriceDisplay.utils'; import SlippageToleranceSelector from '@/components/common/SlippageToleranceSelector'; import PriceImpactWarning from '@/components/common/PriceImpactWarning'; +import PriceImpactOverrideCheckbox from '@/components/common/PriceImpactOverrideCheckbox'; import TradeConfirmationModal from '@/components/common/TradeConfirmationModal'; import LaunchPenaltyWarning from '@/components/common/LaunchPenaltyWarning'; import { - DEFAULT_SLIPPAGE_TOLERANCE_PERCENT, computeSlippageBounds, type SlippageBounds, } from '@/utils/slippageTolerance.utils'; import { calculateTradePriceImpact, - PRICE_IMPACT_THRESHOLD_PERCENT, + isHighPriceImpact, } from '@/utils/priceImpact.utils'; import { calculateLaunchPenalty } from '@/utils/launchPenalty.utils'; import { @@ -30,6 +30,7 @@ import type { KeyConfig } from '@/services/course.service'; import SpreadIndicator from '@/components/common/SpreadIndicator'; import { cn } from '@/lib/utils'; import { ArrowRight } from 'lucide-react'; +import { useSlippageTolerancePreference } from '@/hooks/useSlippageTolerancePreference'; export interface BuySellTradeParams { creatorId?: string; @@ -100,7 +101,10 @@ export const BuySellKeyFlow: React.FC = ({ const [amountText, setAmountText] = useState('1'); const [touched, setTouched] = useState(false); const [slippageTolerancePercent, setSlippageTolerancePercent] = - useState(DEFAULT_SLIPPAGE_TOLERANCE_PERCENT); + useSlippageTolerancePreference(); + const [acknowledgedImpactKey, setAcknowledgedImpactKey] = useState< + string | null + >(null); const [confirmationOpen, setConfirmationOpen] = useState(false); const [internalSubmitting, setInternalSubmitting] = useState(false); @@ -215,6 +219,12 @@ export const BuySellKeyFlow: React.FC = ({ currentSupply: currentSupply ?? 0, }); }, [isValid, parsedAmount, side, currentSupply]); + const impactWarningActive = + isValid && + isHighPriceImpact(priceImpactPercent, slippageTolerancePercent); + const impactAcknowledgementKey = `${side}:${parsedAmount}:${currentSupply ?? 0}:${slippageTolerancePercent}`; + const impactAcknowledged = + acknowledgedImpactKey === impactAcknowledgementKey; // Early sell launch penalty const launchPenalty = useMemo(() => { @@ -234,12 +244,13 @@ export const BuySellKeyFlow: React.FC = ({ // Open confirmation modal const handleReviewOrder = () => { setTouched(true); - if (!isValid) return; + if (!isValid || (impactWarningActive && !impactAcknowledged)) return; setConfirmationOpen(true); }; // Final submission const handleConfirmSubmission = async () => { + if (impactWarningActive && !impactAcknowledged) return; setInternalSubmitting(true); const tradeParams: BuySellTradeParams = { creatorId, @@ -461,17 +472,31 @@ export const BuySellKeyFlow: React.FC = ({ /> - {/* Price Impact Warning when impact exceeds 5% */} + {/* Price impact warning when impact exceeds the selected tolerance */} + {impactWarningActive && ( + + setAcknowledgedImpactKey( + checked ? impactAcknowledgementKey : null + ) + } + /> + )} {/* Review / Proceed to Confirmation Button */}