From 59b7faa579b9a81e83255ab646f1350e938d18e4 Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Tue, 16 Jun 2026 15:54:14 +0700 Subject: [PATCH 01/52] Mock account --- apps/kyberswap-interface/src/hooks/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kyberswap-interface/src/hooks/index.ts b/apps/kyberswap-interface/src/hooks/index.ts index 0bbcabd482..b5f0801ad5 100644 --- a/apps/kyberswap-interface/src/hooks/index.ts +++ b/apps/kyberswap-interface/src/hooks/index.ts @@ -61,7 +61,7 @@ export function useWeb3React() { return useMemo( () => ({ - account: account.address, + account: '0x0193a8a52D77E27bDd4f12E0cDd52d8Ff1d97d68', chainId: account.chainId, connector: account.connector, active: account.address !== undefined, From 3b3846dd117151a07dc1f081d12578388d6047a8 Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Tue, 16 Jun 2026 14:52:41 +0700 Subject: [PATCH 02/52] chore: polish ui first --- .../SwapForm/ReverseTokenSelectionButton.tsx | 12 ++++++++---- .../src/components/SwapForm/SlippageSetting.tsx | 10 +++++++--- .../src/components/SwapForm/index.tsx | 1 + .../TokenSelectorModal/TokenSelectorContent.tsx | 16 +++++++--------- .../swapv2/LimitOrder/LimitOrderForm.tsx | 2 +- .../src/pages/Bridge/SelectNetwork.tsx | 2 +- .../CrossChainSwap/components/TokenPanel.tsx | 4 ++-- .../src/pages/CrossChainSwap/index.tsx | 10 +++++----- .../src/pages/SwapV3/Header.tsx | 6 +++--- 9 files changed, 35 insertions(+), 28 deletions(-) diff --git a/apps/kyberswap-interface/src/components/SwapForm/ReverseTokenSelectionButton.tsx b/apps/kyberswap-interface/src/components/SwapForm/ReverseTokenSelectionButton.tsx index 7c35345978..d89cd62b80 100644 --- a/apps/kyberswap-interface/src/components/SwapForm/ReverseTokenSelectionButton.tsx +++ b/apps/kyberswap-interface/src/components/SwapForm/ReverseTokenSelectionButton.tsx @@ -1,11 +1,13 @@ import { useState } from 'react' import ArrowRotate from 'components/ArrowRotate' +import { cn } from 'utils/cn' type Props = { + className?: string onClick: () => void } -const ReverseTokenSelectionButton: React.FC = ({ onClick }) => { +const ReverseTokenSelectionButton: React.FC = ({ className, onClick }) => { const [rotated, setRotated] = useState(false) const handleClick = () => { @@ -14,9 +16,11 @@ const ReverseTokenSelectionButton: React.FC = ({ onClick }) => { } return ( -
- -
+ ) } diff --git a/apps/kyberswap-interface/src/components/SwapForm/SlippageSetting.tsx b/apps/kyberswap-interface/src/components/SwapForm/SlippageSetting.tsx index 4ef8b4495a..90c3708456 100644 --- a/apps/kyberswap-interface/src/components/SwapForm/SlippageSetting.tsx +++ b/apps/kyberswap-interface/src/components/SwapForm/SlippageSetting.tsx @@ -26,7 +26,7 @@ export const DropdownIcon = ({ {...rest} style={{ width: size || 12, height: size || 12, ...rest.style }} className={cn( - 'relative z-0 ml-1 flex items-center justify-center overflow-visible rounded-full p-0.5 text-white2 transition-all duration-200 ease-in-out [&>svg]:relative [&>svg]:z-[1]', + 'relative z-0 flex items-center justify-center overflow-visible rounded-full text-white2 transition-all duration-200 ease-in-out [&>svg]:relative [&>svg]:z-[1]', 'data-[flip=true]:rotate-180', 'data-[highlight=true]:text-primary', 'data-[highlight=true]:after:pointer-events-none data-[highlight=true]:after:absolute data-[highlight=true]:after:-inset-px data-[highlight=true]:after:rounded-full data-[highlight=true]:after:bg-primary/25 data-[highlight=true]:after:content-[""]', @@ -131,7 +131,11 @@ const SlippageSetting = ({ rightComponent, tooltip, slippageInfo }: Props) => { Max Slippage: -
setExpanded(e => !e)} className="flex cursor-pointer items-center gap-1"> +
setExpanded(e => !e)} + className="flex cursor-pointer items-center gap-1 hover:brightness-[0.85]" + > {msg ? ( @@ -143,7 +147,7 @@ const SlippageSetting = ({ rightComponent, tooltip, slippageInfo }: Props) => { - +
diff --git a/apps/kyberswap-interface/src/components/SwapForm/index.tsx b/apps/kyberswap-interface/src/components/SwapForm/index.tsx index db2a2e8596..b84155e7c1 100644 --- a/apps/kyberswap-interface/src/components/SwapForm/index.tsx +++ b/apps/kyberswap-interface/src/components/SwapForm/index.tsx @@ -274,6 +274,7 @@ const SwapForm: React.FC = props => { /> { trackingHandler(TRACKING_EVENT_TYPE.TOKEN_PAIR_REVERSED, { from_token: currencyIn?.symbol, diff --git a/apps/kyberswap-interface/src/components/TokenSelectorModal/TokenSelectorContent.tsx b/apps/kyberswap-interface/src/components/TokenSelectorModal/TokenSelectorContent.tsx index 3560671393..c811f75153 100644 --- a/apps/kyberswap-interface/src/components/TokenSelectorModal/TokenSelectorContent.tsx +++ b/apps/kyberswap-interface/src/components/TokenSelectorModal/TokenSelectorContent.tsx @@ -341,21 +341,19 @@ export const TokenSelectorContent = ({ - + {title || Select a token} - - Find a token by searching for its name or symbol or by pasting its address below. -
- You can select and trade any token on KyberSwap. -
- + + Find a token by searching for its name or symbol or by pasting its address below. +
+ You can select and trade any token on KyberSwap. +
) } /> diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/LimitOrderForm.tsx index 6bf9035a3a..8115531fbd 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/LimitOrderForm.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/LimitOrderForm.tsx @@ -995,7 +995,7 @@ const LimitOrderForm = forwardRef(function LimitOrd diff --git a/apps/kyberswap-interface/src/pages/Bridge/SelectNetwork.tsx b/apps/kyberswap-interface/src/pages/Bridge/SelectNetwork.tsx index a144bbac8c..833a7a74a2 100644 --- a/apps/kyberswap-interface/src/pages/Bridge/SelectNetwork.tsx +++ b/apps/kyberswap-interface/src/pages/Bridge/SelectNetwork.tsx @@ -55,7 +55,7 @@ const SelectNetwork = forwardRef< )} {name} - +
+
setRevertPrice(!revertPrice)} > 1{' '} @@ -279,9 +279,9 @@ export function CrossChainSwap({ onQuoteChange }: CrossChainSwapProps) { -
+
{ if (isEvmChain(fromChainId) && isToEvm) { @@ -292,7 +292,7 @@ export function CrossChainSwap({ onQuoteChange }: CrossChainSwapProps) { } }} > - + {isEvmChain(fromChainId) && isToEvm ? ( Send to other wallet ) : ( @@ -301,7 +301,7 @@ export function CrossChainSwap({ onQuoteChange }: CrossChainSwapProps) { {isEvmChain(fromChainId) && isToEvm && - (showEvmRecipient ? : )} + (showEvmRecipient ? : )}
{toChainId && (isEvmChain(fromChainId) && isToEvm ? showEvmRecipient : true) && ( diff --git a/apps/kyberswap-interface/src/pages/SwapV3/Header.tsx b/apps/kyberswap-interface/src/pages/SwapV3/Header.tsx index 5a64158424..3c2ceb73c0 100644 --- a/apps/kyberswap-interface/src/pages/SwapV3/Header.tsx +++ b/apps/kyberswap-interface/src/pages/SwapV3/Header.tsx @@ -47,7 +47,7 @@ export default function Header({ Gasless & no slippage - Kyberswap Limit Order execute on-chain automatically when the market reaches your price. - {t`Buy or sell tokens at customized prices`} + {t`Buy or sell tokens at customized prices`} )} {isSwapPage && ( @@ -57,7 +57,7 @@ export default function Header({ An advanced aggregator splits your trade across hundreds of DEXs and liquidity sources for minimal slippage. - {t`Instantly buy or sell tokens at superior prices`} + {t`Instantly buy or sell tokens at superior prices`} )} {isCrossChainPage && ( @@ -66,7 +66,7 @@ export default function Header({ Swap tokens between EVMs, Bitcoin, Solana, and Near chains in one step - no manual bridging. Quotes from multiple providers, best rate picked automatically. - {t`Swap between tokens on different chains`} + {t`Swap between tokens on different chains`} )} From 83f473b4688875b2b3259389437bb17c7d684152 Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Tue, 16 Jun 2026 16:57:27 +0700 Subject: [PATCH 03/52] refactor(limit-order): split form structure chore --- .../components/Announcement/Popups/index.tsx | 2 +- .../index.tsx} | 15 +- .../src/components/NumericalInput/index.tsx | 2 +- .../WalletPopup/Transactions/Status.tsx | 2 +- .../Transactions/TransactionItem.tsx | 2 +- .../WalletPopup/Transactions/index.tsx | 2 +- .../{ => EditOrder}/EditOrderModal.tsx | 7 +- .../{ => Form}/ActionButtonLimitOrder.tsx | 0 .../LimitOrder/{ => Form}/DeltaRate.tsx | 2 +- .../Form/LimitOrderExpirySection.tsx | 79 ++ .../swapv2/LimitOrder/Form/LimitOrderForm.tsx | 315 +++++ .../LimitOrder/Form/LimitOrderRateSection.tsx | 91 ++ .../Form/LimitOrderTokenSection.tsx | 158 +++ .../Form/hooks/useLimitOrderExecution.tsx | 557 +++++++++ .../Form/hooks/useLimitOrderFormState.ts | 342 ++++++ .../swapv2/LimitOrder/LimitOrderForm.tsx | 1088 ----------------- .../swapv2/LimitOrder/ListOrder/index.tsx | 4 +- .../ListOrder/useRequestCancelOrder.tsx | 4 +- .../LimitOrder/Modals/CancelOrderModal.tsx | 4 +- .../src/components/swapv2/LimitOrder/const.ts | 3 - .../{ => hooks}/useCancellingOrders.ts | 5 +- .../{ => hooks}/useFetchActiveAllOrders.ts | 0 .../{ => hooks}/useNotificationLimitOrder.tsx | 3 +- .../LimitOrder/{ => hooks}/useSignOrder.ts | 0 .../{ => hooks}/useValidateInputError.tsx | 0 .../{ => hooks}/useWarningCreateOrder.tsx | 2 +- .../{ => hooks}/useWrapEthStatus.ts | 0 .../components/swapv2/LimitOrder/index.tsx | 2 +- .../components/SmartExit/ExpireSetting.tsx | 2 +- .../SmartExit/Metrics/TimeInput.tsx | 2 +- .../src/pages/PartnerSwap/index.tsx | 2 +- .../src/pages/SwapV3/Tabs/LimitTab.tsx | 2 +- 32 files changed, 1581 insertions(+), 1118 deletions(-) rename apps/kyberswap-interface/src/components/{swapv2/LimitOrder/ExpirePicker.tsx => DateTimePicker/index.tsx} (94%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => EditOrder}/EditOrderModal.tsx (98%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => Form}/ActionButtonLimitOrder.tsx (100%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => Form}/DeltaRate.tsx (97%) create mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx create mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx create mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx create mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx create mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderExecution.tsx create mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderFormState.ts delete mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/LimitOrderForm.tsx rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => hooks}/useCancellingOrders.ts (93%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => hooks}/useFetchActiveAllOrders.ts (100%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => hooks}/useNotificationLimitOrder.tsx (98%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => hooks}/useSignOrder.ts (100%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => hooks}/useValidateInputError.tsx (100%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => hooks}/useWarningCreateOrder.tsx (99%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => hooks}/useWrapEthStatus.ts (100%) diff --git a/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx b/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx index 5fae4c5e49..806e1cdba0 100644 --- a/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx +++ b/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx @@ -6,7 +6,7 @@ import SnippetPopup from 'components/Announcement/Popups/SnippetPopup' import TopRightPopup from 'components/Announcement/Popups/TopRightPopup' import { PopupType, PrivateAnnouncementType } from 'components/Announcement/type' import { ButtonEmpty } from 'components/Button' -import useNotificationLimitOrder from 'components/swapv2/LimitOrder/useNotificationLimitOrder' +import useNotificationLimitOrder from 'components/swapv2/LimitOrder/hooks/useNotificationLimitOrder' import { TIMES_IN_SECS } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ExpirePicker.tsx b/apps/kyberswap-interface/src/components/DateTimePicker/index.tsx similarity index 94% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/ExpirePicker.tsx rename to apps/kyberswap-interface/src/components/DateTimePicker/index.tsx index 1cfcf48d88..8e524e6c6e 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ExpirePicker.tsx +++ b/apps/kyberswap-interface/src/components/DateTimePicker/index.tsx @@ -7,8 +7,19 @@ import { ButtonOutlined, ButtonPrimary } from 'components/Button' import DatePicker from 'components/DatePicker' import Modal from 'components/Modal' import Select, { SelectProps } from 'components/Select' -import { MIN_TIME_MINUTES, getExpireOptions } from 'components/swapv2/LimitOrder/const' +import { TIMES_IN_SECS } from 'constants/index' import useTheme from 'hooks/useTheme' +import { formatTimeDuration } from 'utils/time' + +const MIN_TIME_MINUTES = 5 + +const DEFAULT_OPTIONS = [ + TIMES_IN_SECS.ONE_HOUR, + TIMES_IN_SECS.ONE_DAY, + 7 * TIMES_IN_SECS.ONE_DAY, + 30 * TIMES_IN_SECS.ONE_DAY, + 36500 * TIMES_IN_SECS.ONE_DAY, +].map(e => ({ value: e, label: formatTimeDuration(e) })) const HOURS = Array.from({ length: 24 }, (_, i) => ({ label: i, value: i })) const MINS = Array.from({ length: 60 }, (_, i) => ({ label: i, value: i })) @@ -131,7 +142,7 @@ export default function DateTimePicker({ Default Options - {(defaultOptions || getExpireOptions()).map(opt => ( + {(defaultOptions || DEFAULT_OPTIONS).map(opt => ( & { 'data-flip'?: boolean }) => ( + +) + +type Props = { + expire: number + expanded: boolean + customDateExpire: Date | undefined + displayTime: string + setExpanded: Dispatch> + toggleDatePicker: () => void + onChangeExpire: (val: Date | number) => void +} + +export default function LimitOrderExpirySection({ + expire, + expanded, + customDateExpire, + displayTime, + setExpanded, + toggleDatePicker, + onChangeExpire, +}: Props) { + const expireOptions: Array<{ label: string; value?: number; onSelect?: () => void }> = [ + ...getExpireOptions(), + { label: 'Custom', onSelect: toggleDatePicker }, + ] + + return ( +
+
+ + + Expires in + + +
setExpanded(e => !e)}> + {displayTime} + +
+
+ +
+
+ {expireOptions.map(item => { + return ( + { + if (item.onSelect) item.onSelect() + else if (item.value) onChangeExpire(item.value) + }} + data-active={customDateExpire ? item.label === 'Custom' : item.value === expire} + > + {item.label} + + ) + })} +
+
+
+ ) +} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx new file mode 100644 index 0000000000..f80f95db93 --- /dev/null +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx @@ -0,0 +1,315 @@ +import { Currency } from '@kyberswap/ks-sdk-core' +import { Trans } from '@lingui/macro' +import { forwardRef, memo, useImperativeHandle } from 'react' + +import { ButtonLight } from 'components/Button' +import DateTimePicker from 'components/DateTimePicker' +import { NetworkSelector } from 'components/NetworkSelector' +import ActionButtonLimitOrder from 'components/swapv2/LimitOrder/Form/ActionButtonLimitOrder' +import { useGetDeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/DeltaRate' +import LimitOrderExpirySection from 'components/swapv2/LimitOrder/Form/LimitOrderExpirySection' +import LimitOrderRateSection from 'components/swapv2/LimitOrder/Form/LimitOrderRateSection' +import LimitOrderTokenSection from 'components/swapv2/LimitOrder/Form/LimitOrderTokenSection' +import useLimitOrderExecution from 'components/swapv2/LimitOrder/Form/hooks/useLimitOrderExecution' +import useLimitOrderFormState from 'components/swapv2/LimitOrder/Form/hooks/useLimitOrderFormState' +import ConfirmOrderModal from 'components/swapv2/LimitOrder/Modals/ConfirmOrderModal' +import { EditOrderInfo, LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/type' +import { Z_INDEXS } from 'constants/styles' +import { NETWORKS_INFO } from 'hooks/useChainsConfig' +import { useChangeNetwork } from 'hooks/web3/useChangeNetwork' +import ErrorWarningPanel from 'pages/Bridge/ErrorWarning' +import { TransactionFlowState } from 'types/TransactionFlowState' +import { cn } from 'utils/cn' + +export const Label = ({ children, className, ...rest }: React.HTMLAttributes) => ( +
+ {children} +
+) + +type BaseProps = { + currencyIn: Currency | undefined + currencyOut: Currency | undefined + note?: string + flowState: TransactionFlowState + setFlowState: React.Dispatch> + zIndexToolTip?: number +} + +type CreateLimitOrderFormProps = BaseProps & { + mode?: 'create' + defaultInputAmount?: string + defaultOutputAmount?: string + defaultActiveMakingAmount?: string + defaultExpire?: Date + defaultRate?: RateInfo + orderInfo?: never + editOrderInfo?: never + useUrlParams?: boolean +} + +type EditLimitOrderFormProps = BaseProps & { + mode: 'edit' + defaultInputAmount: string + defaultOutputAmount: string + defaultActiveMakingAmount: string + defaultExpire: Date + defaultRate: RateInfo + orderInfo: LimitOrder + editOrderInfo: EditOrderInfo + useUrlParams?: never +} + +type Props = CreateLimitOrderFormProps | EditLimitOrderFormProps + +export type LimitOrderFormHandle = { + hasChangedOrderInfo: () => boolean +} +const LimitOrderForm = forwardRef(function LimitOrderForm( + { + currencyIn, + currencyOut, + mode = 'create', + defaultInputAmount = '', + defaultOutputAmount = '', + defaultActiveMakingAmount = '', + defaultExpire, + defaultRate = { rate: '', invertRate: '', invert: false }, + note = '', + orderInfo, + flowState, + setFlowState, + zIndexToolTip = Z_INDEXS.TOOL_TIP_ERROR_INPUT_SWAP_FORM, + editOrderInfo, + useUrlParams, + }, + ref, +) { + const { changeNetwork } = useChangeNetwork() + const isEdit = mode === 'edit' + const { + chainId, + walletChainId, + networkInfo, + searchParams, + inputAmount, + outputAmount, + rateInfo, + displayRate, + expire, + showDatePicker, + customDateExpire, + rotate, + expanded, + loadingTrade, + tradeInfo, + expiredAt, + displayTime, + setExpanded, + onSetInput, + onSetOutput, + onChangeRate, + onInvertRate, + handleInputSelect, + switchToWeth, + handleOutputSelect, + handleRotateClick, + toggleDatePicker, + onChangeExpire, + onResetForm, + setPriceRateMarket, + } = useLimitOrderFormState({ + currencyIn, + currencyOut, + defaultInputAmount, + defaultOutputAmount, + defaultExpire, + defaultRate, + isEdit, + useUrlParams, + }) + const deltaRate = useGetDeltaRateLimitOrder({ marketPrice: tradeInfo, rateInfo }) + const { + approval, + approvalSubmitted, + approveCallback, + checkingAllowance, + enoughAllowance, + estimateUSD, + handleMaxInput, + hasChangedOrderInfo, + hasInputError, + hidePreview, + inputError, + isNotFillAllInput, + isWrappingEth, + onSubmitCreateOrderWithTracking, + onWrapToken, + outPutError, + showApproveFlow, + showPreview, + showWrap, + trackingPriceSetOnBlur, + trackingTouchInput, + trackingTouchSelectToken, + warningMessage, + wrapInputError, + } = useLimitOrderExecution({ + currencyIn, + currencyOut, + defaultActiveMakingAmount, + defaultInputAmount, + defaultRate, + defaultExpire, + orderInfo, + setFlowState, + isEdit, + chainId, + networkName: networkInfo.name, + searchParams, + inputAmount, + outputAmount, + displayRate, + expiredAt, + displayTime, + rateInfo, + tradeInfo, + deltaRate, + onSetInput, + onResetForm, + switchToWeth, + }) + + useImperativeHandle(ref, () => ({ + hasChangedOrderInfo, + })) + + const styleTooltip = { maxWidth: '250px', zIndex: zIndexToolTip } + const actionButton = + chainId !== walletChainId ? ( + changeNetwork(chainId)}> + Switch to {NETWORKS_INFO[chainId].name} + + ) : ( + 0} + editOrderInfo={editOrderInfo} + /> + ) + + const renderConfirmModal = (showConfirmContent = false) => ( + + ) + + if (isEdit && flowState.showConfirm) + return ( + <> + {renderConfirmModal(true)} + {actionButton} + + ) + return ( + <> +
+ {useUrlParams ? : null} + + + + + + + {warningMessage.map((mess, i) => ( + + ))} + + {actionButton} +
+ + {renderConfirmModal()} + + + + ) +}) + +export default memo(LimitOrderForm) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx new file mode 100644 index 0000000000..3a5a1b8509 --- /dev/null +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx @@ -0,0 +1,91 @@ +import { Currency } from '@kyberswap/ks-sdk-core' +import { Trans } from '@lingui/macro' +import { Repeat } from 'react-feather' + +import CurrencyLogo from 'components/CurrencyLogo' +import NumericalInput from 'components/NumericalInput' +import { RowBetween } from 'components/Row' +import DeltaRate from 'components/swapv2/LimitOrder/Form/DeltaRate' +import { RateInfo } from 'components/swapv2/LimitOrder/type' +import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' +import { cn } from 'utils/cn' + +const InputWrapper = ({ children, className, ...rest }: React.HTMLAttributes) => ( +
+ {children} +
+) + +const Set2Market = ({ children, className, ...rest }: React.HTMLAttributes) => ( +
+ {children} +
+) + +type Props = { + currencyIn: Currency | undefined + currencyOut: Currency | undefined + displayRate: string + rateInfo: RateInfo + tradeInfo: BaseTradeInfo | undefined + onChangeRate: (value: string) => void + onInvertRate: (invert: boolean) => void + setPriceRateMarket: () => void + trackingTouchInput: () => void + trackingPriceSetOnBlur: () => void +} + +export default function LimitOrderRateSection({ + currencyIn, + currencyOut, + displayRate, + rateInfo, + tradeInfo, + onChangeRate, + onInvertRate, + setPriceRateMarket, + trackingTouchInput, + trackingPriceSetOnBlur, +}: Props) { + return ( + + +
+ + {tradeInfo && ( + + Market + + )} +
+
+ + {currencyIn && currencyOut && ( +
onInvertRate(!rateInfo.invert)}> + + + {rateInfo.invert ? currencyIn?.symbol : currencyOut?.symbol} + +
+ +
+
+ )} +
+
+
+ ) +} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx new file mode 100644 index 0000000000..679674897a --- /dev/null +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx @@ -0,0 +1,158 @@ +import { Currency } from '@kyberswap/ks-sdk-core' +import { Trans, t } from '@lingui/macro' +import { CSSProperties, ReactNode } from 'react' + +import ArrowRotate from 'components/ArrowRotate' +import CurrencyInputPanel from 'components/CurrencyInputPanel' +import { RowBetween } from 'components/Row' +import Tooltip from 'components/Tooltip' +import TradePrice from 'components/swapv2/LimitOrder/TradePrice' +import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' + +const Label = ({ children }: { children: ReactNode }) => ( +
{children}
+) + +type Props = { + chainId: number + currencyIn: Currency | undefined + currencyOut: Currency | undefined + inputAmount: string + outputAmount: string + inputError: string | ReactNode + outPutError: string | ReactNode + estimateUsdIn: string | undefined + estimateUsdOut: string | undefined + showApproveFlow: boolean + isEdit: boolean + rotate: boolean + tradeInfo: BaseTradeInfo | undefined + loadingTrade: boolean + styleTooltip: CSSProperties + onSetInput: (input: string) => void + onSetOutput: (output: string) => void + handleMaxInput: () => void + handleInputSelect: (currency: Currency) => void + handleOutputSelect: (currency: Currency) => void + handleRotateClick: () => void + trackingTouchInput: () => void + trackingTouchSelectToken: () => void +} + +export default function LimitOrderTokenSection({ + chainId, + currencyIn, + currencyOut, + inputAmount, + outputAmount, + inputError, + outPutError, + estimateUsdIn, + estimateUsdOut, + showApproveFlow, + isEdit, + rotate, + tradeInfo, + loadingTrade, + styleTooltip, + onSetInput, + onSetOutput, + handleMaxInput, + handleInputSelect, + handleOutputSelect, + handleRotateClick, + trackingTouchInput, + trackingTouchSelectToken, +}: Props) { + return ( + <> + + + You Sell + + } + positionLabel="in" + customChainId={chainId} + trackingSource="limit_order" + /> + + + + {currencyIn && currencyOut ? ( + + ) : ( +
+ )} + + + + + + You Buy + + } + positionLabel="in" + customChainId={chainId} + trackingSource="limit_order" + /> + + + ) +} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderExecution.tsx new file mode 100644 index 0000000000..95714f206e --- /dev/null +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderExecution.tsx @@ -0,0 +1,557 @@ +import { ChainId, Currency, CurrencyAmount, Token, TokenAmount, WETH } from '@kyberswap/ks-sdk-core' +import { t } from '@lingui/macro' +import JSBI from 'jsbi' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { useCreateOrderMutation, useGetLOConfigQuery, useGetTotalActiveMakingAmountQuery } from 'services/limitOrder' + +import { NotificationType } from 'components/Announcement/type' +import { getTipLinkAttribution } from 'components/TipLinkGeneratorModal/shared' +import type { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/DeltaRate' +import { SummaryNotifyOrderPlaced } from 'components/swapv2/LimitOrder/ListOrder/SummaryNotify' +import { + calcUsdPrices, + formatAmountOrder, + getErrorMessage, + getPayloadCreateOrder, + removeTrailingZero, +} from 'components/swapv2/LimitOrder/helpers' +import useSignOrder from 'components/swapv2/LimitOrder/hooks/useSignOrder' +import useValidateInputError from 'components/swapv2/LimitOrder/hooks/useValidateInputError' +import useWarningCreateOrder from 'components/swapv2/LimitOrder/hooks/useWarningCreateOrder' +import useWrapEthStatus from 'components/swapv2/LimitOrder/hooks/useWrapEthStatus' +import { CreateOrderParam, LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/type' +import { TRANSACTION_STATE_DEFAULT } from 'constants/index' +import { useTokenAllowance } from 'data/Allowances' +import { useActiveWeb3React } from 'hooks' +import { ApprovalState, useApproveCallback } from 'hooks/useApproveCallback' +import type { BaseTradeInfo } from 'hooks/useBaseTradeInfo' +import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' +import useWrapCallback from 'hooks/useWrapCallback' +import { useNotify } from 'state/application/hooks' +import { useLimitActionHandlers, useLimitState } from 'state/limit/hooks' +import { tryParseAmount } from 'state/swap/hooks' +import { useCurrencyBalance } from 'state/wallet/hooks' +import { TransactionFlowState } from 'types/TransactionFlowState' +import { getCookieValue } from 'utils' +import { subscribeNotificationOrderCancelled, subscribeNotificationOrderExpired } from 'utils/firebase' +import { maxAmountSpend } from 'utils/maxAmountSpend' + +type UseLimitOrderExecutionArgs = { + currencyIn: Currency | undefined + currencyOut: Currency | undefined + defaultActiveMakingAmount?: string + defaultInputAmount: string + defaultRate: RateInfo + defaultExpire?: Date + orderInfo?: LimitOrder + setFlowState: React.Dispatch> + isEdit: boolean + chainId: ChainId + networkName: string + searchParams: URLSearchParams + inputAmount: string + outputAmount: string + displayRate: string + expiredAt: number + displayTime: string + rateInfo: RateInfo + tradeInfo: BaseTradeInfo | undefined + deltaRate: DeltaRateLimitOrder + onSetInput: (input: string) => void + onResetForm: () => void + switchToWeth: () => void +} + +const getTokenAddress = (currency: Currency | undefined) => (currency?.isNative ? 'NATIVE' : currency?.wrapped?.address) + +export default function useLimitOrderExecution({ + currencyIn, + currencyOut, + defaultActiveMakingAmount = '', + defaultInputAmount, + defaultRate, + defaultExpire, + orderInfo, + setFlowState, + isEdit, + chainId, + networkName, + searchParams, + inputAmount, + outputAmount, + displayRate, + expiredAt, + displayTime, + rateInfo, + tradeInfo, + deltaRate, + onSetInput, + onResetForm, + switchToWeth, +}: UseLimitOrderExecutionArgs) { + const { account } = useActiveWeb3React() + const notify = useNotify() + const { trackingHandler } = useTracking() + const { ordersNeedCreated } = useLimitState() + const { removeOrderNeedCreated, setOrderEditing } = useLimitActionHandlers() + const [approvalSubmitted, setApprovalSubmitted] = useState(false) + + // Balances, allowance, and form readiness. + const { data: activeOrderMakingAmount = defaultActiveMakingAmount, refetch: getActiveMakingAmount } = + useGetTotalActiveMakingAmountQuery( + { chainId, tokenAddress: currencyIn?.wrapped.address ?? '', account: account ?? '' }, + { skip: !currencyIn || !account }, + ) + + const { execute: onWrap, inputError: wrapInputError } = useWrapCallback( + currencyIn, + currencyOut, + inputAmount, + true, + chainId, + ) + const showWrap = !!currencyIn?.isNative + + const { isWrappingEth, setTxHashWrapped } = useWrapEthStatus(switchToWeth) + + const parseInputAmount = tryParseAmount(inputAmount, currencyIn ?? undefined) + const { currentData } = useGetLOConfigQuery(chainId) + const limitOrderContract = currentData?.contract + + const currentAllowance = useTokenAllowance( + currencyIn as Token, + account ?? undefined, + limitOrderContract, + ) as CurrencyAmount + + const parsedActiveOrderMakingAmount = useMemo(() => { + try { + if (currencyIn && activeOrderMakingAmount) { + if (currencyIn.isNative) { + return TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(0)) + } + const value = TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(activeOrderMakingAmount)) + if (isEdit && orderInfo) { + const makingAmount = TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(orderInfo.makingAmount)) + return value.greaterThan(makingAmount) + ? value.subtract(makingAmount) + : TokenAmount.fromRawAmount(currencyIn, 0) + } + return value + } + } catch (error) {} + return undefined + }, [currencyIn, activeOrderMakingAmount, isEdit, orderInfo]) + + const balance = useCurrencyBalance(currencyIn, chainId) + const maxAmountInput = useMemo(() => { + return maxAmountSpend(balance) + }, [balance]) + + const handleMaxInput = useCallback(() => { + if (!maxAmountInput) return + try { + onSetInput(maxAmountInput.toExact()) + } catch (error) {} + }, [maxAmountInput, onSetInput]) + + const missingAllowance = useMemo(() => { + if (currentAllowance?.equalTo(0)) return true + if (currencyIn?.isNative || !parseInputAmount) return false + const allowanceSubtracted = parsedActiveOrderMakingAmount + ? currentAllowance?.subtract(parsedActiveOrderMakingAmount) + : undefined + if ( + !allowanceSubtracted || + allowanceSubtracted.greaterThan(parseInputAmount) || + allowanceSubtracted.equalTo(parseInputAmount) + ) + return false + return parseInputAmount.subtract(allowanceSubtracted) + }, [currencyIn?.isNative, currentAllowance, parseInputAmount, parsedActiveOrderMakingAmount]) + + const enoughAllowance = !missingAllowance + + const [approval, approveCallback] = useApproveCallback( + parseInputAmount, + limitOrderContract || undefined, + !enoughAllowance, + ) + + const { inputError, outPutError } = useValidateInputError({ + inputAmount, + outputAmount, + balance, + displayRate, + parsedActiveOrderMakingAmount: undefined, + currencyIn, + wrapInputError, + showWrap, + currencyOut, + }) + + const hasInputError = Boolean(inputError || outPutError) + const checkingAllowance = + !(currencyIn && parsedActiveOrderMakingAmount?.currency?.equals(currencyIn)) || + !(currencyIn && currentAllowance?.currency?.equals(currencyIn)) + + const isNotFillAllInput = [outputAmount, inputAmount, currencyIn, currencyOut, displayRate].some(e => !e) + + const estimateUSD = useMemo(() => { + return calcUsdPrices({ + inputAmount, + outputAmount, + priceUsdIn: tradeInfo?.priceUsdIn, + priceUsdOut: tradeInfo?.priceUsdOut, + currencyIn, + currencyOut, + }) + }, [inputAmount, outputAmount, tradeInfo, currencyIn, currencyOut]) + + const showApproveFlow = + !checkingAllowance && + !showWrap && + !isNotFillAllInput && + (approval === ApprovalState.NOT_APPROVED || + approval === ApprovalState.PENDING || + !enoughAllowance || + (approvalSubmitted && approval === ApprovalState.APPROVED)) + + const warningMessage = useWarningCreateOrder({ + estimateUSD: estimateUSD.rawInput, + currencyIn, + outputAmount, + displayRate, + deltaRate, + missingAllowance, + }) + + // User-facing actions. + const trackingTouchInput = useCallback(() => { + trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'touch enter amount box') + }, [trackingHandler]) + + const trackingPriceSetOnBlur = useCallback(() => { + if (!displayRate || !currencyIn || !currencyOut) return + trackingHandler(TRACKING_EVENT_TYPE.LO_PRICE_SET, { + side: rateInfo.invert ? 'buy' : 'sell', + limit_price: displayRate, + market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, + price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, + from_token: currencyIn.symbol, + to_token: currencyOut.symbol, + chain: networkName, + }) + }, [ + displayRate, + currencyIn, + currencyOut, + rateInfo.invert, + tradeInfo, + deltaRate.rawPercent, + networkName, + trackingHandler, + ]) + + const trackingTouchSelectToken = useCallback(() => { + trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'touch enter token box') + }, [trackingHandler]) + + const showPreview = () => { + if (!currencyIn || !currencyOut || !outputAmount || !inputAmount || !displayRate) return + setFlowState({ ...TRANSACTION_STATE_DEFAULT, showConfirm: true }) + if (!isEdit) { + trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_REVIEW_PLACE_ORDER, { + from_token: currencyIn.symbol, + to_token: currencyOut.symbol, + from_network: chainId, + trade_qty: inputAmount, + }) + trackingHandler(TRACKING_EVENT_TYPE.LO_REVIEW_OPENED, { + side: rateInfo.invert ? 'buy' : 'sell', + from_token: currencyIn.symbol, + from_token_address: getTokenAddress(currencyIn), + to_token: currencyOut.symbol, + to_token_address: getTokenAddress(currencyOut), + pair: `${currencyIn.symbol}/${currencyOut.symbol}`, + limit_price: displayRate, + amount_in: inputAmount, + amount_in_usd: estimateUSD.rawInput || undefined, + amount_out_estimated: outputAmount, + expiry: displayTime, + market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, + price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, + chain: networkName, + }) + } + } + + const hidePreview = useCallback(() => { + setFlowState(state => ({ ...state, showConfirm: false })) + }, [setFlowState]) + + const handleError = useCallback( + (error: any) => { + const errorMessage = getErrorMessage(error) + const isUserRejected = + errorMessage.toLowerCase().includes('user denied') || errorMessage.toLowerCase().includes('user rejected') + trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_FAILED, { + side: rateInfo.invert ? 'buy' : 'sell', + from_token: currencyIn?.symbol, + to_token: currencyOut?.symbol, + pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, + limit_price: displayRate, + amount_in: inputAmount, + error_type: isUserRejected ? 'user_rejected' : 'tx_failed', + error_message: errorMessage, + chain: networkName, + }) + setFlowState(state => ({ + ...state, + attemptingTxn: false, + errorMessage, + })) + }, + [setFlowState, trackingHandler, rateInfo.invert, currencyIn, currencyOut, displayRate, inputAmount, networkName], + ) + + const refreshActiveMakingAmount = useCallback(() => { + try { + getActiveMakingAmount() + } catch (error) {} + }, [getActiveMakingAmount]) + + const resetForm = useCallback(() => { + onResetForm() + refreshActiveMakingAmount() + }, [onResetForm, refreshActiveMakingAmount]) + + const onWrapToken = async () => { + try { + if (isNotFillAllInput || wrapInputError || isWrappingEth || hasInputError) return + const amount = formatAmountOrder(inputAmount) + const wethSymbol = WETH[chainId].symbol + const inSymbol = currencyIn?.symbol + setFlowState(state => ({ + ...state, + attemptingTxn: true, + showConfirm: true, + pendingText: t`Wrapping ${amount} ${inSymbol} to ${amount} ${wethSymbol}`, + })) + const hash = await onWrap?.() + if (hash) setTxHashWrapped(hash) + setFlowState(state => ({ ...state, showConfirm: false })) + } catch (error) { + handleError(error) + } + } + + const trackingPlaceOrder = useCallback( + (type: TRACKING_EVENT_TYPE, data = {}) => { + trackingHandler(type, { + from_token: currencyIn?.symbol, + to_token: currencyOut?.symbol, + from_network: networkName, + trade_qty: inputAmount, + ...data, + }) + }, + [currencyIn?.symbol, currencyOut?.symbol, inputAmount, networkName, trackingHandler], + ) + + const signOrder = useSignOrder(setFlowState) + const [submitOrder] = useCreateOrderMutation() + const onSubmitCreateOrder = useCallback( + async (params: CreateOrderParam) => { + try { + const { currencyIn, currencyOut, account, inputAmount, outputAmount, expiredAt } = params + if (!currencyIn || !currencyOut || !account || !inputAmount || !outputAmount || !expiredAt) { + throw new Error('wrong input') + } + + const refCode = getCookieValue('refCode') + const clientId = searchParams.get('clientId') + + const { signature, salt } = await signOrder({ ...params, referral: refCode }) + const payload = getPayloadCreateOrder(params) + setFlowState(state => ({ ...state, pendingText: t`Placing order` })) + const response = await submitOrder({ ...payload, salt, signature, referral: refCode, clientId }).unwrap() + setFlowState(state => ({ ...state, showConfirm: false })) + + notify( + { + type: NotificationType.SUCCESS, + title: t`Order Placed`, + summary: , + }, + 10000, + ) + resetForm() + return response?.id + } catch (error) { + handleError(error) + return + } + }, + [handleError, notify, resetForm, searchParams, setFlowState, signOrder, submitOrder], + ) + + const onSubmitCreateOrderWithTracking = async () => { + trackingPlaceOrder(TRACKING_EVENT_TYPE.LO_CLICK_PLACE_ORDER) + const order_id = await onSubmitCreateOrder({ + currencyIn, + currencyOut, + chainId, + account, + inputAmount, + outputAmount, + expiredAt, + nativeOutput: currencyOut?.isNative || false, + }) + if (!order_id) return + + trackingPlaceOrder(TRACKING_EVENT_TYPE.LO_PLACE_ORDER_SUCCESS, { order_id }) + trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_PLACED, { + side: rateInfo.invert ? 'buy' : 'sell', + from_token: currencyIn?.symbol, + from_token_address: getTokenAddress(currencyIn), + to_token: currencyOut?.symbol, + to_token_address: getTokenAddress(currencyOut), + pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, + limit_price: displayRate, + market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, + price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, + amount_in: inputAmount, + amount_in_usd: estimateUSD.rawInput || undefined, + amount_out_estimated: outputAmount, + expiry: displayTime, + chain: networkName, + order_id, + volume: estimateUSD.rawInput || undefined, + }) + + const tipLink = getTipLinkAttribution(searchParams) + if (tipLink) { + trackingHandler(TRACKING_EVENT_TYPE.TIP_LINK_TRADE, { + trade_type: 'limit_order', + trade_status: 'placed', + tip_charged: false, + ...tipLink, + input_token: currencyIn?.symbol, + output_token: currencyOut?.symbol, + input_token_address: getTokenAddress(currencyIn), + output_token_address: getTokenAddress(currencyOut), + pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, + chain: networkName, + chain_id: chainId, + volume: estimateUSD.rawInput || undefined, + order_id, + }) + } + } + + // External state synchronization. + useEffect(() => { + if (approval === ApprovalState.PENDING) { + setApprovalSubmitted(true) + } + if (approval === ApprovalState.NOT_APPROVED) { + setApprovalSubmitted(false) + } + }, [approval]) + + useEffect(() => { + if (!isEdit || !orderInfo?.id) return + setOrderEditing({ + orderId: orderInfo.id, + account, + chainId, + currencyIn, + currencyOut, + inputAmount, + outputAmount, + expiredAt, + nativeOutput: currencyOut?.isNative || false, + }) + }, [ + setOrderEditing, + account, + chainId, + currencyIn, + currencyOut, + inputAmount, + outputAmount, + expiredAt, + orderInfo?.id, + isEdit, + ]) + + const refSubmitCreateOrder = useRef(onSubmitCreateOrder) + refSubmitCreateOrder.current = onSubmitCreateOrder + + useEffect(() => { + if (!account) return + const unsubscribeCancelled = subscribeNotificationOrderCancelled(account, chainId, data => { + data?.orders.forEach(order => { + const findInfo = ordersNeedCreated.find(e => e.orderId === order.id) + if (!findInfo?.orderId) return + removeOrderNeedCreated(findInfo.orderId) + if (order.isSuccessful && !isEdit) { + refSubmitCreateOrder.current(findInfo) + } + }) + refreshActiveMakingAmount() + }) + const unsubscribeExpired = subscribeNotificationOrderExpired(account, chainId, refreshActiveMakingAmount) + return () => { + unsubscribeCancelled?.() + unsubscribeExpired?.() + } + }, [account, chainId, ordersNeedCreated, removeOrderNeedCreated, refreshActiveMakingAmount, isEdit]) + + const hasChangedOrderInfo = useCallback(() => { + return ( + isEdit && + !hasInputError && + (defaultInputAmount !== inputAmount || + defaultRate?.rate !== rateInfo.rate || + defaultExpire?.getTime() !== expiredAt) + ) + }, [ + defaultExpire, + defaultInputAmount, + defaultRate?.rate, + expiredAt, + hasInputError, + inputAmount, + isEdit, + rateInfo.rate, + ]) + + return { + approval, + approvalSubmitted, + approveCallback, + checkingAllowance, + enoughAllowance, + estimateUSD, + handleMaxInput, + hasChangedOrderInfo, + hasInputError, + hidePreview, + inputError, + isNotFillAllInput, + isWrappingEth, + onSubmitCreateOrderWithTracking, + onWrapToken, + outPutError, + showApproveFlow, + showPreview, + showWrap, + trackingPriceSetOnBlur, + trackingTouchInput, + trackingTouchSelectToken, + warningMessage, + wrapInputError, + } +} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderFormState.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderFormState.ts new file mode 100644 index 0000000000..d136bf9bb1 --- /dev/null +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderFormState.ts @@ -0,0 +1,342 @@ +import { ChainId, Currency } from '@kyberswap/ks-sdk-core' +import dayjs from 'dayjs' +import { useCallback, useEffect, useRef, useState } from 'react' +import { useSearchParams } from 'react-router-dom' + +import { DEFAULT_EXPIRED } from 'components/swapv2/LimitOrder/const' +import { + calcInvert, + calcOutput, + calcRate, + parseFraction, + removeTrailingZero, +} from 'components/swapv2/LimitOrder/helpers' +import { RateInfo } from 'components/swapv2/LimitOrder/type' +import { SUPPORTED_NETWORKS } from 'constants/networks' +import { useActiveWeb3React } from 'hooks' +import { useBaseTradeInfoLimitOrder } from 'hooks/useBaseTradeInfo' +import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' +import { useLimitActionHandlers, useLimitState } from 'state/limit/hooks' +import { formatTimeDuration } from 'utils/time' + +const useInputAmount = ({ + defaultInputAmount, + isEdit, +}: { + defaultInputAmount?: string + isEdit: boolean +}): [string, (v: string) => void] => { + const { inputAmount } = useLimitState() + const { setInputValue } = useLimitActionHandlers() + + const localState = useState(defaultInputAmount || '') + return isEdit ? localState : [inputAmount, setInputValue] +} + +export type LimitOrderFormStateArgs = { + currencyIn: Currency | undefined + currencyOut: Currency | undefined + defaultInputAmount?: string + defaultOutputAmount?: string + defaultExpire?: Date + defaultRate: RateInfo + isEdit: boolean + useUrlParams?: boolean +} + +export default function useLimitOrderFormState({ + currencyIn, + currencyOut, + defaultInputAmount = '', + defaultOutputAmount = '', + defaultExpire, + defaultRate, + isEdit, + useUrlParams, +}: LimitOrderFormStateArgs) { + const { chainId: walletChainId, networkInfo } = useActiveWeb3React() + const { trackingHandler } = useTracking() + const [searchParams, setSearchParams] = useSearchParams() + const urlChainId = searchParams.get('chainId') + const urlChainIdNumber = urlChainId ? +urlChainId : undefined + const chainId: ChainId = + useUrlParams && urlChainIdNumber && SUPPORTED_NETWORKS.includes(urlChainIdNumber) ? urlChainIdNumber : walletChainId + + const { + setCurrencyIn: updateCurrencyIn, + setCurrencyOut: updateCurrencyOut, + switchCurrency: rotateCurrency, + } = useLimitActionHandlers() + + const autoFillMarketPrice = useRef(false) + + const [inputAmount, setInputAmount] = useInputAmount({ defaultInputAmount, isEdit }) + const [outputAmount, setOutputAmount] = useState(defaultOutputAmount) + const [rateInfo, setRateInfo] = useState(defaultRate) + const [expire, setExpire] = useState(DEFAULT_EXPIRED) + const [showDatePicker, setShowDatePicker] = useState(false) + const [customDateExpire, setCustomDateExpire] = useState(defaultExpire) + const [rotate, setRotate] = useState(false) + const [expanded, setExpanded] = useState(false) + + const { loading: loadingTrade, tradeInfo } = useBaseTradeInfoLimitOrder(currencyIn, currencyOut, chainId) + + const displayRate = rateInfo.invert ? rateInfo.invertRate : rateInfo.rate + const expiredAt = customDateExpire?.getTime() || Date.now() + expire * 1000 + const displayTime = customDateExpire ? dayjs(customDateExpire).format('DD/MM/YYYY HH:mm') : formatTimeDuration(expire) + + const setCurrencyIn = useCallback( + (currency: Currency | undefined) => { + if (useUrlParams) { + const nextSearchParams = new URLSearchParams(searchParams) + nextSearchParams.set( + 'inputCurrency', + !currency ? '' : currency.isNative ? currency.symbol || '' : currency.wrapped.address, + ) + setSearchParams(nextSearchParams) + } else updateCurrencyIn(currency) + autoFillMarketPrice.current = false + }, + [useUrlParams, searchParams, setSearchParams, updateCurrencyIn], + ) + + const setCurrencyOut = useCallback( + (currency: Currency | undefined) => { + if (useUrlParams) { + const nextSearchParams = new URLSearchParams(searchParams) + nextSearchParams.set( + 'outputCurrency', + !currency ? '' : currency.isNative ? currency.symbol || '' : currency.wrapped.address, + ) + setSearchParams(nextSearchParams) + } else updateCurrencyOut(currency) + autoFillMarketPrice.current = false + }, + [useUrlParams, searchParams, setSearchParams, updateCurrencyOut], + ) + + const switchCurrency = useCallback(() => { + if (useUrlParams) { + const cin = searchParams.get('inputCurrency') || '' + const cout = searchParams.get('outputCurrency') || '' + const nextSearchParams = new URLSearchParams(searchParams) + nextSearchParams.set('outputCurrency', cin) + nextSearchParams.set('inputCurrency', cout) + setSearchParams(nextSearchParams) + } else rotateCurrency() + }, [useUrlParams, rotateCurrency, searchParams, setSearchParams]) + + const onSetInput = useCallback( + (input: string) => { + setInputAmount(input) + if (rateInfo.rate && currencyIn && currencyOut && input) { + setOutputAmount(calcOutput(input, rateInfo.rateFraction || rateInfo.rate, currencyOut.decimals)) + } + }, + [rateInfo, currencyIn, currencyOut, setInputAmount], + ) + + const onSetRate = useCallback( + (rate: string, invertRate: string) => { + if (!currencyIn || !currencyOut) return + const newRate: RateInfo = { ...rateInfo, rate, invertRate, rateFraction: parseFraction(rate) } + if (!rate && !invertRate) { + setRateInfo(newRate) + return + } + + if (rate) { + if (inputAmount) { + const output = calcOutput(inputAmount, newRate.rateFraction || rate, currencyOut.decimals) + setOutputAmount(output) + } + if (!invertRate) { + newRate.invertRate = calcInvert(rate) + } + setRateInfo(newRate) + return + } + if (invertRate) { + newRate.rate = calcInvert(invertRate) + newRate.rateFraction = parseFraction(invertRate).invert() + if (inputAmount) { + const output = calcOutput(inputAmount, newRate.rateFraction, currencyOut.decimals) + setOutputAmount(output) + } + setRateInfo(newRate) + return + } + }, + [currencyIn, currencyOut, inputAmount, rateInfo], + ) + + const onChangeRate = (val: string) => { + if (currencyOut) { + onSetRate(rateInfo.invert ? '' : val, rateInfo.invert ? val : '') + } + } + + const setPriceRateMarket = useCallback( + (autoFillInput = false) => { + try { + !autoFillInput && trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'set price') + if ((loadingTrade && !autoFillInput) || !tradeInfo) return + const marketRate = removeTrailingZero(tradeInfo.marketRate.toFixed(16)) ?? '' + onSetRate(marketRate, removeTrailingZero(tradeInfo.invertRate.toFixed(16)) ?? '') + if (!autoFillInput) { + trackingHandler(TRACKING_EVENT_TYPE.LO_PRICE_SET, { + side: rateInfo.invert ? 'buy' : 'sell', + limit_price: marketRate, + market_price: marketRate, + price_difference_pct: 0, + from_token: currencyIn?.symbol, + to_token: currencyOut?.symbol, + chain: networkInfo.name, + }) + } + } catch (error) {} + }, + [loadingTrade, trackingHandler, onSetRate, tradeInfo, rateInfo.invert, currencyIn, currencyOut, networkInfo.name], + ) + + const onSetOutput = (output: string) => { + if (inputAmount && parseFloat(inputAmount) !== 0 && currencyOut && output) { + const rate = calcRate(inputAmount, output, currencyOut.decimals) + setRateInfo({ + ...rateInfo, + rate, + rateFraction: parseFraction(rate), + invertRate: calcInvert(rate), + }) + } + setOutputAmount(output) + } + + const onInvertRate = (invert: boolean) => { + setRateInfo(rateInfo => ({ ...rateInfo, invert })) + } + + const handleInputSelect = useCallback( + (currency: Currency, resetRate = true) => { + if (currencyOut && currency?.equals(currencyOut)) { + switchCurrency() + return + } + setCurrencyIn(currency) + resetRate && setRateInfo(rateInfo => ({ ...rateInfo, invertRate: '', rate: '', rateFraction: undefined })) + }, + [currencyOut, setCurrencyIn, switchCurrency], + ) + + const switchToWeth = useCallback(() => { + if (!currencyIn) return + handleInputSelect(currencyIn.wrapped, false) + }, [currencyIn, handleInputSelect]) + + const handleOutputSelect = (currency: Currency) => { + if (currencyIn && currency?.equals(currencyIn)) { + switchCurrency() + return + } + setCurrencyOut(currency) + setRateInfo(rateInfo => ({ ...rateInfo, invertRate: '', rate: '', rateFraction: undefined })) + } + + const handleRotateClick = () => { + if (isEdit) return + trackingHandler(TRACKING_EVENT_TYPE.LO_SIDE_SELECTED, { + side: rateInfo.invert ? 'sell' : 'buy', + from_token: currencyOut?.symbol, + to_token: currencyIn?.symbol, + chain: networkInfo.name, + }) + setRotate(prev => !prev) + switchCurrency() + setInputAmount(outputAmount) + setOutputAmount(inputAmount) + if (currencyIn) { + const rate = calcRate(outputAmount, inputAmount, currencyIn.decimals) + setRateInfo({ + ...rateInfo, + rate, + rateFraction: parseFraction(rate), + invertRate: calcInvert(rate), + }) + } + } + + const toggleDatePicker = () => { + setShowDatePicker(showDatePicker => !showDatePicker) + } + + const onChangeExpire = (val: Date | number) => { + const previousExpiry = displayTime + if (typeof val === 'number') { + setExpire(val) + setCustomDateExpire(undefined) + trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'choose date') + trackingHandler(TRACKING_EVENT_TYPE.LO_EXPIRY_CHANGED, { + previous_expiry: previousExpiry, + new_expiry: formatTimeDuration(val), + custom_expiry_minutes: null, + chain: networkInfo.name, + }) + } else { + setCustomDateExpire(val) + trackingHandler(TRACKING_EVENT_TYPE.LO_EXPIRY_CHANGED, { + previous_expiry: previousExpiry, + new_expiry: 'custom', + custom_expiry_minutes: Math.round((val.getTime() - Date.now()) / 60000), + chain: networkInfo.name, + }) + } + } + + const onResetForm = useCallback(() => { + setInputAmount(defaultInputAmount) + setOutputAmount(defaultOutputAmount) + setRateInfo(defaultRate) + setExpire(DEFAULT_EXPIRED) + setCustomDateExpire(undefined) + }, [defaultInputAmount, defaultOutputAmount, defaultRate, setInputAmount]) + + useEffect(() => { + if (tradeInfo && !autoFillMarketPrice.current && !loadingTrade && !defaultRate?.rate) { + autoFillMarketPrice.current = true + setPriceRateMarket(true) + } + }, [tradeInfo, setPriceRateMarket, loadingTrade, defaultRate?.rate]) + + return { + chainId, + walletChainId, + networkInfo, + searchParams, + inputAmount, + outputAmount, + rateInfo, + displayRate, + expire, + showDatePicker, + customDateExpire, + rotate, + expanded, + loadingTrade, + tradeInfo, + expiredAt, + displayTime, + setExpanded, + onSetInput, + onSetOutput, + onChangeRate, + onInvertRate, + handleInputSelect, + switchToWeth, + handleOutputSelect, + handleRotateClick, + toggleDatePicker, + onChangeExpire, + onResetForm, + setPriceRateMarket, + } +} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/LimitOrderForm.tsx deleted file mode 100644 index 8115531fbd..0000000000 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/LimitOrderForm.tsx +++ /dev/null @@ -1,1088 +0,0 @@ -import { ChainId, Currency, CurrencyAmount, Token, TokenAmount, WETH } from '@kyberswap/ks-sdk-core' -import { Trans, t } from '@lingui/macro' -import dayjs from 'dayjs' -import JSBI from 'jsbi' -import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react' -import { Repeat } from 'react-feather' -import { useSearchParams } from 'react-router-dom' -import { useCreateOrderMutation, useGetLOConfigQuery, useGetTotalActiveMakingAmountQuery } from 'services/limitOrder' - -import { ReactComponent as DropdownSVG } from 'assets/svg/down.svg' -import { NotificationType } from 'components/Announcement/type' -import ArrowRotate from 'components/ArrowRotate' -import { ButtonLight } from 'components/Button' -import CurrencyInputPanel from 'components/CurrencyInputPanel' -import CurrencyLogo from 'components/CurrencyLogo' -import { NetworkSelector } from 'components/NetworkSelector' -import NumericalInput from 'components/NumericalInput' -import { RowBetween } from 'components/Row' -import { DefaultSlippageOption } from 'components/SlippageControl' -import { TextDashed } from 'components/Text' -import { getTipLinkAttribution } from 'components/TipLinkGeneratorModal/shared' -import Tooltip, { MouseoverTooltip } from 'components/Tooltip' -import ActionButtonLimitOrder from 'components/swapv2/LimitOrder/ActionButtonLimitOrder' -import DeltaRate, { useGetDeltaRateLimitOrder } from 'components/swapv2/LimitOrder/DeltaRate' -import ExpirePicker from 'components/swapv2/LimitOrder/ExpirePicker' -import { SummaryNotifyOrderPlaced } from 'components/swapv2/LimitOrder/ListOrder/SummaryNotify' -import ConfirmOrderModal from 'components/swapv2/LimitOrder/Modals/ConfirmOrderModal' -import TradePrice from 'components/swapv2/LimitOrder/TradePrice' -import { DEFAULT_EXPIRED, getExpireOptions } from 'components/swapv2/LimitOrder/const' -import { - calcInvert, - calcOutput, - calcRate, - calcUsdPrices, - formatAmountOrder, - getErrorMessage, - getPayloadCreateOrder, - parseFraction, - removeTrailingZero, -} from 'components/swapv2/LimitOrder/helpers' -import { CreateOrderParam, EditOrderInfo, LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/type' -import useSignOrder from 'components/swapv2/LimitOrder/useSignOrder' -import useValidateInputError from 'components/swapv2/LimitOrder/useValidateInputError' -import useWarningCreateOrder from 'components/swapv2/LimitOrder/useWarningCreateOrder' -import useWrapEthStatus from 'components/swapv2/LimitOrder/useWrapEthStatus' -import { TRANSACTION_STATE_DEFAULT } from 'constants/index' -import { SUPPORTED_NETWORKS } from 'constants/networks' -import { Z_INDEXS } from 'constants/styles' -import { useTokenAllowance } from 'data/Allowances' -import { useActiveWeb3React } from 'hooks' -import { ApprovalState, useApproveCallback } from 'hooks/useApproveCallback' -import { useBaseTradeInfoLimitOrder } from 'hooks/useBaseTradeInfo' -import { NETWORKS_INFO } from 'hooks/useChainsConfig' -import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' -import useWrapCallback from 'hooks/useWrapCallback' -import { useChangeNetwork } from 'hooks/web3/useChangeNetwork' -import ErrorWarningPanel from 'pages/Bridge/ErrorWarning' -import { useNotify } from 'state/application/hooks' -import { useLimitActionHandlers, useLimitState } from 'state/limit/hooks' -import { tryParseAmount } from 'state/swap/hooks' -import { useCurrencyBalance } from 'state/wallet/hooks' -import { TransactionFlowState } from 'types/TransactionFlowState' -import { getCookieValue } from 'utils' -import { cn } from 'utils/cn' -import { subscribeNotificationOrderCancelled, subscribeNotificationOrderExpired } from 'utils/firebase' -import { maxAmountSpend } from 'utils/maxAmountSpend' -import { formatTimeDuration } from 'utils/time' - -const DropdownIcon = ({ className, ...rest }: React.SVGProps & { 'data-flip'?: boolean }) => ( - -) - -export const Label = ({ children, className, ...rest }: React.HTMLAttributes) => ( -
- {children} -
-) - -const Set2Market = ({ children, className, ...rest }: React.HTMLAttributes) => ( - -) - -type Props = { - currencyIn: Currency | undefined - currencyOut: Currency | undefined - defaultInputAmount?: string - defaultOutputAmount?: string - defaultActiveMakingAmount?: string - defaultExpire?: Date - note?: string - orderInfo?: LimitOrder - flowState: TransactionFlowState - setFlowState: React.Dispatch> - zIndexToolTip?: number - defaultRate?: RateInfo - editOrderInfo?: EditOrderInfo - useUrlParams?: boolean -} - -const InputWrapper = ({ children, className, ...rest }: React.HTMLAttributes) => ( -
- {children} -
-) - -const useInputAmount = ({ - defaultInputAmount, - isEdit, -}: { - defaultInputAmount?: string - isEdit: boolean -}): [string, (v: string) => void] => { - const { inputAmount } = useLimitState() - const { setInputValue } = useLimitActionHandlers() - - const localState = useState(defaultInputAmount || '') - return isEdit ? localState : [inputAmount, setInputValue] -} - -export type LimitOrderFormHandle = { - hasChangedOrderInfo: () => boolean -} -const LimitOrderForm = forwardRef(function LimitOrderForm( - { - currencyIn, - currencyOut, - defaultInputAmount = '', - defaultOutputAmount = '', - defaultActiveMakingAmount = '', - defaultExpire, - defaultRate = { rate: '', invertRate: '', invert: false }, - note = '', - orderInfo, - flowState, - setFlowState, - zIndexToolTip = Z_INDEXS.TOOL_TIP_ERROR_INPUT_SWAP_FORM, - editOrderInfo, - useUrlParams, - }, - ref, -) { - const { changeNetwork } = useChangeNetwork() - const isEdit = editOrderInfo?.isEdit || false // else create - const { account, chainId: walletChainId, networkInfo } = useActiveWeb3React() - const [searchParams, setSearchParams] = useSearchParams() - const urlChainId = searchParams.get('chainId') - const chainId: ChainId = useUrlParams - ? urlChainId && SUPPORTED_NETWORKS.includes(+urlChainId) - ? +urlChainId - : walletChainId - : walletChainId - - const notify = useNotify() - const { trackingHandler } = useTracking() - - const { - setCurrencyIn: updateCurrencyIn, - setCurrencyOut: updateCurrencyOut, - switchCurrency: rotateCurrency, - removeOrderNeedCreated, - setOrderEditing, - } = useLimitActionHandlers() - - const setCurrencyIn = useCallback( - (currency: Currency | undefined) => { - if (useUrlParams) { - searchParams.set( - 'inputCurrency', - !currency ? '' : currency.isNative ? currency.symbol || '' : currency.wrapped.address, - ) - setSearchParams(searchParams) - } else updateCurrencyIn(currency) - autoFillMarketPrice.current = false - }, - [useUrlParams, searchParams, setSearchParams, updateCurrencyIn], - ) - - const setCurrencyOut = useCallback( - (currency: Currency | undefined) => { - if (useUrlParams) { - searchParams.set( - 'outputCurrency', - !currency ? '' : currency.isNative ? currency.symbol || '' : currency.wrapped.address, - ) - setSearchParams(searchParams) - } else updateCurrencyOut(currency) - autoFillMarketPrice.current = false - }, - [useUrlParams, searchParams, setSearchParams, updateCurrencyOut], - ) - - const switchCurrency = useCallback(() => { - if (useUrlParams) { - const cin = searchParams.get('inputCurrency') || '' - const cout = searchParams.get('outputCurrency') || '' - searchParams.set('outputCurrency', cin) - searchParams.set('inputCurrency', cout) - setSearchParams(searchParams) - } else rotateCurrency() - }, [useUrlParams, rotateCurrency, searchParams, setSearchParams]) - - const { ordersNeedCreated } = useLimitState() - - const [inputAmount, setInputAmount] = useInputAmount({ defaultInputAmount, isEdit }) - const [outputAmount, setOutputAmount] = useState(defaultOutputAmount) - - const [rateInfo, setRateInfo] = useState(defaultRate) - const displayRate = rateInfo.invert ? rateInfo.invertRate : rateInfo.rate - - const [expire, setExpire] = useState(DEFAULT_EXPIRED) - - const [showDatePicker, setShowDatePicker] = useState(false) - const [customDateExpire, setCustomDateExpire] = useState(defaultExpire) - - const [approvalSubmitted, setApprovalSubmitted] = useState(false) - - const { loading: loadingTrade, tradeInfo } = useBaseTradeInfoLimitOrder(currencyIn, currencyOut, chainId) - const deltaRate = useGetDeltaRateLimitOrder({ marketPrice: tradeInfo, rateInfo }) - - const { data: activeOrderMakingAmount = defaultActiveMakingAmount, refetch: getActiveMakingAmount } = - useGetTotalActiveMakingAmountQuery( - { chainId, tokenAddress: currencyIn?.wrapped.address ?? '', account: account ?? '' }, - { skip: !currencyIn || !account }, - ) - - const { execute: onWrap, inputError: wrapInputError } = useWrapCallback( - currencyIn, - currencyOut, - inputAmount, - true, - chainId, - ) - const showWrap = !!currencyIn?.isNative - - const onSetRate = useCallback( - (rate: string, invertRate: string) => { - if (!currencyIn || !currencyOut) return - const newRate: RateInfo = { ...rateInfo, rate, invertRate, rateFraction: parseFraction(rate) } - if (!rate && !invertRate) { - setRateInfo(newRate) - return - } - - if (rate) { - if (inputAmount) { - const output = calcOutput(inputAmount, newRate.rateFraction || rate, currencyOut.decimals) - setOutputAmount(output) - } - if (!invertRate) { - newRate.invertRate = calcInvert(rate) - } - setRateInfo(newRate) - return - } - if (invertRate) { - newRate.rate = calcInvert(invertRate) - newRate.rateFraction = parseFraction(invertRate).invert() - if (inputAmount) { - const output = calcOutput(inputAmount, newRate.rateFraction, currencyOut.decimals) - setOutputAmount(output) - } - setRateInfo(newRate) - return - } - }, - [currencyIn, currencyOut, inputAmount, rateInfo], - ) - - const onSetOutput = (output: string) => { - if (inputAmount && parseFloat(inputAmount) !== 0 && currencyOut && output) { - const rate = calcRate(inputAmount, output, currencyOut?.decimals) - setRateInfo({ - ...rateInfo, - rate, - rateFraction: parseFraction(rate), - invertRate: calcInvert(rate), - }) - } - setOutputAmount(output) - } - - const setPriceRateMarket = useCallback( - (autoFillInput = false) => { - try { - !autoFillInput && trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'set price') - if ((loadingTrade && !autoFillInput) || !tradeInfo) return - const marketRate = removeTrailingZero(tradeInfo.marketRate.toFixed(16)) ?? '' - onSetRate(marketRate, removeTrailingZero(tradeInfo.invertRate.toFixed(16)) ?? '') - if (!autoFillInput) { - trackingHandler(TRACKING_EVENT_TYPE.LO_PRICE_SET, { - side: rateInfo.invert ? 'buy' : 'sell', - limit_price: marketRate, - market_price: marketRate, - price_difference_pct: 0, - from_token: currencyIn?.symbol, - to_token: currencyOut?.symbol, - chain: networkInfo.name, - }) - } - } catch (error) {} - }, - [loadingTrade, trackingHandler, onSetRate, tradeInfo, rateInfo.invert, currencyIn, currencyOut, networkInfo.name], - ) - - const onChangeRate = (val: string) => { - if (currencyOut) { - onSetRate(rateInfo.invert ? '' : val, rateInfo.invert ? val : '') - } - } - - const onSetInput = useCallback( - (input: string) => { - setInputAmount(input) - if (rateInfo.rate && currencyIn && currencyOut && input) { - setOutputAmount(calcOutput(input, rateInfo.rateFraction || rateInfo.rate, currencyOut.decimals)) - } - }, - [rateInfo, currencyIn, currencyOut, setInputAmount], - ) - - const onInvertRate = (invert: boolean) => { - setRateInfo({ ...rateInfo, invert }) - } - - const handleInputSelect = useCallback( - (currency: Currency, resetRate = true) => { - if (currencyOut && currency?.equals(currencyOut)) { - switchCurrency() - return - } - setCurrencyIn(currency) - resetRate && setRateInfo(rateInfo => ({ ...rateInfo, invertRate: '', rate: '', rateFraction: undefined })) - }, - [currencyOut, setCurrencyIn, switchCurrency], - ) - - const switchToWeth = useCallback(() => { - handleInputSelect(currencyIn?.wrapped as Currency, false) - }, [currencyIn, handleInputSelect]) - - const { isWrappingEth, setTxHashWrapped } = useWrapEthStatus(switchToWeth) - - const handleOutputSelect = (currency: Currency) => { - if (currencyIn && currency?.equals(currencyIn)) { - switchCurrency() - return - } - setCurrencyOut(currency) - setRateInfo({ ...rateInfo, invertRate: '', rate: '', rateFraction: undefined }) - } - - const [rotate, setRotate] = useState(false) - const handleRotateClick = () => { - if (isEdit) return - trackingHandler(TRACKING_EVENT_TYPE.LO_SIDE_SELECTED, { - side: rateInfo.invert ? 'sell' : 'buy', - from_token: currencyOut?.symbol, - to_token: currencyIn?.symbol, - chain: networkInfo.name, - }) - setRotate(prev => !prev) - switchCurrency() - setInputAmount(outputAmount) - setOutputAmount(inputAmount) - if (currencyIn) { - const rate = calcRate(outputAmount, inputAmount, currencyIn?.decimals) - setRateInfo({ - ...rateInfo, - rate, - rateFraction: parseFraction(rate), - invertRate: calcInvert(rate), - }) - } - } - - const parseInputAmount = tryParseAmount(inputAmount, currencyIn ?? undefined) - const { currentData } = useGetLOConfigQuery(chainId) - const limitOrderContract = currentData?.contract - - const currentAllowance = useTokenAllowance( - currencyIn as Token, - account ?? undefined, - limitOrderContract, - ) as CurrencyAmount - - const parsedActiveOrderMakingAmount = useMemo(() => { - try { - if (currencyIn && activeOrderMakingAmount) { - if (currencyIn.isNative) { - return TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(0)) - } - const value = TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(activeOrderMakingAmount)) - if (isEdit && orderInfo) { - const makingAmount = TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(orderInfo.makingAmount)) - return value.greaterThan(makingAmount) - ? value.subtract(makingAmount) - : TokenAmount.fromRawAmount(currencyIn, 0) - } - return value - } - } catch (error) {} - return undefined - }, [currencyIn, activeOrderMakingAmount, isEdit, orderInfo]) - - const balance = useCurrencyBalance(currencyIn, chainId) - const maxAmountInput = useMemo(() => { - return maxAmountSpend(balance) - }, [balance]) - - const handleMaxInput = useCallback(() => { - if (!maxAmountInput) return - try { - onSetInput(maxAmountInput.toExact()) - } catch (error) {} - }, [maxAmountInput, onSetInput]) - - const missingAllowance = useMemo(() => { - if (currentAllowance?.equalTo(0)) return true - if (currencyIn?.isNative || !parseInputAmount) return false - const allowanceSubtracted = parsedActiveOrderMakingAmount - ? currentAllowance?.subtract(parsedActiveOrderMakingAmount) - : undefined - if ( - !allowanceSubtracted || - allowanceSubtracted.greaterThan(parseInputAmount) || - allowanceSubtracted.equalTo(parseInputAmount) - ) - return false - return parseInputAmount.subtract(allowanceSubtracted) - }, [currencyIn?.isNative, currentAllowance, parseInputAmount, parsedActiveOrderMakingAmount]) - - const enoughAllowance = !Boolean(missingAllowance) - - const [approval, approveCallback] = useApproveCallback( - parseInputAmount, - limitOrderContract || undefined, - !enoughAllowance, - ) - - const { inputError, outPutError } = useValidateInputError({ - inputAmount, - outputAmount, - balance, - displayRate, - parsedActiveOrderMakingAmount: undefined, - currencyIn, - wrapInputError, - showWrap, - currencyOut, - }) - - const hasInputError = Boolean(inputError || outPutError) - const checkingAllowance = - !(currencyIn && parsedActiveOrderMakingAmount?.currency?.equals(currencyIn)) || - !(currencyIn && currentAllowance?.currency?.equals(currencyIn)) - - const isNotFillAllInput = [outputAmount, inputAmount, currencyIn, currencyOut, displayRate].some(e => !e) - - const expiredAt = customDateExpire?.getTime() || Date.now() + expire * 1000 - - const displayTime = customDateExpire ? dayjs(customDateExpire).format('DD/MM/YYYY HH:mm') : formatTimeDuration(expire) - - const getTokenAddress = (currency: Currency | undefined) => - currency?.isNative ? 'NATIVE' : currency?.wrapped?.address - - const showPreview = () => { - if (!currencyIn || !currencyOut || !outputAmount || !inputAmount || !displayRate) return - setFlowState({ ...TRANSACTION_STATE_DEFAULT, showConfirm: true }) - if (!isEdit) { - trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_REVIEW_PLACE_ORDER, { - from_token: currencyIn.symbol, - to_token: currencyOut.symbol, - from_network: chainId, - trade_qty: inputAmount, - }) - trackingHandler(TRACKING_EVENT_TYPE.LO_REVIEW_OPENED, { - side: rateInfo.invert ? 'buy' : 'sell', - from_token: currencyIn.symbol, - from_token_address: getTokenAddress(currencyIn), - to_token: currencyOut.symbol, - to_token_address: getTokenAddress(currencyOut), - pair: `${currencyIn.symbol}/${currencyOut.symbol}`, - limit_price: displayRate, - amount_in: inputAmount, - amount_in_usd: estimateUSD.rawInput || undefined, - amount_out_estimated: outputAmount, - expiry: displayTime, - market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, - price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, - chain: networkInfo.name, - }) - } - } - - const hidePreview = useCallback(() => { - setFlowState(state => ({ ...state, showConfirm: false })) - }, [setFlowState]) - - const toggleDatePicker = () => { - setShowDatePicker(!showDatePicker) - } - - const onChangeExpire = (val: Date | number) => { - const previousExpiry = displayTime - if (typeof val === 'number') { - setExpire(val) - setCustomDateExpire(undefined) - trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'choose date') - trackingHandler(TRACKING_EVENT_TYPE.LO_EXPIRY_CHANGED, { - previous_expiry: previousExpiry, - new_expiry: formatTimeDuration(val), - custom_expiry_minutes: null, - chain: networkInfo.name, - }) - } else { - setCustomDateExpire(val) - trackingHandler(TRACKING_EVENT_TYPE.LO_EXPIRY_CHANGED, { - previous_expiry: previousExpiry, - new_expiry: 'custom', - custom_expiry_minutes: Math.round((val.getTime() - Date.now()) / 60000), - chain: networkInfo.name, - }) - } - } - - const onResetForm = () => { - setInputAmount(defaultInputAmount) - setOutputAmount(defaultOutputAmount) - setRateInfo(defaultRate) - setExpire(DEFAULT_EXPIRED) - setCustomDateExpire(undefined) - refreshActiveMakingAmount() - } - - const handleError = useCallback( - (error: any) => { - const errorMessage = getErrorMessage(error) - const isUserRejected = - errorMessage.toLowerCase().includes('user denied') || errorMessage.toLowerCase().includes('user rejected') - trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_FAILED, { - side: rateInfo.invert ? 'buy' : 'sell', - from_token: currencyIn?.symbol, - to_token: currencyOut?.symbol, - pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, - limit_price: displayRate, - amount_in: inputAmount, - error_type: isUserRejected ? 'user_rejected' : 'tx_failed', - error_message: errorMessage, - chain: networkInfo.name, - }) - setFlowState(state => ({ - ...state, - attemptingTxn: false, - errorMessage, - })) - }, - [ - setFlowState, - trackingHandler, - rateInfo.invert, - currencyIn, - currencyOut, - displayRate, - inputAmount, - networkInfo.name, - ], - ) - - const signOrder = useSignOrder(setFlowState) - - const [submitOrder] = useCreateOrderMutation() - const onSubmitCreateOrder = async (params: CreateOrderParam) => { - try { - const { currencyIn, currencyOut, account, inputAmount, outputAmount, expiredAt } = params - if (!currencyIn || !currencyOut || !account || !inputAmount || !outputAmount || !expiredAt) { - throw new Error('wrong input') - } - - const refCode = getCookieValue('refCode') - const clientId = searchParams.get('clientId') - - const { signature, salt } = await signOrder({ ...params, referral: refCode }) - const payload = getPayloadCreateOrder(params) - setFlowState(state => ({ ...state, pendingText: t`Placing order` })) - const response = await submitOrder({ ...payload, salt, signature, referral: refCode, clientId }).unwrap() - setFlowState(state => ({ ...state, showConfirm: false })) - - notify( - { - type: NotificationType.SUCCESS, - title: t`Order Placed`, - summary: , - }, - 10000, - ) - onResetForm() - return response?.id - } catch (error) { - handleError(error) - return - } - } - - const onWrapToken = async () => { - try { - if (isNotFillAllInput || wrapInputError || isWrappingEth || hasInputError) return - const amount = formatAmountOrder(inputAmount) - const wethSymbol = WETH[chainId].symbol - const inSymbol = currencyIn?.symbol - setFlowState(state => ({ - ...state, - attemptingTxn: true, - showConfirm: true, - pendingText: t`Wrapping ${amount} ${inSymbol} to ${amount} ${wethSymbol}`, - })) - const hash = await onWrap?.() - hash && setTxHashWrapped(hash) - setFlowState(state => ({ ...state, showConfirm: false })) - } catch (error) { - handleError(error) - } - } - - useEffect(() => { - if (approval === ApprovalState.PENDING) { - setApprovalSubmitted(true) - } - if (approval === ApprovalState.NOT_APPROVED) { - setApprovalSubmitted(false) - } - }, [approval, approvalSubmitted]) - - const refreshActiveMakingAmount = useCallback(() => { - try { - getActiveMakingAmount() - } catch (error) {} - }, [getActiveMakingAmount]) - - useEffect(() => { - if (!isEdit || !orderInfo?.id) return - setOrderEditing({ - orderId: orderInfo.id, - account, - chainId, - currencyIn, - currencyOut, - inputAmount, - outputAmount, - expiredAt, - nativeOutput: currencyOut?.isNative || false, - }) - }, [ - setOrderEditing, - account, - chainId, - currencyIn, - currencyOut, - inputAmount, - outputAmount, - expiredAt, - orderInfo?.id, - isEdit, - ]) - - // use ref to prevent too many api call when firebase update status - const refSubmitCreateOrder = useRef(onSubmitCreateOrder) - refSubmitCreateOrder.current = onSubmitCreateOrder - const [expanded, setExpanded] = useState(false) - - useEffect(() => { - if (!account) return - // call when cancel expired/cancelled - const unsubscribeCancelled = subscribeNotificationOrderCancelled(account, chainId, data => { - data?.orders.forEach(order => { - const findInfo = ordersNeedCreated.find(e => e.orderId === order.id) - if (!findInfo?.orderId) return - removeOrderNeedCreated(findInfo.orderId) - // when cancel order success => create a new order - if (order.isSuccessful && !isEdit) { - refSubmitCreateOrder.current(findInfo) - } - }) - refreshActiveMakingAmount() - }) - const unsubscribeExpired = subscribeNotificationOrderExpired(account, chainId, refreshActiveMakingAmount) - return () => { - unsubscribeCancelled?.() - unsubscribeExpired?.() - } - }, [account, chainId, ordersNeedCreated, removeOrderNeedCreated, refreshActiveMakingAmount, isEdit]) - - const autoFillMarketPrice = useRef(false) - useEffect(() => { - if (tradeInfo && !autoFillMarketPrice.current && !loadingTrade && !defaultRate?.rate) { - autoFillMarketPrice.current = true - setPriceRateMarket(true) - } - }, [tradeInfo, setPriceRateMarket, loadingTrade, defaultRate?.rate]) - - const trackingTouchInput = useCallback(() => { - trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'touch enter amount box') - }, [trackingHandler]) - - const trackingPriceSetOnBlur = useCallback(() => { - if (!displayRate || !currencyIn || !currencyOut) return - trackingHandler(TRACKING_EVENT_TYPE.LO_PRICE_SET, { - side: rateInfo.invert ? 'buy' : 'sell', - limit_price: displayRate, - market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, - price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, - from_token: currencyIn.symbol, - to_token: currencyOut.symbol, - chain: networkInfo.name, - }) - }, [ - displayRate, - currencyIn, - currencyOut, - rateInfo.invert, - tradeInfo, - deltaRate.rawPercent, - networkInfo.name, - trackingHandler, - ]) - - const trackingTouchSelectToken = useCallback(() => { - trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'touch enter token box') - }, [trackingHandler]) - - const trackingPlaceOrder = (type: TRACKING_EVENT_TYPE, data = {}) => { - trackingHandler(type, { - from_token: currencyIn?.symbol, - to_token: currencyOut?.symbol, - from_network: networkInfo.name, - trade_qty: inputAmount, - ...data, - }) - } - - const onSubmitCreateOrderWithTracking = async () => { - trackingPlaceOrder(TRACKING_EVENT_TYPE.LO_CLICK_PLACE_ORDER) - const order_id = await onSubmitCreateOrder({ - currencyIn, - currencyOut, - chainId, - account, - inputAmount, - outputAmount, - expiredAt, - nativeOutput: currencyOut?.isNative || false, - }) - if (order_id) { - trackingPlaceOrder(TRACKING_EVENT_TYPE.LO_PLACE_ORDER_SUCCESS, { order_id }) - trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_PLACED, { - side: rateInfo.invert ? 'buy' : 'sell', - from_token: currencyIn?.symbol, - from_token_address: getTokenAddress(currencyIn), - to_token: currencyOut?.symbol, - to_token_address: getTokenAddress(currencyOut), - pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, - limit_price: displayRate, - market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, - price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, - amount_in: inputAmount, - amount_in_usd: estimateUSD.rawInput || undefined, - amount_out_estimated: outputAmount, - expiry: displayTime, - chain: networkInfo.name, - order_id, - volume: estimateUSD.rawInput || undefined, - }) - - // Tip is not charged on limit orders, so this attributes referral volume only - // (tracked at placement — `Limit Order Filled` fires off-page with no tip context). - const tipLink = getTipLinkAttribution(searchParams) - if (tipLink) { - trackingHandler(TRACKING_EVENT_TYPE.TIP_LINK_TRADE, { - trade_type: 'limit_order', - trade_status: 'placed', - tip_charged: false, - ...tipLink, - input_token: currencyIn?.symbol, - output_token: currencyOut?.symbol, - input_token_address: getTokenAddress(currencyIn), - output_token_address: getTokenAddress(currencyOut), - pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, - chain: networkInfo.name, - chain_id: chainId, - volume: estimateUSD.rawInput || undefined, - order_id, - }) - } - } - } - - const styleTooltip = { maxWidth: '250px', zIndex: zIndexToolTip } - const estimateUSD = useMemo(() => { - return calcUsdPrices({ - inputAmount, - outputAmount, - priceUsdIn: tradeInfo?.priceUsdIn, - priceUsdOut: tradeInfo?.priceUsdOut, - currencyIn, - currencyOut, - }) - }, [inputAmount, outputAmount, tradeInfo, currencyIn, currencyOut]) - - const showApproveFlow = - !checkingAllowance && - !showWrap && - !isNotFillAllInput && - (approval === ApprovalState.NOT_APPROVED || - approval === ApprovalState.PENDING || - !enoughAllowance || - (approvalSubmitted && approval === ApprovalState.APPROVED)) - - const warningMessage = useWarningCreateOrder({ - estimateUSD: estimateUSD.rawInput, - currencyIn, - outputAmount, - displayRate, - deltaRate, - missingAllowance, - }) - - useImperativeHandle(ref, () => ({ - hasChangedOrderInfo() { - return ( - isEdit && - !hasInputError && - (defaultInputAmount !== inputAmount || - defaultRate?.rate !== rateInfo.rate || - defaultExpire?.getTime() !== expiredAt) - ) - }, - })) - - const renderActionBtn = () => - chainId !== walletChainId ? ( - changeNetwork(chainId)}> - Switch to {NETWORKS_INFO[chainId].name} - - ) : ( - 0, - editOrderInfo, - }} - /> - ) - const renderConfirmModal = (showConfirmContent = false) => ( - - ) - - if (isEdit && flowState.showConfirm) - return ( - <> - {renderConfirmModal(true)} - {renderActionBtn()} - - ) - return ( - <> -
- {useUrlParams ? : null} - - - You Sell - - } - positionLabel="in" - customChainId={chainId} - trackingSource="limit_order" - /> - - - - -
- - {tradeInfo && ( - setPriceRateMarket()}> - Market - - )} -
-
- - {currencyIn && currencyOut && ( -
onInvertRate(!rateInfo.invert)}> - - - {rateInfo.invert ? currencyIn?.symbol : currencyOut?.symbol} - -
- -
-
- )} -
-
-
- - - {currencyIn && currencyOut ? ( - - ) : ( -
- )} - - - - - - You Buy - - } - positionLabel="in" - customChainId={chainId} - trackingSource="limit_order" - /> - - -
-
- - - Expires in - - -
setExpanded(e => !e)}> - {displayTime} - -
-
- -
-
- {[...getExpireOptions(), { label: 'Custom', onSelect: toggleDatePicker }].map((item: any) => { - return ( - { - if (item.label === 'Custom') item.onSelect() - else onChangeExpire(item.value) - }} - data-active={customDateExpire ? item.label === 'Custom' : item.value === expire} - > - {item.label} - - ) - })} -
-
-
- - {warningMessage.map((mess, i) => ( - - ))} - - {renderActionBtn()} -
- - {renderConfirmModal()} - - - - ) -}) - -export default memo(LimitOrderForm) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx index ff70523efa..7a9d796cd3 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx @@ -13,7 +13,7 @@ import Pagination from 'components/Pagination' import Row from 'components/Row' import SearchInput from 'components/SearchInput' import Select from 'components/Select' -import EditOrderModal from 'components/swapv2/LimitOrder/EditOrderModal' +import EditOrderModal from 'components/swapv2/LimitOrder/EditOrder/EditOrderModal' import OrderItem from 'components/swapv2/LimitOrder/ListOrder/OrderItem' import TabSelector from 'components/swapv2/LimitOrder/ListOrder/TabSelector' import TableHeader from 'components/swapv2/LimitOrder/ListOrder/TableHeader' @@ -27,8 +27,8 @@ import { getPayloadTracking, isActiveStatus, } from 'components/swapv2/LimitOrder/helpers' +import useCancellingOrders from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' -import useCancellingOrders from 'components/swapv2/LimitOrder/useCancellingOrders' import { EMPTY_ARRAY, RTK_QUERY_TAGS, TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { useInvalidateTagLimitOrder } from 'hooks/useInvalidateTags' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx index 09ee2ee809..1e9530d788 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx @@ -11,14 +11,14 @@ import { import { wagmiConfig } from 'components/Web3Provider' import { CancelStatus } from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' import { formatAmountOrder, getErrorMessage, getPayloadTracking } from 'components/swapv2/LimitOrder/helpers' +import useCancellingOrders from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' +import useSignOrder from 'components/swapv2/LimitOrder/hooks/useSignOrder' import { CancelOrderFunction, CancelOrderResponse, CancelOrderType, LimitOrder, } from 'components/swapv2/LimitOrder/type' -import useCancellingOrders from 'components/swapv2/LimitOrder/useCancellingOrders' -import useSignOrder from 'components/swapv2/LimitOrder/useSignOrder' import { LIMIT_ORDER_ABI } from 'constants/abis' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React, useWeb3React } from 'hooks' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx index 9261afb7c4..cbc337b2bc 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx @@ -9,8 +9,10 @@ import CancelButtons from 'components/swapv2/LimitOrder/Modals/CancelButtons' import CancelStatusCountDown from 'components/swapv2/LimitOrder/Modals/CancelStatusCountDown' import { Container, Header, Label, ListInfo, Note, Rate, Value } from 'components/swapv2/LimitOrder/Modals/styled' import { calcPercentFilledOrder, formatAmountOrder } from 'components/swapv2/LimitOrder/helpers' +import useAllActiveOrders, { + useIsSupportSoftCancelOrder, +} from 'components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders' import { CancelOrderFunction, CancelOrderType, LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' -import useAllActiveOrders, { useIsSupportSoftCancelOrder } from 'components/swapv2/LimitOrder/useFetchActiveAllOrders' import { NativeCurrencies } from 'constants/tokens' import { useCurrencyV2 } from 'hooks/Tokens' import { useBaseTradeInfoLimitOrder } from 'hooks/useBaseTradeInfo' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/const.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/const.ts index ecbadbe8c8..2a63f02e91 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/const.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/const.ts @@ -8,11 +8,8 @@ import { LimitOrderStatus } from './type' export const DEFAULT_EXPIRED = 36500 * TIMES_IN_SECS.ONE_DAY -export const MIN_TIME_MINUTES = 5 - export const getExpireOptions = () => [ - // MIN_TIME_MINUTES * TIMES_IN_SECS.ONE_MIN, // 10 * TIMES_IN_SECS.ONE_MIN, // 30 * TIMES_IN_SECS.ONE_MIN, TIMES_IN_SECS.ONE_HOUR, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/useCancellingOrders.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts similarity index 93% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/useCancellingOrders.ts rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts index 0066fe8c90..51e27bcedf 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/useCancellingOrders.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts @@ -1,12 +1,11 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { useGetLOConfigQuery } from 'services/limitOrder' +import { isActiveStatus } from 'components/swapv2/LimitOrder/helpers' +import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' import { useActiveWeb3React } from 'hooks' import { OrderNonces, subscribeCancellingOrders } from 'utils/firebase' -import { isActiveStatus } from './helpers' -import { LimitOrder, LimitOrderStatus } from './type' - export type CancellingOrderInfo = { loading: boolean cancellingOrdersIds: number[] diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/useFetchActiveAllOrders.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/useFetchActiveAllOrders.ts rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx similarity index 98% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx index e6893c3b6d..52db0a87a7 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx @@ -3,6 +3,7 @@ import { useCallback, useEffect, useRef } from 'react' import { useAckNotificationOrderMutation } from 'services/limitOrder' import { NotificationType } from 'components/Announcement/type' +import SummaryNotify from 'components/swapv2/LimitOrder/ListOrder/SummaryNotify' import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' import { APP_PATHS } from 'constants/index' import { useActiveWeb3React } from 'hooks' @@ -17,8 +18,6 @@ import { } from 'utils/firebase' import { getTransactionStatus } from 'utils/transaction' -import SummaryNotify from './ListOrder/SummaryNotify' - const isTransactionFailed = (txHash: string, transactions: GroupedTxsByHash | undefined) => { const transactionInfo = findTx(transactions, txHash) return transactionInfo ? getTransactionStatus(transactionInfo).error : false diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/useSignOrder.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/useSignOrder.ts rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/useValidateInputError.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/useValidateInputError.tsx rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx similarity index 99% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx index 98568625b7..3ce7babaf4 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx @@ -2,7 +2,7 @@ import { Currency, CurrencyAmount } from '@kyberswap/ks-sdk-core' import { Trans } from '@lingui/macro' import { useMemo } from 'react' -import { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/DeltaRate' +import { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/DeltaRate' import { BETTER_PRICE_DIFF_THRESHOLD, USD_THRESHOLD, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/useWrapEthStatus.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWrapEthStatus.ts similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/useWrapEthStatus.ts rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWrapEthStatus.ts diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/index.tsx index 0da03ea893..6464bc1bc7 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/index.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/index.tsx @@ -1,6 +1,6 @@ import { memo, useState } from 'react' -import LimitOrderForm from 'components/swapv2/LimitOrder/LimitOrderForm' +import LimitOrderForm from 'components/swapv2/LimitOrder/Form/LimitOrderForm' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useLimitState } from 'state/limit/hooks' import { TransactionFlowState } from 'types/TransactionFlowState' diff --git a/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/ExpireSetting.tsx b/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/ExpireSetting.tsx index bc383020eb..6f807a6396 100644 --- a/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/ExpireSetting.tsx +++ b/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/ExpireSetting.tsx @@ -3,9 +3,9 @@ import dayjs from 'dayjs' import { useMemo, useRef, useState } from 'react' import { Sliders } from 'react-feather' +import DateTimePicker from 'components/DateTimePicker' import { TextDashed } from 'components/Text' import { MouseoverTooltip } from 'components/Tooltip' -import DateTimePicker from 'components/swapv2/LimitOrder/ExpirePicker' import { TIMES_IN_SECS } from 'constants/index' import { useOnClickOutside } from 'hooks/useOnClickOutside' import { EXPIRE_TIME_PRESETS, FOREVER_EXPIRE_TIME } from 'pages/Earns/components/SmartExit/constants' diff --git a/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/Metrics/TimeInput.tsx b/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/Metrics/TimeInput.tsx index 878dde6a41..d956b4466e 100644 --- a/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/Metrics/TimeInput.tsx +++ b/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/Metrics/TimeInput.tsx @@ -3,7 +3,7 @@ import dayjs from 'dayjs' import { useMemo, useState } from 'react' import { Calendar } from 'react-feather' -import DateTimePicker from 'components/swapv2/LimitOrder/ExpirePicker' +import DateTimePicker from 'components/DateTimePicker' import useTheme from 'hooks/useTheme' import { DEFAULT_TIME_OPTIONS } from 'pages/Earns/components/SmartExit/ExpireSetting' import { HighlightWrapper } from 'pages/Earns/components/SmartExit/GuidedHighlight' diff --git a/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx b/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx index 7a3c116b98..6036cf4c44 100644 --- a/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx +++ b/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx @@ -9,7 +9,7 @@ import Banner from 'components/Banner' import SwapForm, { SwapFormProps } from 'components/SwapForm' import { SwitchLocaleLink } from 'components/SwitchLocaleLink' import { DEFAULT_TIP, TIP_LINK_CLIENT_ID, isCreatorNameValid } from 'components/TipLinkGeneratorModal/shared' -import LimitOrderForm from 'components/swapv2/LimitOrder/LimitOrderForm' +import LimitOrderForm from 'components/swapv2/LimitOrder/Form/LimitOrderForm' import ListLimitOrder from 'components/swapv2/LimitOrder/ListLimitOrder' import LiquiditySourcesPanel from 'components/swapv2/LiquiditySourcesPanel' import SettingsPanel from 'components/swapv2/SwapSettingsPanel' diff --git a/apps/kyberswap-interface/src/pages/SwapV3/Tabs/LimitTab.tsx b/apps/kyberswap-interface/src/pages/SwapV3/Tabs/LimitTab.tsx index cdc65535d5..e9a465186c 100644 --- a/apps/kyberswap-interface/src/pages/SwapV3/Tabs/LimitTab.tsx +++ b/apps/kyberswap-interface/src/pages/SwapV3/Tabs/LimitTab.tsx @@ -46,7 +46,7 @@ export default function LimitTab({ onClick, active, customChainId }: Props) { Limit Order{' '} {!!numberOfActiveOrders && ( You have {numberOfActiveOrders} active orders.}> - + {numberOfActiveOrders} From a3e2dba3a3bab87a15969d286da194ba23ec28d6 Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Wed, 17 Jun 2026 16:10:38 +0700 Subject: [PATCH 04/52] First look new UI --- .../components/CurrencyInputPanel/index.tsx | 2 +- .../src/components/NumericalInput/index.tsx | 47 +++-- .../Form/LimitOrderExpirySection.tsx | 8 +- .../swapv2/LimitOrder/Form/LimitOrderForm.tsx | 16 +- .../LimitOrder/Form/LimitOrderRateSection.tsx | 163 ++++++++++++++---- .../Form/LimitOrderTokenSection.tsx | 33 +--- .../CrossChainSwap/components/TokenPanel.tsx | 2 +- .../Earns/components/SmartExit/GasSetting.tsx | 4 +- .../StakeKNC/CurrencyInputForStake.tsx | 4 +- .../KyberDAO/StakeKNC/StakeKNCComponent.tsx | 4 +- .../CreateAlert/styleds.tsx | 6 +- 11 files changed, 196 insertions(+), 93 deletions(-) diff --git a/apps/kyberswap-interface/src/components/CurrencyInputPanel/index.tsx b/apps/kyberswap-interface/src/components/CurrencyInputPanel/index.tsx index 49c7f39ebc..ec79ea23d5 100644 --- a/apps/kyberswap-interface/src/components/CurrencyInputPanel/index.tsx +++ b/apps/kyberswap-interface/src/components/CurrencyInputPanel/index.tsx @@ -9,7 +9,7 @@ import Card from 'components/Card' import TokenInfo from 'components/CurrencyInputPanel/TokenInfo' import CurrencyLogo from 'components/CurrencyLogo' import Wallet from 'components/Icons/Wallet' -import { Input as NumericalInput } from 'components/NumericalInput' +import NumericalInput from 'components/NumericalInput' import { RowFixed } from 'components/Row' import TokenSelectorModal from 'components/TokenSelectorModal' import { useActiveWeb3React } from 'hooks' diff --git a/apps/kyberswap-interface/src/components/NumericalInput/index.tsx b/apps/kyberswap-interface/src/components/NumericalInput/index.tsx index 232bab4849..957ca903a4 100644 --- a/apps/kyberswap-interface/src/components/NumericalInput/index.tsx +++ b/apps/kyberswap-interface/src/components/NumericalInput/index.tsx @@ -1,11 +1,20 @@ import { CSSProperties } from 'react' -import { escapeRegExp } from 'utils' import { cn } from 'utils/cn' -const inputRegex = RegExp(`^\\d*(?:\\\\[.])?\\d*$`) // match escaped "." characters via in a non-capturing group +const inputRegex = /^\d*\.?\d*$/ +const signedInputRegex = /^[+-]?\d*\.?\d*$/ -export const Input = function InnerInput({ +type Props = { + value: string | number + onUserInput?: (input: string) => void + error?: boolean + fontSize?: string + align?: 'right' | 'left' + allowNegative?: boolean +} & Omit, 'ref' | 'onChange' | 'as'> + +const NumericalInput = ({ value, onUserInput, placeholder, @@ -16,20 +25,24 @@ export const Input = function InnerInput({ className, style, disabled, + allowNegative, + onKeyDown, ...rest -}: { - value: string | number - onUserInput?: (input: string) => void - error?: boolean - fontSize?: string - align?: 'right' | 'left' -} & Omit, 'ref' | 'onChange' | 'as'>) { +}: Props) => { const enforcer = (nextUserInput: string) => { - if (nextUserInput === '' || inputRegex.test(escapeRegExp(nextUserInput))) { + const regex = allowNegative ? signedInputRegex : inputRegex + if (nextUserInput === '' || regex.test(nextUserInput)) { onUserInput?.(nextUserInput) } } + const handleStep = (step: 1 | -1) => { + const numericValue = Number(value || 0) + if (!Number.isFinite(numericValue)) return + const nextValue = numericValue + step + onUserInput?.(String(!allowNegative && nextValue < 0 ? 0 : nextValue)) + } + // Only set fontSize inline when caller explicitly passes one — otherwise leave // the size to the className (default `text-2xl` below) so consumers can // override with `text-xs` / `text-sm` via the className prop. @@ -52,12 +65,20 @@ export const Input = function InnerInput({ // replace commas with periods (period is the decimal separator) enforcer(event.target.value.replace(/,/g, '.')) }} + onKeyDown={event => { + onKeyDown?.(event) + if (event.defaultPrevented) return + if (event.key === 'ArrowUp' || event.key === 'ArrowDown') { + event.preventDefault() + handleStep(event.key === 'ArrowUp' ? 1 : -1) + } + }} inputMode="decimal" title={value.toString()} autoComplete="off" autoCorrect="off" type="text" - pattern="^[0-9]*[.,]?[0-9]*$" + pattern={allowNegative ? '^[+-]?[0-9]*[.,]?[0-9]*$' : '^[0-9]*[.,]?[0-9]*$'} placeholder={placeholder || '0.0'} minLength={1} maxLength={maxLength} @@ -73,4 +94,4 @@ export const Input = function InnerInput({ ) } -export default Input +export default NumericalInput diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx index 77d7cf8d5f..9bede4281d 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx @@ -40,14 +40,14 @@ export default function LimitOrderExpirySection({ ] return ( -
-
- +
+
+ - Expires in + Expires In
setExpanded(e => !e)}> diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx index f80f95db93..19bf2cf65d 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx @@ -1,5 +1,5 @@ import { Currency } from '@kyberswap/ks-sdk-core' -import { Trans } from '@lingui/macro' +import { Trans, t } from '@lingui/macro' import { forwardRef, memo, useImperativeHandle } from 'react' import { ButtonLight } from 'components/Button' @@ -13,6 +13,7 @@ import LimitOrderTokenSection from 'components/swapv2/LimitOrder/Form/LimitOrder import useLimitOrderExecution from 'components/swapv2/LimitOrder/Form/hooks/useLimitOrderExecution' import useLimitOrderFormState from 'components/swapv2/LimitOrder/Form/hooks/useLimitOrderFormState' import ConfirmOrderModal from 'components/swapv2/LimitOrder/Modals/ConfirmOrderModal' +import TradePrice from 'components/swapv2/LimitOrder/TradePrice' import { EditOrderInfo, LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/type' import { Z_INDEXS } from 'constants/styles' import { NETWORKS_INFO } from 'hooks/useChainsConfig' @@ -256,8 +257,6 @@ const LimitOrderForm = forwardRef(function LimitOrd showApproveFlow={showApproveFlow} isEdit={isEdit} rotate={rotate} - tradeInfo={tradeInfo} - loadingTrade={loadingTrade} styleTooltip={styleTooltip} onSetInput={onSetInput} onSetOutput={onSetOutput} @@ -292,6 +291,17 @@ const LimitOrderForm = forwardRef(function LimitOrd onChangeExpire={onChangeExpire} /> + {currencyIn && currencyOut ? ( + + ) : null} + {warningMessage.map((mess, i) => ( ))} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx index 3a5a1b8509..c8da835226 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx @@ -1,27 +1,78 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans } from '@lingui/macro' +import { useEffect, useState } from 'react' import { Repeat } from 'react-feather' import CurrencyLogo from 'components/CurrencyLogo' import NumericalInput from 'components/NumericalInput' -import { RowBetween } from 'components/Row' -import DeltaRate from 'components/swapv2/LimitOrder/Form/DeltaRate' +import DeltaRate, { useGetDeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/DeltaRate' +import { removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' import { RateInfo } from 'components/swapv2/LimitOrder/type' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import { cn } from 'utils/cn' -const InputWrapper = ({ children, className, ...rest }: React.HTMLAttributes) => ( -
+const RateCard = ({ children, className, ...rest }: React.HTMLAttributes) => ( +
{children}
) -const Set2Market = ({ children, className, ...rest }: React.HTMLAttributes) => ( -
+const RateChip = ({ children, className, ...rest }: React.ButtonHTMLAttributes) => ( +
+ ) +const PercentInputChip = ({ value, onUserInput }: { value: string; onUserInput: (value: string) => void }) => { + const [isEditing, setIsEditing] = useState(false) + const [draftValue, setDraftValue] = useState(value) + const displayValue = isEditing ? draftValue : value + + useEffect(() => { + if (!isEditing) { + setDraftValue(value) + } + }, [isEditing, value]) + + const onChange = (nextValue: string) => { + setDraftValue(nextValue) + if (!nextValue || nextValue === '-' || nextValue === '+') { + onUserInput('') + return + } + if (nextValue.endsWith('.')) return + onUserInput(nextValue) + } + + return ( +
+ {displayValue && !/^[+-]/.test(displayValue) ? '+' : ''} + { + setIsEditing(true) + setDraftValue(value) + }} + onBlur={() => { + setIsEditing(false) + }} + maxLength={8} + allowNegative + /> + % +
+ ) +} + type Props = { currencyIn: Currency | undefined currencyOut: Currency | undefined @@ -47,45 +98,83 @@ export default function LimitOrderRateSection({ trackingTouchInput, trackingPriceSetOnBlur, }: Props) { + const deltaRate = useGetDeltaRateLimitOrder({ marketPrice: tradeInfo, rateInfo }) + const marketRate = tradeInfo + ? removeTrailingZero((rateInfo.invert ? tradeInfo.invertRate : tradeInfo.marketRate).toPrecision(6)) + : '' + const unitCurrency = rateInfo.invert ? currencyIn : currencyOut + const rateDeltaOptions = [10, 20, 50] + const percentInputValue = + deltaRate.rawPercent === undefined || !Number.isFinite(deltaRate.rawPercent) + ? '' + : removeTrailingZero(deltaRate.rawPercent.toFixed(2)) ?? '' + + const setRateByDelta = (percent: number) => { + if (!tradeInfo) return + const market = rateInfo.invert ? tradeInfo.invertRate : tradeInfo.marketRate + const nextRate = market * (1 + (rateInfo.invert ? -percent : percent) / 100) + onChangeRate(removeTrailingZero(nextRate.toFixed(16)) ?? '') + } + + const onChangePercent = (value: string) => { + if (!value || value === '-') { + onChangeRate('') + return + } + setRateByDelta(Number(value)) + } + return ( - - -
- - {tradeInfo && ( - - Market - - )} -
-
+ +
+ + {currencyIn && currencyOut && unitCurrency && ( + + )} +
+ +
+
- {currencyIn && currencyOut && ( -
onInvertRate(!rateInfo.invert)}> - - - {rateInfo.invert ? currencyIn?.symbol : currencyOut?.symbol} - -
- -
-
- )}
- - +
+ +
+
+ + {rateDeltaOptions.map(percent => ( + setRateByDelta(percent)}> + +{percent}% + + ))} +
+ {tradeInfo ? ( + + ) : null} +
+
) } diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx index 679674897a..25b0fe8c12 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx @@ -1,13 +1,10 @@ import { Currency } from '@kyberswap/ks-sdk-core' -import { Trans, t } from '@lingui/macro' +import { Trans } from '@lingui/macro' import { CSSProperties, ReactNode } from 'react' import ArrowRotate from 'components/ArrowRotate' import CurrencyInputPanel from 'components/CurrencyInputPanel' -import { RowBetween } from 'components/Row' import Tooltip from 'components/Tooltip' -import TradePrice from 'components/swapv2/LimitOrder/TradePrice' -import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' const Label = ({ children }: { children: ReactNode }) => (
{children}
@@ -26,8 +23,6 @@ type Props = { showApproveFlow: boolean isEdit: boolean rotate: boolean - tradeInfo: BaseTradeInfo | undefined - loadingTrade: boolean styleTooltip: CSSProperties onSetInput: (input: string) => void onSetOutput: (output: string) => void @@ -52,8 +47,6 @@ export default function LimitOrderTokenSection({ showApproveFlow, isEdit, rotate, - tradeInfo, - loadingTrade, styleTooltip, onSetInput, onSetOutput, @@ -65,7 +58,7 @@ export default function LimitOrderTokenSection({ trackingTouchSelectToken, }: Props) { return ( - <> +
- - {currencyIn && currencyOut ? ( - - ) : ( -
- )} +
- +
- +
) } diff --git a/apps/kyberswap-interface/src/pages/CrossChainSwap/components/TokenPanel.tsx b/apps/kyberswap-interface/src/pages/CrossChainSwap/components/TokenPanel.tsx index b33f5c9301..93bc0ed10b 100644 --- a/apps/kyberswap-interface/src/pages/CrossChainSwap/components/TokenPanel.tsx +++ b/apps/kyberswap-interface/src/pages/CrossChainSwap/components/TokenPanel.tsx @@ -11,7 +11,7 @@ import UnknownToken from 'assets/svg/kyber/unknown-token.svg' import { Aligner, CurrencySelect, InputRow, StyledTokenName } from 'components/CurrencyInputPanel' import CurrencyLogo from 'components/CurrencyLogo' import Wallet from 'components/Icons/Wallet' -import { Input as NumericalInput } from 'components/NumericalInput' +import NumericalInput from 'components/NumericalInput' import { RowFixed } from 'components/Row' import Skeleton from 'components/Skeleton' import { Stack } from 'components/Stack' diff --git a/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/GasSetting.tsx b/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/GasSetting.tsx index 336d7fbfb0..4d476ade07 100644 --- a/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/GasSetting.tsx +++ b/apps/kyberswap-interface/src/pages/Earns/components/SmartExit/GasSetting.tsx @@ -2,7 +2,7 @@ import { Trans, t } from '@lingui/macro' import { useState } from 'react' import { ChevronDown } from 'react-feather' -import Input from 'components/NumericalInput' +import NumericalInput from 'components/NumericalInput' import { DropdownIcon } from 'components/SwapForm/SlippageSetting' import PositionSkeleton from 'pages/Earns/components/PositionSkeleton' import { GAS_MULTIPLIER_PRESETS } from 'pages/Earns/components/SmartExit/constants' @@ -110,7 +110,7 @@ export default function GasSetting({ key="custom" className={cn('flex flex-1 items-center gap-1', customGasPercent && 'text-primary')} > - setCustomGasPercent(v)} placeholder={t`Custom`} diff --git a/apps/kyberswap-interface/src/pages/KyberDAO/StakeKNC/CurrencyInputForStake.tsx b/apps/kyberswap-interface/src/pages/KyberDAO/StakeKNC/CurrencyInputForStake.tsx index 02b35c8f9a..e696fecf19 100644 --- a/apps/kyberswap-interface/src/pages/KyberDAO/StakeKNC/CurrencyInputForStake.tsx +++ b/apps/kyberswap-interface/src/pages/KyberDAO/StakeKNC/CurrencyInputForStake.tsx @@ -3,7 +3,7 @@ import { useMemo } from 'react' import KNC from 'assets/images/KNC.svg' import Wallet from 'components/Icons/Wallet' -import Input from 'components/NumericalInput' +import NumericalInput from 'components/NumericalInput' import { AutoRow, RowBetween } from 'components/Row' import useTokenBalance from 'hooks/useTokenBalance' import { KNCLogoWrapper, SmallButton } from 'pages/KyberDAO/StakeKNC/StakeKNCComponent' @@ -61,7 +61,7 @@ export default function CurrencyInputForStake({
- + ~${kncValueInUsd} {getTokenLogoURL(tokenAddress, ChainId.MAINNET) !== '' ? ( diff --git a/apps/kyberswap-interface/src/pages/KyberDAO/StakeKNC/StakeKNCComponent.tsx b/apps/kyberswap-interface/src/pages/KyberDAO/StakeKNC/StakeKNCComponent.tsx index 201917e074..d53430204c 100644 --- a/apps/kyberswap-interface/src/pages/KyberDAO/StakeKNC/StakeKNCComponent.tsx +++ b/apps/kyberswap-interface/src/pages/KyberDAO/StakeKNC/StakeKNCComponent.tsx @@ -21,7 +21,7 @@ import VoteIcon from 'components/Icons/Vote' import Wallet from 'components/Icons/Wallet' import WarningIcon from 'components/Icons/WarningIcon' import InfoHelper from 'components/InfoHelper' -import Input from 'components/NumericalInput' +import NumericalInput from 'components/NumericalInput' import Row, { AutoRow, RowBetween, RowFit } from 'components/Row' import useParsedAmount from 'components/SwapForm/hooks/useParsedAmount' import { MouseoverTooltip } from 'components/Tooltip' @@ -351,7 +351,7 @@ export default function StakeKNCComponent() { )} - + ~${kncValueInUsd} diff --git a/apps/kyberswap-interface/src/pages/NotificationCenter/CreateAlert/styleds.tsx b/apps/kyberswap-interface/src/pages/NotificationCenter/CreateAlert/styleds.tsx index 892fa13403..c29b05b7f8 100644 --- a/apps/kyberswap-interface/src/pages/NotificationCenter/CreateAlert/styleds.tsx +++ b/apps/kyberswap-interface/src/pages/NotificationCenter/CreateAlert/styleds.tsx @@ -1,5 +1,5 @@ import { ButtonPrimary } from 'components/Button' -import Input from 'components/NumericalInput' +import NumericalInput from 'components/NumericalInput' import Select from 'components/Select' import { cn } from 'utils/cn' @@ -47,8 +47,8 @@ export const RightColumn = ({ children, className, ...rest }: React.HTMLAttribut
) -export const StyledInputNumber = ({ className, ...rest }: React.ComponentProps) => ( - +export const StyledInputNumber = ({ className, ...rest }: React.ComponentProps) => ( + ) export const StyledInput = ({ className, ...rest }: React.TextareaHTMLAttributes) => ( From e565dd5500540f3ba3c6c39c948ba34995a1318f Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Thu, 18 Jun 2026 09:03:05 +0700 Subject: [PATCH 05/52] Process order new flow --- .../src/components/NumericalInput/index.tsx | 2 +- .../Form/ActionButtonLimitOrder.tsx | 132 ---------- .../swapv2/LimitOrder/Form/DeltaRate.tsx | 85 ------- .../swapv2/LimitOrder/Form/LimitOrderForm.tsx | 84 +++--- .../LimitOrder/Form/LimitOrderRateSection.tsx | 86 ++++++- .../Modals/ProcessingOrderModal.tsx | 110 ++++++++ .../hooks/useLimitOrderExecution.tsx | 240 +++++++++++++++++- .../hooks/useLimitOrderFormState.ts | 0 .../hooks/useValidateInputError.tsx | 9 +- .../hooks/useWarningCreateOrder.tsx | 2 +- 10 files changed, 478 insertions(+), 272 deletions(-) delete mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/ActionButtonLimitOrder.tsx delete mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/DeltaRate.tsx create mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{Form => }/hooks/useLimitOrderExecution.tsx (71%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{Form => }/hooks/useLimitOrderFormState.ts (100%) diff --git a/apps/kyberswap-interface/src/components/NumericalInput/index.tsx b/apps/kyberswap-interface/src/components/NumericalInput/index.tsx index 957ca903a4..9e260c94d0 100644 --- a/apps/kyberswap-interface/src/components/NumericalInput/index.tsx +++ b/apps/kyberswap-interface/src/components/NumericalInput/index.tsx @@ -78,7 +78,7 @@ const NumericalInput = ({ autoComplete="off" autoCorrect="off" type="text" - pattern={allowNegative ? '^[+-]?[0-9]*[.,]?[0-9]*$' : '^[0-9]*[.,]?[0-9]*$'} + pattern={allowNegative ? '^[-+]?[0-9]*[.,]?[0-9]*$' : '^[0-9]*[.,]?[0-9]*$'} placeholder={placeholder || '0.0'} minLength={1} maxLength={maxLength} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/ActionButtonLimitOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/ActionButtonLimitOrder.tsx deleted file mode 100644 index 7a3a0dff01..0000000000 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/ActionButtonLimitOrder.tsx +++ /dev/null @@ -1,132 +0,0 @@ -import { Currency, WETH } from '@kyberswap/ks-sdk-core' -import { Trans, t } from '@lingui/macro' - -import { - ButtonApprove, - ButtonError, - ButtonLight, - ButtonPrimary, - ButtonWarning, - ButtonWithInfoHelper, -} from 'components/Button' -import ProgressSteps from 'components/ProgressSteps' -import { RowBetween } from 'components/Row' -import { EditOrderInfo } from 'components/swapv2/LimitOrder/type' -import { useActiveWeb3React } from 'hooks' -import { ApprovalState } from 'hooks/useApproveCallback' -import { useWalletModalToggle } from 'state/application/hooks' -import { isTokenNative } from 'utils/tokenInfo' - -export default function ActionButtonLimitOrder({ - showWrap, - approval, - currencyIn, - currencyOut, - isWrappingEth, - wrapInputError, - approveCallback, - onWrapToken, - checkingAllowance, - showPreview, - isNotFillAllInput, - enoughAllowance, - hasInputError, - approvalSubmitted, - showApproveFlow, - showWarning, - editOrderInfo, -}: { - currencyIn: Currency | undefined - currencyOut: Currency | undefined - approval: ApprovalState - showWrap: boolean - isWrappingEth: boolean - isNotFillAllInput: boolean - hasInputError: boolean - approvalSubmitted: boolean - enoughAllowance: boolean - checkingAllowance: boolean - showApproveFlow: boolean - wrapInputError: any - showWarning: boolean - approveCallback: () => Promise - onWrapToken: () => Promise - showPreview: () => void - editOrderInfo?: EditOrderInfo -}) { - const { isEdit, renderCancelButtons } = editOrderInfo || {} - const disableBtnApproved = - approval === ApprovalState.PENDING || - !!hasInputError || - ((approval !== ApprovalState.NOT_APPROVED || approvalSubmitted) && enoughAllowance) - - const disableBtnReview = - checkingAllowance || - isNotFillAllInput || - !!hasInputError || - approval !== ApprovalState.APPROVED || - isWrappingEth || - (showWrap && !isWrappingEth) || - (currencyIn?.equals(WETH[currencyIn.chainId]) && isTokenNative(currencyOut)) - - const { account } = useActiveWeb3React() - const toggleWalletModal = useWalletModalToggle() - if (!account) - return ( - - Connect - - ) - - const inSymbol = currencyIn?.symbol - const wrapSymbol = currencyIn?.wrapped.symbol - if (showApproveFlow || showWrap) - return ( - <> - - {showWrap ? ( - - ) : ( - - )} - - - Review Order - - - - {showApproveFlow && } - - ) - - const contentButton = ( - - {checkingAllowance ? Checking Allowance... : Review Order} - - ) - - if (isEdit) { - return checkingAllowance ? {contentButton} : renderCancelButtons?.() || null - } - - if (showWarning && !disableBtnReview) return {contentButton} - - return ( - - {contentButton} - - ) -} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/DeltaRate.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/DeltaRate.tsx deleted file mode 100644 index 2e872f9228..0000000000 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/DeltaRate.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useMemo } from 'react' - -import InfoHelper from 'components/InfoHelper' -import { Label } from 'components/swapv2/LimitOrder/Form/LimitOrderForm' -import { RateInfo } from 'components/swapv2/LimitOrder/type' -import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' -import useTheme from 'hooks/useTheme' -import { cn } from 'utils/cn' - -export type DeltaRateLimitOrder = { rawPercent: number | undefined; percent: string; profit: boolean } - -export function useGetDeltaRateLimitOrder({ - marketPrice, - rateInfo, -}: { - marketPrice: BaseTradeInfo | undefined - rateInfo: RateInfo -}): DeltaRateLimitOrder { - const { deltaText, percent } = useMemo(() => { - try { - if (marketPrice && rateInfo.rate && rateInfo.invertRate) { - const { rate, invert, invertRate } = rateInfo - const ourRate = Number(invert ? invertRate : rate) - const marketRate = Number(invert ? marketPrice.invertRate : marketPrice.marketRate) - let percent = ((ourRate - marketRate) / marketRate) * 100 - if (invert) percent = -percent - const delta = Number(percent) - const sign = delta > 0 ? '+' : '' - const deltaText = `${Math.abs(delta) > 100 ? '>100' : `${sign}${delta.toFixed(2)}`}%` - return { percent, deltaText } - } - } catch (error) { - console.log(error) - } - return { percent: undefined, deltaText: '' } - }, [marketPrice, rateInfo]) - - const percentText = Math.abs(Number(percent)) > 0.009 ? deltaText : '' - return { - rawPercent: percent, - percent: percentText, - profit: Boolean(percent && Number(percent) > 0), - } -} - -const DeltaRate = ({ - marketPrice, - rateInfo, - symbol, - invert, -}: { - marketPrice: BaseTradeInfo | undefined - rateInfo: RateInfo - symbol: string - invert: boolean -}) => { - const theme = useTheme() - - const { percent, profit } = useGetDeltaRateLimitOrder({ marketPrice, rateInfo }) - const color = profit ? theme.apr : theme.warning - const colorClass = profit ? 'text-apr' : 'text-warning' - const styledPercent = {percent} - return ( - - ) -} -export default DeltaRate diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx index 19bf2cf65d..24e58ddb97 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx @@ -2,23 +2,26 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' import { forwardRef, memo, useImperativeHandle } from 'react' -import { ButtonLight } from 'components/Button' +import { ButtonLight, ButtonPrimary, ButtonWarning } from 'components/Button' import DateTimePicker from 'components/DateTimePicker' import { NetworkSelector } from 'components/NetworkSelector' -import ActionButtonLimitOrder from 'components/swapv2/LimitOrder/Form/ActionButtonLimitOrder' -import { useGetDeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/DeltaRate' import LimitOrderExpirySection from 'components/swapv2/LimitOrder/Form/LimitOrderExpirySection' -import LimitOrderRateSection from 'components/swapv2/LimitOrder/Form/LimitOrderRateSection' +import LimitOrderRateSection, { + useGetDeltaRateLimitOrder, +} from 'components/swapv2/LimitOrder/Form/LimitOrderRateSection' import LimitOrderTokenSection from 'components/swapv2/LimitOrder/Form/LimitOrderTokenSection' -import useLimitOrderExecution from 'components/swapv2/LimitOrder/Form/hooks/useLimitOrderExecution' -import useLimitOrderFormState from 'components/swapv2/LimitOrder/Form/hooks/useLimitOrderFormState' import ConfirmOrderModal from 'components/swapv2/LimitOrder/Modals/ConfirmOrderModal' +import ProcessingOrderModal from 'components/swapv2/LimitOrder/Modals/ProcessingOrderModal' import TradePrice from 'components/swapv2/LimitOrder/TradePrice' +import useLimitOrderExecution from 'components/swapv2/LimitOrder/hooks/useLimitOrderExecution' +import useLimitOrderFormState from 'components/swapv2/LimitOrder/hooks/useLimitOrderFormState' import { EditOrderInfo, LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/type' import { Z_INDEXS } from 'constants/styles' +import { useActiveWeb3React } from 'hooks' import { NETWORKS_INFO } from 'hooks/useChainsConfig' import { useChangeNetwork } from 'hooks/web3/useChangeNetwork' import ErrorWarningPanel from 'pages/Bridge/ErrorWarning' +import { useWalletModalToggle } from 'state/application/hooks' import { TransactionFlowState } from 'types/TransactionFlowState' import { cn } from 'utils/cn' @@ -87,6 +90,8 @@ const LimitOrderForm = forwardRef(function LimitOrd ref, ) { const { changeNetwork } = useChangeNetwork() + const { account } = useActiveWeb3React() + const toggleWalletModal = useWalletModalToggle() const isEdit = mode === 'edit' const { chainId, @@ -131,30 +136,27 @@ const LimitOrderForm = forwardRef(function LimitOrd }) const deltaRate = useGetDeltaRateLimitOrder({ marketPrice: tradeInfo, rateInfo }) const { - approval, - approvalSubmitted, - approveCallback, checkingAllowance, - enoughAllowance, estimateUSD, handleMaxInput, hasChangedOrderInfo, hasInputError, hidePreview, + hideProcessingOrder, inputError, + insufficientBalance, + insufficientBalanceText, isNotFillAllInput, - isWrappingEth, onSubmitCreateOrderWithTracking, - onWrapToken, outPutError, - showApproveFlow, + processingOrder, + retryProcessingOrder, showPreview, - showWrap, + startProcessingOrder, trackingPriceSetOnBlur, trackingTouchInput, trackingTouchSelectToken, warningMessage, - wrapInputError, } = useLimitOrderExecution({ currencyIn, currencyOut, @@ -186,37 +188,39 @@ const LimitOrderForm = forwardRef(function LimitOrd })) const styleTooltip = { maxWidth: '250px', zIndex: zIndexToolTip } + const disableReviewButton = isNotFillAllInput || !!hasInputError || insufficientBalance + const reviewButtonContent = ( + + {insufficientBalance && insufficientBalanceText ? insufficientBalanceText : Review Order} + + ) const actionButton = chainId !== walletChainId ? ( changeNetwork(chainId)}> Switch to {NETWORKS_INFO[chainId].name} + ) : !account ? ( + + Connect + + ) : isEdit ? ( + checkingAllowance ? ( + {reviewButtonContent} + ) : ( + editOrderInfo?.renderCancelButtons?.() || null + ) + ) : warningMessage.length > 0 && !disableReviewButton ? ( + {reviewButtonContent} ) : ( - 0} - editOrderInfo={editOrderInfo} - /> + + {reviewButtonContent} + ) const renderConfirmModal = (showConfirmContent = false) => ( (function LimitOrd outPutError={outPutError} estimateUsdIn={estimateUSD.input} estimateUsdOut={estimateUSD.output} - showApproveFlow={showApproveFlow} + showApproveFlow={false} isEdit={isEdit} rotate={rotate} styleTooltip={styleTooltip} @@ -318,6 +322,14 @@ const LimitOrderForm = forwardRef(function LimitOrd onDismiss={toggleDatePicker} onSetDate={onChangeExpire} /> + + ) }) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx index c8da835226..ea6d8ce3b4 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx @@ -1,16 +1,98 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans } from '@lingui/macro' -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import { Repeat } from 'react-feather' import CurrencyLogo from 'components/CurrencyLogo' +import InfoHelper from 'components/InfoHelper' import NumericalInput from 'components/NumericalInput' -import DeltaRate, { useGetDeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/DeltaRate' import { removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' import { RateInfo } from 'components/swapv2/LimitOrder/type' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' +import useTheme from 'hooks/useTheme' import { cn } from 'utils/cn' +export type DeltaRateLimitOrder = { rawPercent: number | undefined; percent: string; profit: boolean } + +export function useGetDeltaRateLimitOrder({ + marketPrice, + rateInfo, +}: { + marketPrice: BaseTradeInfo | undefined + rateInfo: RateInfo +}): DeltaRateLimitOrder { + const { deltaText, percent } = useMemo(() => { + try { + if (marketPrice && rateInfo.rate && rateInfo.invertRate) { + const { rate, invert, invertRate } = rateInfo + const ourRate = Number(invert ? invertRate : rate) + const marketRate = Number(invert ? marketPrice.invertRate : marketPrice.marketRate) + let percent = ((ourRate - marketRate) / marketRate) * 100 + if (invert) percent = -percent + const delta = Number(percent) + const sign = delta > 0 ? '+' : '' + const deltaText = `${Math.abs(delta) > 100 ? '>100' : `${sign}${delta.toFixed(2)}`}%` + return { percent, deltaText } + } + } catch (error) { + console.log(error) + } + return { percent: undefined, deltaText: '' } + }, [marketPrice, rateInfo]) + + const percentText = Math.abs(Number(percent)) > 0.009 ? deltaText : '' + return { + rawPercent: percent, + percent: percentText, + profit: Boolean(percent && Number(percent) > 0), + } +} + +const RateLabel = ({ children, className, ...rest }: React.HTMLAttributes) => ( +
+ {children} +
+) + +const DeltaRate = ({ + marketPrice, + rateInfo, + symbol, + invert, +}: { + marketPrice: BaseTradeInfo | undefined + rateInfo: RateInfo + symbol: string + invert: boolean +}) => { + const theme = useTheme() + + const { percent, profit } = useGetDeltaRateLimitOrder({ marketPrice, rateInfo }) + const color = profit ? theme.apr : theme.warning + const colorClass = profit ? 'text-apr' : 'text-warning' + const styledPercent = {percent} + return ( + + {invert ? Buy {symbol} at rate : Sell {symbol} at rate} + {percent ? ( + <> +  {percent} + Your selected price is {styledPercent} better than the current market price. + ) : ( + Your selected price is {styledPercent} worse than the current market price. + ) + } + /> + + ) : null} + + ) +} + const RateCard = ({ children, className, ...rest }: React.HTMLAttributes) => (
{children} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx new file mode 100644 index 0000000000..912e64c9ac --- /dev/null +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx @@ -0,0 +1,110 @@ +import { ChainId, Currency } from '@kyberswap/ks-sdk-core' +import { t } from '@lingui/macro' +import { AlertCircle, RefreshCw, X } from 'react-feather' + +import { ButtonLight } from 'components/Button' +import { CheckCircle } from 'components/Icons' +import Loader from 'components/Loader' +import Modal from 'components/Modal' +import type { + ProcessingOrderState, + ProcessingOrderStep, + ProcessingOrderStepStatus, +} from 'components/swapv2/LimitOrder/hooks/useLimitOrderExecution' +import { NativeCurrencies } from 'constants/tokens' +import { cn } from 'utils/cn' + +const getStepStatus = (state: ProcessingOrderState, step: ProcessingOrderStep): ProcessingOrderStepStatus => { + if (state.errorStep === step) return 'error' + if (state.completedSteps.includes(step)) return 'success' + if (state.currentStep === step) return 'active' + return 'idle' +} + +const StepIcon = ({ index, status }: { index: number; status: ProcessingOrderStepStatus }) => { + if (status === 'success') return + if (status === 'active') return + if (status === 'error') return + return ( + + {index + 1} + + ) +} + +const getStepLabel = ({ + step, + status, + chainId, + currencyIn, +}: { + step: ProcessingOrderStep + status: ProcessingOrderStepStatus + chainId: ChainId + currencyIn: Currency | undefined +}) => { + const nativeSymbol = NativeCurrencies[chainId].symbol + const inputSymbol = currencyIn?.wrapped.symbol + if (step === 'wrap') return t`Wrapping ${nativeSymbol}...` + if (step === 'approve') return t`Approving ${inputSymbol}...` + if (step === 'create' && status === 'success') return t`Order successfully listed!` + return t`Signing order...` +} + +export default function ProcessingOrderModal({ + chainId, + currencyIn, + state, + onDismiss, + onRetry, +}: { + chainId: ChainId + currencyIn: Currency | undefined + state: ProcessingOrderState + onDismiss: () => void + onRetry: () => void +}) { + return ( + +
+
+
{t`Processing Order`}
+ +
+ +
+ {state.steps.map((step, index) => { + const status = getStepStatus(state, step) + return ( +
+
+ + {getStepLabel({ step, status, chainId, currencyIn })} +
+ + {status === 'error' ? ( + + + {t`Retry`} + + ) : null} +
+ ) + })} +
+
+
+ ) +} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx similarity index 71% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderExecution.tsx rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx index 95714f206e..36bc6fac83 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderExecution.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx @@ -6,7 +6,7 @@ import { useCreateOrderMutation, useGetLOConfigQuery, useGetTotalActiveMakingAmo import { NotificationType } from 'components/Announcement/type' import { getTipLinkAttribution } from 'components/TipLinkGeneratorModal/shared' -import type { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/DeltaRate' +import type { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/LimitOrderRateSection' import { SummaryNotifyOrderPlaced } from 'components/swapv2/LimitOrder/ListOrder/SummaryNotify' import { calcUsdPrices, @@ -21,6 +21,7 @@ import useWarningCreateOrder from 'components/swapv2/LimitOrder/hooks/useWarning import useWrapEthStatus from 'components/swapv2/LimitOrder/hooks/useWrapEthStatus' import { CreateOrderParam, LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/type' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' +import { NativeCurrencies } from 'constants/tokens' import { useTokenAllowance } from 'data/Allowances' import { useActiveWeb3React } from 'hooks' import { ApprovalState, useApproveCallback } from 'hooks/useApproveCallback' @@ -64,6 +65,17 @@ type UseLimitOrderExecutionArgs = { const getTokenAddress = (currency: Currency | undefined) => (currency?.isNative ? 'NATIVE' : currency?.wrapped?.address) +export type ProcessingOrderStep = 'wrap' | 'approve' | 'create' +export type ProcessingOrderStepStatus = 'idle' | 'active' | 'success' | 'error' + +export type ProcessingOrderState = { + show: boolean + steps: ProcessingOrderStep[] + currentStep?: ProcessingOrderStep + errorStep?: ProcessingOrderStep + completedSteps: ProcessingOrderStep[] +} + export default function useLimitOrderExecution({ currencyIn, currencyOut, @@ -95,6 +107,13 @@ export default function useLimitOrderExecution({ const { ordersNeedCreated } = useLimitState() const { removeOrderNeedCreated, setOrderEditing } = useLimitActionHandlers() const [approvalSubmitted, setApprovalSubmitted] = useState(false) + const [processingOrder, setProcessingOrder] = useState({ + show: false, + steps: [], + completedSteps: [], + }) + const processingStepStartedRef = useRef() + const approvalRef = useRef(ApprovalState.UNKNOWN) // Balances, allowance, and form readiness. const { data: activeOrderMakingAmount = defaultActiveMakingAmount, refetch: getActiveMakingAmount } = @@ -103,15 +122,6 @@ export default function useLimitOrderExecution({ { skip: !currencyIn || !account }, ) - const { execute: onWrap, inputError: wrapInputError } = useWrapCallback( - currencyIn, - currencyOut, - inputAmount, - true, - chainId, - ) - const showWrap = !!currencyIn?.isNative - const { isWrappingEth, setTxHashWrapped } = useWrapEthStatus(switchToWeth) const parseInputAmount = tryParseAmount(inputAmount, currencyIn ?? undefined) @@ -144,10 +154,42 @@ export default function useLimitOrderExecution({ }, [currencyIn, activeOrderMakingAmount, isEdit, orderInfo]) const balance = useCurrencyBalance(currencyIn, chainId) + const nativeCurrency = NativeCurrencies[chainId] + const nativeBalance = useCurrencyBalance(nativeCurrency, chainId) + const isWrappedNativeInput = !!currencyIn?.equals(WETH[chainId]) + const wrapAmountForOrder = useMemo(() => { + if (!currencyIn || !isWrappedNativeInput || !parseInputAmount || !balance?.currency.equals(currencyIn)) { + return undefined + } + if (!balance.lessThan(parseInputAmount)) return undefined + const deficit = JSBI.subtract(parseInputAmount.quotient, balance.quotient) + return CurrencyAmount.fromRawAmount(nativeCurrency, deficit) + }, [balance, currencyIn, isWrappedNativeInput, nativeCurrency, parseInputAmount]) + const needsWrap = !!currencyIn?.isNative || !!wrapAmountForOrder + const wrapInputCurrency = currencyIn?.isNative ? currencyIn : wrapAmountForOrder ? nativeCurrency : currencyIn + const wrapTypedValue = wrapAmountForOrder ? wrapAmountForOrder.toExact() : inputAmount + const { execute: onWrap, inputError: wrapInputError } = useWrapCallback( + wrapInputCurrency, + WETH[chainId], + wrapTypedValue, + true, + chainId, + ) + const showWrap = needsWrap const maxAmountInput = useMemo(() => { return maxAmountSpend(balance) }, [balance]) + const insufficientBalance = useMemo(() => { + if (!parseInputAmount || !currencyIn || !balance?.currency.equals(currencyIn)) return false + if (!balance.lessThan(parseInputAmount)) return false + if (!isWrappedNativeInput || !wrapAmountForOrder || !nativeBalance?.currency.equals(nativeCurrency)) return true + return nativeBalance.lessThan(wrapAmountForOrder) + }, [balance, currencyIn, isWrappedNativeInput, nativeBalance, nativeCurrency, parseInputAmount, wrapAmountForOrder]) + + const insufficientBalanceSymbol = currencyIn?.symbol + const insufficientBalanceText = insufficientBalance ? t`Insufficient ${insufficientBalanceSymbol} balance` : undefined + const handleMaxInput = useCallback(() => { if (!maxAmountInput) return try { @@ -188,6 +230,7 @@ export default function useLimitOrderExecution({ wrapInputError, showWrap, currencyOut, + showInsufficientBalanceError: false, }) const hasInputError = Boolean(inputError || outPutError) @@ -326,6 +369,50 @@ export default function useLimitOrderExecution({ refreshActiveMakingAmount() }, [onResetForm, refreshActiveMakingAmount]) + const markProcessingStepSuccess = useCallback((step: ProcessingOrderStep) => { + processingStepStartedRef.current = undefined + setProcessingOrder(state => { + if (!state.show || state.currentStep !== step) return state + const completedSteps = state.completedSteps.includes(step) + ? state.completedSteps + : [...state.completedSteps, step] + const nextStep = state.steps[state.steps.indexOf(step) + 1] + return { + ...state, + currentStep: nextStep, + completedSteps, + } + }) + }, []) + + const markProcessingStepError = useCallback((step: ProcessingOrderStep) => { + processingStepStartedRef.current = undefined + setProcessingOrder(state => { + if (!state.show || state.currentStep !== step) return state + return { + ...state, + errorStep: step, + } + }) + }, []) + + const hideProcessingOrder = useCallback(() => { + processingStepStartedRef.current = undefined + setProcessingOrder({ show: false, steps: [], completedSteps: [] }) + }, []) + + const retryProcessingOrder = useCallback(() => { + processingStepStartedRef.current = undefined + setProcessingOrder(state => { + if (!state.errorStep) return state + return { + ...state, + currentStep: state.errorStep, + errorStep: undefined, + } + }) + }, []) + const onWrapToken = async () => { try { if (isNotFillAllInput || wrapInputError || isWrappingEth || hasInputError) return @@ -396,7 +483,7 @@ export default function useLimitOrderExecution({ [handleError, notify, resetForm, searchParams, setFlowState, signOrder, submitOrder], ) - const onSubmitCreateOrderWithTracking = async () => { + const onSubmitCreateOrderWithTracking = useCallback(async () => { trackingPlaceOrder(TRACKING_EVENT_TYPE.LO_CLICK_PLACE_ORDER) const order_id = await onSubmitCreateOrder({ currencyIn, @@ -448,10 +535,127 @@ export default function useLimitOrderExecution({ order_id, }) } - } + return order_id + }, [ + account, + chainId, + currencyIn, + currencyOut, + deltaRate.rawPercent, + displayRate, + displayTime, + estimateUSD.rawInput, + expiredAt, + inputAmount, + networkName, + onSubmitCreateOrder, + outputAmount, + rateInfo.invert, + searchParams, + trackingHandler, + trackingPlaceOrder, + tradeInfo, + ]) + + const runProcessingStep = useCallback( + (step: ProcessingOrderStep) => { + if (step === 'wrap') { + if (!needsWrap) { + markProcessingStepSuccess('wrap') + return + } + if (isWrappingEth || processingStepStartedRef.current === 'wrap') return + processingStepStartedRef.current = 'wrap' + ;(async () => { + try { + const hash = await onWrap?.() + if (!hash) { + markProcessingStepError('wrap') + return + } + setTxHashWrapped(hash) + } catch (error) { + handleError(error) + markProcessingStepError('wrap') + } + })() + return + } + + if (step === 'approve') { + if (approval === ApprovalState.APPROVED) { + markProcessingStepSuccess('approve') + return + } + if (approval === ApprovalState.UNKNOWN || approval === ApprovalState.PENDING) return + if (processingStepStartedRef.current === 'approve') return + processingStepStartedRef.current = 'approve' + ;(async () => { + try { + await approveCallback() + setTimeout(() => { + if (approvalRef.current === ApprovalState.NOT_APPROVED) { + markProcessingStepError('approve') + } + }, 800) + } catch (error) { + handleError(error) + markProcessingStepError('approve') + } + })() + return + } + + if (processingStepStartedRef.current === 'create') return + processingStepStartedRef.current = 'create' + ;(async () => { + try { + const orderId = await onSubmitCreateOrderWithTracking() + if (orderId) { + markProcessingStepSuccess('create') + return + } + markProcessingStepError('create') + } catch (error) { + handleError(error) + markProcessingStepError('create') + } + })() + }, + [ + approval, + approveCallback, + handleError, + isWrappingEth, + markProcessingStepError, + markProcessingStepSuccess, + needsWrap, + onSubmitCreateOrderWithTracking, + onWrap, + setTxHashWrapped, + ], + ) + + const startProcessingOrder = useCallback(() => { + const steps: ProcessingOrderStep[] = [] + if (needsWrap) steps.push('wrap') + if (needsWrap || (!currencyIn?.isNative && approval !== ApprovalState.APPROVED)) steps.push('approve') + steps.push('create') + const firstStep = steps[0] + processingStepStartedRef.current = undefined + setFlowState(state => ({ ...state, showConfirm: false, errorMessage: undefined })) + setProcessingOrder({ + show: true, + steps, + currentStep: firstStep, + completedSteps: [], + }) + runProcessingStep(firstStep) + }, [approval, currencyIn?.isNative, needsWrap, runProcessingStep, setFlowState]) // External state synchronization. useEffect(() => { + approvalRef.current = approval if (approval === ApprovalState.PENDING) { setApprovalSubmitted(true) } @@ -460,6 +664,12 @@ export default function useLimitOrderExecution({ } }, [approval]) + useEffect(() => { + const currentStep = processingOrder.currentStep + if (!processingOrder.show || !currentStep || processingOrder.errorStep) return + runProcessingStep(currentStep) + }, [processingOrder.currentStep, processingOrder.errorStep, processingOrder.show, runProcessingStep]) + useEffect(() => { if (!isEdit || !orderInfo?.id) return setOrderEditing({ @@ -539,15 +749,21 @@ export default function useLimitOrderExecution({ hasChangedOrderInfo, hasInputError, hidePreview, + hideProcessingOrder, inputError, + insufficientBalance, + insufficientBalanceText, isNotFillAllInput, isWrappingEth, onSubmitCreateOrderWithTracking, onWrapToken, outPutError, + processingOrder, + retryProcessingOrder, showApproveFlow, showPreview, showWrap, + startProcessingOrder, trackingPriceSetOnBlur, trackingTouchInput, trackingTouchSelectToken, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderFormState.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/hooks/useLimitOrderFormState.ts rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx index 6d85cf1484..a1e018d1aa 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx @@ -18,11 +18,13 @@ const useValidateInputError = ({ wrapInputError, showWrap, currencyOut, + showInsufficientBalanceError = true, }: { currencyIn: Currency | undefined currencyOut: Currency | undefined showWrap: boolean wrapInputError: any + showInsufficientBalanceError?: boolean displayRate: string inputAmount: string outputAmount: string @@ -38,13 +40,13 @@ const useValidateInputError = ({ if (parseFloat(inputAmount) === 0 && (parseFloat(outputAmount) === 0 || parseFloat(displayRate) === 0)) { return t`Invalid input amount` } - if (balance && parseInputAmount?.greaterThan(balance)) { + if (showInsufficientBalanceError && balance && parseInputAmount?.greaterThan(balance)) { const symbol = currencyIn?.symbol return t`Insufficient ${symbol} balance` } const remainBalance = parsedActiveOrderMakingAmount ? balance?.subtract(parsedActiveOrderMakingAmount) : undefined - if (parseInputAmount && remainBalance?.lessThan(parseInputAmount)) { + if (showInsufficientBalanceError && parseInputAmount && remainBalance?.lessThan(parseInputAmount)) { const formatNum = formatDisplayNumber(remainBalance, { style: 'decimal', fractionDigits: 6, @@ -69,7 +71,7 @@ const useValidateInputError = ({ return t`Your input amount is invalid.` } - if (showWrap && wrapInputError) return wrapInputError + if (showInsufficientBalanceError && showWrap && wrapInputError) return wrapInputError return } catch (error) { return @@ -86,6 +88,7 @@ const useValidateInputError = ({ wrapInputError, setInputValue, account, + showInsufficientBalanceError, ]) const outPutError = useMemo(() => { diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx index 3ce7babaf4..b4c6e5dec4 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx @@ -2,7 +2,7 @@ import { Currency, CurrencyAmount } from '@kyberswap/ks-sdk-core' import { Trans } from '@lingui/macro' import { useMemo } from 'react' -import { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/DeltaRate' +import { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/LimitOrderRateSection' import { BETTER_PRICE_DIFF_THRESHOLD, USD_THRESHOLD, From e2212786f26cf9caa780fe687d5d4569141b9e9b Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Thu, 18 Jun 2026 10:01:18 +0700 Subject: [PATCH 06/52] refactor(limit-order): remove edit order flow --- .../LimitOrder/EditOrder/EditOrderModal.tsx | 195 ---------------- .../swapv2/LimitOrder/Form/LimitOrderForm.tsx | 136 +++-------- .../Form/LimitOrderTokenSection.tsx | 9 +- .../LimitOrder/ListOrder/ActionButtons.tsx | 1 - .../swapv2/LimitOrder/ListOrder/OrderItem.tsx | 4 - .../swapv2/LimitOrder/ListOrder/index.tsx | 50 ---- .../ListOrder/useRequestCancelOrder.tsx | 30 +-- .../LimitOrder/Modals/CancelButtons.tsx | 36 +-- .../LimitOrder/Modals/ConfirmOrderModal.tsx | 46 +--- .../hooks/useLimitOrderExecution.tsx | 215 +++--------------- .../hooks/useLimitOrderFormState.ts | 52 +---- .../swapv2/LimitOrder/hooks/useSignOrder.ts | 3 +- .../hooks/useValidateInputError.tsx | 62 +---- .../src/components/swapv2/LimitOrder/type.ts | 12 - .../src/hooks/useTracking.ts | 10 - apps/kyberswap-interface/src/locales/en-US.po | 36 --- apps/kyberswap-interface/src/locales/zh-CN.po | 36 --- apps/kyberswap-interface/src/state/index.ts | 2 - .../src/state/limit/actions.ts | 8 - .../src/state/limit/hooks.ts | 40 +--- .../src/state/limit/reducer.ts | 28 --- 21 files changed, 100 insertions(+), 911 deletions(-) delete mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/EditOrder/EditOrderModal.tsx delete mode 100644 apps/kyberswap-interface/src/state/limit/actions.ts delete mode 100644 apps/kyberswap-interface/src/state/limit/reducer.ts diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/EditOrder/EditOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/EditOrder/EditOrderModal.tsx deleted file mode 100644 index f4e2d70b36..0000000000 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/EditOrder/EditOrderModal.tsx +++ /dev/null @@ -1,195 +0,0 @@ -import { ChainId } from '@kyberswap/ks-sdk-core' -import { Trans } from '@lingui/macro' -import { useEffect, useMemo, useRef, useState } from 'react' -import { ChevronLeft, X } from 'react-feather' -import { useGetTotalActiveMakingAmountQuery } from 'services/limitOrder' - -import Column from 'components/Column' -import Modal from 'components/Modal' -import LimitOrderForm, { Label, LimitOrderFormHandle } from 'components/swapv2/LimitOrder/Form/LimitOrderForm' -import { useEstimateFee, useProcessCancelOrder } from 'components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder' -import CancelButtons from 'components/swapv2/LimitOrder/Modals/CancelButtons' -import { CancelStatus } from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' -import CancelStatusCountDown from 'components/swapv2/LimitOrder/Modals/CancelStatusCountDown' -import { calcInvert, calcPercentFilledOrder, calcRate, removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' -import { useIsSupportSoftCancelOrder } from 'components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders' -import { - CancelOrderFunction, - CancelOrderType, - EditOrderInfo, - LimitOrder, - LimitOrderStatus, - RateInfo, -} from 'components/swapv2/LimitOrder/type' -import { Z_INDEXS } from 'constants/styles' -import { useActiveWeb3React } from 'hooks' -import { useCurrencyV2 } from 'hooks/Tokens' -import { TransactionFlowState } from 'types/TransactionFlowState' -import { formatUnits } from 'utils/viem' - -enum Steps { - EDIT_ORDER, - REVIEW_ORDER, -} -export default function EditOrderModal({ - onSubmit, - onDismiss, - customChainId, - order, - note, - isOpen, - flowState, - setFlowState, -}: { - onSubmit: CancelOrderFunction - onDismiss: () => void - customChainId?: ChainId - order: LimitOrder - note: string - isOpen: boolean - flowState: TransactionFlowState - setFlowState: React.Dispatch> -}) { - const { chainId, account } = useActiveWeb3React() - const [step, setStep] = useState(Steps.EDIT_ORDER) - - const { status, makingAmount, takingAmount, makerAsset, takerAsset, filledTakingAmount, expiredAt } = order - const currencyIn = useCurrencyV2(makerAsset, customChainId) ?? undefined - const currencyOut = useCurrencyV2(takerAsset, customChainId) ?? undefined - const inputAmount = currencyIn ? formatUnits(BigInt(makingAmount), currencyIn.decimals) : '' - const outputAmount = currencyOut ? formatUnits(BigInt(takingAmount), currencyOut.decimals) : '' - - const formatIn = inputAmount ? removeTrailingZero(inputAmount) : inputAmount - const formatOut = outputAmount ? removeTrailingZero(outputAmount) : outputAmount - const defaultExpire = new Date(expiredAt * 1000) - const rate = currencyOut ? calcRate(formatIn, formatOut, currencyOut.decimals) : '' - const defaultRate: RateInfo = { rate, invertRate: calcInvert(rate), invert: false } - const filled = currencyOut ? calcPercentFilledOrder(filledTakingAmount, takingAmount, currencyOut.decimals) : 0 - - const { data: defaultActiveMakingAmount } = useGetTotalActiveMakingAmountQuery( - { chainId, tokenAddress: currencyIn?.wrapped.address ?? '', account: account ?? '' }, - { skip: !currencyIn || !account }, - ) - - const { onClickGaslessCancel, onClickHardCancel, expiredTime, cancelStatus, setCancelStatus } = useProcessCancelOrder( - { - isOpen, - onDismiss, - onSubmit, - getOrders: () => (order ? [order] : []), - isEdit: true, - }, - ) - - const isSupportSoftCancelOrder = useIsSupportSoftCancelOrder() - const { orderSupportGasless: supportGasLessCancel, chainSupportGasless } = isSupportSoftCancelOrder(order) - const [cancelType, setCancelType] = useState(CancelOrderType.GAS_LESS_CANCEL) - useEffect(() => { - setCancelType(supportGasLessCancel ? CancelOrderType.GAS_LESS_CANCEL : CancelOrderType.HARD_CANCEL) - }, [supportGasLessCancel]) - - const orders = useMemo(() => (order ? [order] : []), [order]) - - const estimateGas = useEstimateFee({ orders }) - - const isReviewOrder = step === Steps.REVIEW_ORDER - const onBack = () => { - setStep(Steps.EDIT_ORDER) - setFlowState(v => ({ ...v, showConfirm: false })) - } - const onNext = () => { - setStep(Steps.REVIEW_ORDER) - setFlowState(v => ({ ...v, showConfirm: true })) - } - - const isWaiting = cancelStatus === CancelStatus.WAITING - const showReview = isReviewOrder && isWaiting - - const ref = useRef(null) - const renderCancelButtons = () => { - const hasChangeInfo = step === Steps.EDIT_ORDER ? ref.current?.hasChangedOrderInfo?.() : true - const disabledGasLessCancel = !hasChangeInfo || !supportGasLessCancel || flowState.attemptingTxn - const disabledHardCancel = !hasChangeInfo || flowState.attemptingTxn - return ( - <> - {isReviewOrder && ( - - )} - Gasless Edit, - hardCancelGasless: Hard Edit, - confirmBtnText: isReviewOrder ? Place Order : Edit Order, - disabledConfirm: flowState.attemptingTxn || (disabledGasLessCancel && disabledHardCancel), - }} - /> - - ) - } - - const editOrderInfo: EditOrderInfo = { isEdit: true, gasFee: estimateGas, cancelType, renderCancelButtons } - return ( - -
-
- {showReview ? :
} - {showReview ? Review your order : Edit Order} - -
- - - - {status === LimitOrderStatus.PARTIALLY_FILLED && ( - - )} - - - {isWaiting && ( - - )} -
- - ) -} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx index 24e58ddb97..ea95345d39 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx @@ -1,6 +1,6 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' -import { forwardRef, memo, useImperativeHandle } from 'react' +import { memo } from 'react' import { ButtonLight, ButtonPrimary, ButtonWarning } from 'components/Button' import DateTimePicker from 'components/DateTimePicker' @@ -15,7 +15,6 @@ import ProcessingOrderModal from 'components/swapv2/LimitOrder/Modals/Processing import TradePrice from 'components/swapv2/LimitOrder/TradePrice' import useLimitOrderExecution from 'components/swapv2/LimitOrder/hooks/useLimitOrderExecution' import useLimitOrderFormState from 'components/swapv2/LimitOrder/hooks/useLimitOrderFormState' -import { EditOrderInfo, LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/type' import { Z_INDEXS } from 'constants/styles' import { useActiveWeb3React } from 'hooks' import { NETWORKS_INFO } from 'hooks/useChainsConfig' @@ -23,13 +22,6 @@ import { useChangeNetwork } from 'hooks/web3/useChangeNetwork' import ErrorWarningPanel from 'pages/Bridge/ErrorWarning' import { useWalletModalToggle } from 'state/application/hooks' import { TransactionFlowState } from 'types/TransactionFlowState' -import { cn } from 'utils/cn' - -export const Label = ({ children, className, ...rest }: React.HTMLAttributes) => ( -
- {children} -
-) type BaseProps = { currencyIn: Currency | undefined @@ -41,58 +33,21 @@ type BaseProps = { } type CreateLimitOrderFormProps = BaseProps & { - mode?: 'create' - defaultInputAmount?: string - defaultOutputAmount?: string - defaultActiveMakingAmount?: string - defaultExpire?: Date - defaultRate?: RateInfo - orderInfo?: never - editOrderInfo?: never useUrlParams?: boolean } -type EditLimitOrderFormProps = BaseProps & { - mode: 'edit' - defaultInputAmount: string - defaultOutputAmount: string - defaultActiveMakingAmount: string - defaultExpire: Date - defaultRate: RateInfo - orderInfo: LimitOrder - editOrderInfo: EditOrderInfo - useUrlParams?: never -} - -type Props = CreateLimitOrderFormProps | EditLimitOrderFormProps - -export type LimitOrderFormHandle = { - hasChangedOrderInfo: () => boolean -} -const LimitOrderForm = forwardRef(function LimitOrderForm( - { - currencyIn, - currencyOut, - mode = 'create', - defaultInputAmount = '', - defaultOutputAmount = '', - defaultActiveMakingAmount = '', - defaultExpire, - defaultRate = { rate: '', invertRate: '', invert: false }, - note = '', - orderInfo, - flowState, - setFlowState, - zIndexToolTip = Z_INDEXS.TOOL_TIP_ERROR_INPUT_SWAP_FORM, - editOrderInfo, - useUrlParams, - }, - ref, -) { +const LimitOrderForm = ({ + currencyIn, + currencyOut, + note = '', + flowState, + setFlowState, + zIndexToolTip = Z_INDEXS.TOOL_TIP_ERROR_INPUT_SWAP_FORM, + useUrlParams, +}: CreateLimitOrderFormProps) => { const { changeNetwork } = useChangeNetwork() const { account } = useActiveWeb3React() const toggleWalletModal = useWalletModalToggle() - const isEdit = mode === 'edit' const { chainId, walletChainId, @@ -127,19 +82,12 @@ const LimitOrderForm = forwardRef(function LimitOrd } = useLimitOrderFormState({ currencyIn, currencyOut, - defaultInputAmount, - defaultOutputAmount, - defaultExpire, - defaultRate, - isEdit, useUrlParams, }) const deltaRate = useGetDeltaRateLimitOrder({ marketPrice: tradeInfo, rateInfo }) const { - checkingAllowance, estimateUSD, handleMaxInput, - hasChangedOrderInfo, hasInputError, hidePreview, hideProcessingOrder, @@ -147,7 +95,6 @@ const LimitOrderForm = forwardRef(function LimitOrd insufficientBalance, insufficientBalanceText, isNotFillAllInput, - onSubmitCreateOrderWithTracking, outPutError, processingOrder, retryProcessingOrder, @@ -160,13 +107,7 @@ const LimitOrderForm = forwardRef(function LimitOrd } = useLimitOrderExecution({ currencyIn, currencyOut, - defaultActiveMakingAmount, - defaultInputAmount, - defaultRate, - defaultExpire, - orderInfo, setFlowState, - isEdit, chainId, networkName: networkInfo.name, searchParams, @@ -183,10 +124,6 @@ const LimitOrderForm = forwardRef(function LimitOrd switchToWeth, }) - useImperativeHandle(ref, () => ({ - hasChangedOrderInfo, - })) - const styleTooltip = { maxWidth: '250px', zIndex: zIndexToolTip } const disableReviewButton = isNotFillAllInput || !!hasInputError || insufficientBalance const reviewButtonContent = ( @@ -203,12 +140,6 @@ const LimitOrderForm = forwardRef(function LimitOrd Connect - ) : isEdit ? ( - checkingAllowance ? ( - {reviewButtonContent} - ) : ( - editOrderInfo?.renderCancelButtons?.() || null - ) ) : warningMessage.length > 0 && !disableReviewButton ? ( {reviewButtonContent} ) : ( @@ -217,33 +148,6 @@ const LimitOrderForm = forwardRef(function LimitOrd ) - const renderConfirmModal = (showConfirmContent = false) => ( - - ) - - if (isEdit && flowState.showConfirm) - return ( - <> - {renderConfirmModal(true)} - {actionButton} - - ) return ( <>
@@ -258,8 +162,6 @@ const LimitOrderForm = forwardRef(function LimitOrd outPutError={outPutError} estimateUsdIn={estimateUSD.input} estimateUsdOut={estimateUSD.output} - showApproveFlow={false} - isEdit={isEdit} rotate={rotate} styleTooltip={styleTooltip} onSetInput={onSetInput} @@ -313,7 +215,21 @@ const LimitOrderForm = forwardRef(function LimitOrd {actionButton}
- {renderConfirmModal()} + (function LimitOrd /> ) -}) +} export default memo(LimitOrderForm) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx index 25b0fe8c12..6d53736e08 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx @@ -20,8 +20,6 @@ type Props = { outPutError: string | ReactNode estimateUsdIn: string | undefined estimateUsdOut: string | undefined - showApproveFlow: boolean - isEdit: boolean rotate: boolean styleTooltip: CSSProperties onSetInput: (input: string) => void @@ -44,8 +42,6 @@ export default function LimitOrderTokenSection({ outPutError, estimateUsdIn, estimateUsdOut, - showApproveFlow, - isEdit, rotate, styleTooltip, onSetInput, @@ -84,8 +80,6 @@ export default function LimitOrderTokenSection({ maxCurrencySymbolLength={6} filterWrap onClickSelect={trackingTouchSelectToken} - lockIcon={showApproveFlow} - disableCurrencySelect={isEdit} label={
@@ -459,7 +456,6 @@ export default function OrderItem({ expand={expand} txHash={txHash} onCancelOrder={onCancelOrder} - onEditOrder={onEditOrder} isCancelling={isCancelling} /> diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx index 7a9d796cd3..465cc0fd22 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx @@ -13,7 +13,6 @@ import Pagination from 'components/Pagination' import Row from 'components/Row' import SearchInput from 'components/SearchInput' import Select from 'components/Select' -import EditOrderModal from 'components/swapv2/LimitOrder/EditOrder/EditOrderModal' import OrderItem from 'components/swapv2/LimitOrder/ListOrder/OrderItem' import TabSelector from 'components/swapv2/LimitOrder/ListOrder/TabSelector' import TableHeader from 'components/swapv2/LimitOrder/ListOrder/TableHeader' @@ -21,7 +20,6 @@ import useRequestCancelOrder from 'components/swapv2/LimitOrder/ListOrder/useReq import CancelOrderModal from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' import { ACTIVE_ORDER_OPTIONS, CLOSE_ORDER_OPTIONS } from 'components/swapv2/LimitOrder/const' import { - calcPercentFilledOrder, formatAmountOrder, formatRateLimitOrder, getPayloadTracking, @@ -36,7 +34,6 @@ import usePageLocation from 'hooks/usePageLocation' import useParsedQueryString from 'hooks/useParsedQueryString' import useShowLoadingAtLeastTime from 'hooks/useShowLoadingAtLeastTime' import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' -import { useLimitState } from 'state/limit/hooks' import { useTokenPricesWithLoading } from 'state/tokenPrices/hooks' import { cn } from 'utils/cn' import { @@ -83,9 +80,6 @@ export default function ListMyOrder({ customChainId }: { customChainId?: ChainId ) const [isOpenCancel, setIsOpenCancel] = useState(false) - const [isOpenEdit, setIsOpenEdit] = useState(false) - const { ordersNeedCreated: ordersUpdating } = useLimitState() - const { isOrderCancelling } = useCancellingOrders() const { trackingHandler } = useTracking() @@ -228,12 +222,6 @@ export default function ListMyOrder({ customChainId }: { customChainId?: ChainId }, 300) }, [setFlowState]) - const hideEditModal = useCallback(() => { - setFlowState(TRANSACTION_STATE_DEFAULT) - setCurrentOrder(undefined) - setIsOpenEdit(false) - }, [setFlowState]) - const showConfirmCancel = useCallback( (order?: LimitOrder) => { setCurrentOrder(order) @@ -247,17 +235,6 @@ export default function ListMyOrder({ customChainId }: { customChainId?: ChainId [trackingHandler, setFlowState, networkInfo], ) - const showEditOrderModal = useCallback( - (order: LimitOrder) => { - setFlowState({ ...TRANSACTION_STATE_DEFAULT }) - setCurrentOrder(order) - setIsOpenEdit(true) - setIsCancelAll(false) - trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_EDIT_ORDER, getPayloadTracking(order, networkInfo.name)) - }, - [trackingHandler, networkInfo.name, setFlowState], - ) - const totalOrderNotCancelling = useMemo(() => { return orders.filter(e => !isOrderCancelling(e)).length }, [orders, isOrderCancelling]) @@ -270,15 +247,6 @@ export default function ListMyOrder({ customChainId }: { customChainId?: ChainId const disabledBtnCancelAll = totalOrderNotCancelling === 0 const isTabActive = isActiveStatus(orderType) - useEffect(() => { - const orderCancelling = orders.length - totalOrderNotCancelling - window.onbeforeunload = () => (orderCancelling > 0 && ordersUpdating.length > 0 ? '' : null) // return null will not show confirm, else will show - }, [totalOrderNotCancelling, orders, ordersUpdating]) - - const filledPercent = - currentOrder && - calcPercentFilledOrder(currentOrder.filledTakingAmount, currentOrder.takingAmount, currentOrder.takerAssetDecimals) - return (
@@ -320,7 +288,6 @@ export default function ListMyOrder({ customChainId }: { customChainId?: ChainId key={order.id} order={order} onCancelOrder={showConfirmCancel} - onEditOrder={showEditOrderModal} tokenPrices={tokenPrices} hasOrderCancelling={orders.some(isOrderCancelling)} /> @@ -378,23 +345,6 @@ export default function ListMyOrder({ customChainId }: { customChainId?: ChainId order={currentOrder} isCancelAll={isCancelAll} /> - - {currentOrder && isOpenEdit && ( - - )}
) } diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx index 1e9530d788..825f27334f 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx @@ -12,7 +12,6 @@ import { wagmiConfig } from 'components/Web3Provider' import { CancelStatus } from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' import { formatAmountOrder, getErrorMessage, getPayloadTracking } from 'components/swapv2/LimitOrder/helpers' import useCancellingOrders from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' -import useSignOrder from 'components/swapv2/LimitOrder/hooks/useSignOrder' import { CancelOrderFunction, CancelOrderResponse, @@ -22,7 +21,6 @@ import { import { LIMIT_ORDER_ABI } from 'constants/abis' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React, useWeb3React } from 'hooks' -import { useLimitActionHandlers, useLimitState } from 'state/limit/hooks' import { useTransactionAdder } from 'state/transactions/hooks' import { TRANSACTION_TYPE } from 'state/transactions/type' import { TransactionFlowState } from 'types/TransactionFlowState' @@ -179,19 +177,7 @@ const useRequestCancelOrder = ({ return resp } - const { removeOrderNeedCreated, pushOrderNeedCreated } = useLimitActionHandlers() - const signOrder = useSignOrder(setFlowState) - const { orderEditing } = useLimitState() - - const onCancelOrder = async ({ - orders, - cancelType, - isEdit, - }: { - orders: LimitOrder[] - cancelType: CancelOrderType - isEdit?: boolean - }) => { + const onCancelOrder = async ({ orders, cancelType }: { orders: LimitOrder[]; cancelType: CancelOrderType }) => { try { setFlowState({ ...TRANSACTION_STATE_DEFAULT, @@ -199,17 +185,11 @@ const useRequestCancelOrder = ({ showConfirm: true, attemptingTxn: true, }) - if (orderEditing && isEdit) { - // pre-sign order - const { signature, salt } = await signOrder(orderEditing) - pushOrderNeedCreated({ ...orderEditing, salt, signature }) - } const gaslessCancel = cancelType === CancelOrderType.GAS_LESS_CANCEL const resp = await (gaslessCancel ? requestGasLessCancelOrder(orders) : requestHardCancelOrder(orders?.[0])) - setFlowState(state => ({ ...state, attemptingTxn: false, showConfirm: !!(isEdit && gaslessCancel) })) + setFlowState(state => ({ ...state, attemptingTxn: false })) return resp } catch (error) { - if (isEdit && orders[0]) removeOrderNeedCreated(orders[0].id) setFlowState(state => ({ ...state, attemptingTxn: false, @@ -227,13 +207,11 @@ export const useProcessCancelOrder = ({ onDismiss, onSubmit, getOrders, - isEdit, }: { onSubmit: CancelOrderFunction onDismiss: () => void isOpen: boolean getOrders: (v: boolean) => LimitOrder[] - isEdit?: boolean }) => { const { chainId } = useActiveWeb3React() const [expiredTime, setExpiredTime] = useState(0) @@ -264,14 +242,14 @@ export const useProcessCancelOrder = ({ const gasLessCancel = type === CancelOrderType.GAS_LESS_CANCEL const orders = getOrders(gasLessCancel) try { - const data: CancelOrderResponse = await onSubmit({ orders, cancelType: type, isEdit }) + const data: CancelOrderResponse = await onSubmit({ orders, cancelType: type }) if (signal.aborted) return setCancelStatus(gasLessCancel ? CancelStatus.COUNTDOWN : CancelStatus.WAITING) const expired = data?.orders?.[0]?.operatorSignatureExpiredAt if (expired) { setExpiredTime(expired) if (expired * 1000 < Date.now()) { - isEdit ? onDismiss() : setCancelStatus(CancelStatus.CANCEL_DONE) + setCancelStatus(CancelStatus.CANCEL_DONE) } } else onDismiss() } catch (error) { diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx index e17581e306..331eea2e83 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx @@ -24,16 +24,14 @@ const ButtonWrapper = ({ children, style }: { children: ReactNode; style?: CSSPr ) const ButtonGroup = ({ - isEdit, buttonGasless, - buttonHardEdit, + buttonHardCancel, gasAmountDisplay, style, showGaslessNote = true, }: { - isEdit?: boolean buttonGasless: ReactNode - buttonHardEdit: ReactNode + buttonHardCancel: ReactNode gasAmountDisplay: string style?: CSSProperties showGaslessNote?: boolean @@ -44,7 +42,7 @@ const ButtonGroup = ({ {buttonGasless} {showGaslessNote && ( - {isEdit ? Edit the order without paying gas. : Cancel without paying gas.} + Cancel without paying gas.
Cancellation may not be instant.{' '} Learn more ↗︎ @@ -53,13 +51,9 @@ const ButtonGroup = ({ )} - {buttonHardEdit} + {buttonHardCancel} - {isEdit ? ( - Edit immediately by paying {gasAmountDisplay} gas fees. - ) : ( - Cancel immediately by paying {gasAmountDisplay} gas fees. - )}{' '} + Cancel immediately by paying {gasAmountDisplay} gas fees.{' '} Learn more ↗︎ @@ -86,7 +80,6 @@ const CancelButtons = ({ onClickHardCancel, onClickGaslessCancel, onSubmit, - isEdit, estimateGas, confirmOnly = false, cancelType, @@ -108,7 +101,6 @@ const CancelButtons = ({ onSubmit?: () => void onClickGaslessCancel: () => void onClickHardCancel: () => void - isEdit?: boolean // else cancel estimateGas: string confirmOnly?: boolean cancelType: CancelOrderType @@ -127,12 +119,10 @@ const CancelButtons = ({ const onSetType = (type: CancelOrderType) => { setCancelType(type) if (!order) return - trackingHandler( - isEdit ? TRACKING_EVENT_TYPE.LO_CLICK_UPDATE_TYPE : TRACKING_EVENT_TYPE.LO_CLICK_CANCEL_TYPE, - getPayloadTracking(order, networkInfo.name, { - [isEdit ? 'edit_type' : 'cancel_type']: type === CancelOrderType.GAS_LESS_CANCEL ? 'Gasless' : 'Hard', - }), - ) + trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_CANCEL_TYPE, { + ...getPayloadTracking(order, networkInfo.name), + cancel_type: type === CancelOrderType.GAS_LESS_CANCEL ? 'Gasless' : 'Hard', + }) } const gasAmountDisplay = estimateGas @@ -168,7 +158,6 @@ const CancelButtons = ({ @@ -177,11 +166,11 @@ const CancelButtons = ({ Close } - buttonHardEdit={ + buttonHardCancel={   - {isEdit ? Hard Edit Instead : Hard Cancel Instead} + Hard Cancel Instead } /> @@ -192,7 +181,6 @@ const CancelButtons = ({ {!confirmOnly && ( } - buttonHardEdit={ + buttonHardCancel={ onSetType(CancelOrderType.HARD_CANCEL)} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx index 42c5cda2f7..130aa9c913 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx @@ -10,12 +10,11 @@ import TransactionConfirmationModal, { TransactionErrorContent } from 'component import { Container, Header, ListInfo, Note, Rate, Value } from 'components/swapv2/LimitOrder/Modals/styled' import { WORSE_PRICE_DIFF_THRESHOLD } from 'components/swapv2/LimitOrder/const' import { formatAmountOrder } from 'components/swapv2/LimitOrder/helpers' -import { CancelOrderType, EditOrderInfo, RateInfo } from 'components/swapv2/LimitOrder/type' +import { RateInfo } from 'components/swapv2/LimitOrder/type' import { useActiveWeb3React } from 'hooks' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import ErrorWarningPanel from 'pages/Bridge/ErrorWarning' import { TransactionFlowState } from 'types/TransactionFlowState' -import { formatDisplayNumber } from 'utils/numbers' const styleLogo = { width: 20, height: 20 } @@ -33,8 +32,6 @@ export default memo(function ConfirmOrderModal({ note, warningMessage, percentDiff, - editOrderInfo, - showConfirmContent, }: { onSubmit: () => void onDismiss: () => void @@ -49,13 +46,10 @@ export default memo(function ConfirmOrderModal({ note?: string warningMessage: ReactNode[] percentDiff: number - editOrderInfo?: EditOrderInfo - showConfirmContent: boolean }) { const { account } = useActiveWeb3React() const [confirmed, setConfirmed] = useState(false) const shouldShowConfirmFlow = percentDiff < WORSE_PRICE_DIFF_THRESHOLD - const { cancelType, gasFee, isEdit } = editOrderInfo || {} const listData = useMemo(() => { const nodes = [ @@ -94,29 +88,8 @@ export default memo(function ConfirmOrderModal({ ), }, ] - if (isEdit) - nodes.push({ - label: t`Edit Type`, - content: ( - - - {cancelType === CancelOrderType.GAS_LESS_CANCEL ? ( - Gasless Edit - ) : ( - - Hard Edit ( - - ~{formatDisplayNumber(gasFee, { style: 'currency', fractionDigits: 4 })} - {' '} - gas fees) - - )} - - - ), - }) return nodes - }, [account, currencyIn, currencyOut, inputAmount, rateInfo, outputAmount, expiredAt, isEdit, gasFee, cancelType]) + }, [account, currencyIn, currencyOut, inputAmount, rateInfo, outputAmount, expiredAt]) const handleDismiss = () => { onDismiss() @@ -191,22 +164,18 @@ export default memo(function ConfirmOrderModal({ )} - {isEdit ? null : ( -
- {renderConfirmPriceButton()} - {renderPlaceOrderButton()} -
- )} +
+ {renderConfirmPriceButton()} + {renderPlaceOrderButton()} +
) - if (showConfirmContent) return renderConfirmData() - const renderConfirmationContent = (): ReactNode => { return (
- {flowState.errorMessage && !isEdit ? ( + {flowState.errorMessage ? ( ) : ( @@ -226,7 +195,6 @@ export default memo(function ConfirmOrderModal({ isOpen={flowState.showConfirm} onDismiss={handleDismiss} attemptingTxn={flowState.attemptingTxn} - attemptingTxnContent={isEdit ? renderConfirmationContent : undefined} content={renderConfirmationContent} pendingText={flowState.pendingText || t`Placing order`} /> diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx index 36bc6fac83..53b5c7130e 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx @@ -10,7 +10,6 @@ import type { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/Limi import { SummaryNotifyOrderPlaced } from 'components/swapv2/LimitOrder/ListOrder/SummaryNotify' import { calcUsdPrices, - formatAmountOrder, getErrorMessage, getPayloadCreateOrder, removeTrailingZero, @@ -19,7 +18,7 @@ import useSignOrder from 'components/swapv2/LimitOrder/hooks/useSignOrder' import useValidateInputError from 'components/swapv2/LimitOrder/hooks/useValidateInputError' import useWarningCreateOrder from 'components/swapv2/LimitOrder/hooks/useWarningCreateOrder' import useWrapEthStatus from 'components/swapv2/LimitOrder/hooks/useWrapEthStatus' -import { CreateOrderParam, LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/type' +import { CreateOrderParam, RateInfo } from 'components/swapv2/LimitOrder/type' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { NativeCurrencies } from 'constants/tokens' import { useTokenAllowance } from 'data/Allowances' @@ -29,24 +28,17 @@ import type { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' import useWrapCallback from 'hooks/useWrapCallback' import { useNotify } from 'state/application/hooks' -import { useLimitActionHandlers, useLimitState } from 'state/limit/hooks' import { tryParseAmount } from 'state/swap/hooks' import { useCurrencyBalance } from 'state/wallet/hooks' import { TransactionFlowState } from 'types/TransactionFlowState' import { getCookieValue } from 'utils' -import { subscribeNotificationOrderCancelled, subscribeNotificationOrderExpired } from 'utils/firebase' +import { subscribeNotificationOrderExpired } from 'utils/firebase' import { maxAmountSpend } from 'utils/maxAmountSpend' type UseLimitOrderExecutionArgs = { currencyIn: Currency | undefined currencyOut: Currency | undefined - defaultActiveMakingAmount?: string - defaultInputAmount: string - defaultRate: RateInfo - defaultExpire?: Date - orderInfo?: LimitOrder setFlowState: React.Dispatch> - isEdit: boolean chainId: ChainId networkName: string searchParams: URLSearchParams @@ -79,13 +71,7 @@ export type ProcessingOrderState = { export default function useLimitOrderExecution({ currencyIn, currencyOut, - defaultActiveMakingAmount = '', - defaultInputAmount, - defaultRate, - defaultExpire, - orderInfo, setFlowState, - isEdit, chainId, networkName, searchParams, @@ -104,9 +90,6 @@ export default function useLimitOrderExecution({ const { account } = useActiveWeb3React() const notify = useNotify() const { trackingHandler } = useTracking() - const { ordersNeedCreated } = useLimitState() - const { removeOrderNeedCreated, setOrderEditing } = useLimitActionHandlers() - const [approvalSubmitted, setApprovalSubmitted] = useState(false) const [processingOrder, setProcessingOrder] = useState({ show: false, steps: [], @@ -116,11 +99,10 @@ export default function useLimitOrderExecution({ const approvalRef = useRef(ApprovalState.UNKNOWN) // Balances, allowance, and form readiness. - const { data: activeOrderMakingAmount = defaultActiveMakingAmount, refetch: getActiveMakingAmount } = - useGetTotalActiveMakingAmountQuery( - { chainId, tokenAddress: currencyIn?.wrapped.address ?? '', account: account ?? '' }, - { skip: !currencyIn || !account }, - ) + const { data: activeOrderMakingAmount = '', refetch: getActiveMakingAmount } = useGetTotalActiveMakingAmountQuery( + { chainId, tokenAddress: currencyIn?.wrapped.address ?? '', account: account ?? '' }, + { skip: !currencyIn || !account }, + ) const { isWrappingEth, setTxHashWrapped } = useWrapEthStatus(switchToWeth) @@ -140,18 +122,11 @@ export default function useLimitOrderExecution({ if (currencyIn.isNative) { return TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(0)) } - const value = TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(activeOrderMakingAmount)) - if (isEdit && orderInfo) { - const makingAmount = TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(orderInfo.makingAmount)) - return value.greaterThan(makingAmount) - ? value.subtract(makingAmount) - : TokenAmount.fromRawAmount(currencyIn, 0) - } - return value + return TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(activeOrderMakingAmount)) } } catch (error) {} return undefined - }, [currencyIn, activeOrderMakingAmount, isEdit, orderInfo]) + }, [currencyIn, activeOrderMakingAmount]) const balance = useCurrencyBalance(currencyIn, chainId) const nativeCurrency = NativeCurrencies[chainId] @@ -168,14 +143,7 @@ export default function useLimitOrderExecution({ const needsWrap = !!currencyIn?.isNative || !!wrapAmountForOrder const wrapInputCurrency = currencyIn?.isNative ? currencyIn : wrapAmountForOrder ? nativeCurrency : currencyIn const wrapTypedValue = wrapAmountForOrder ? wrapAmountForOrder.toExact() : inputAmount - const { execute: onWrap, inputError: wrapInputError } = useWrapCallback( - wrapInputCurrency, - WETH[chainId], - wrapTypedValue, - true, - chainId, - ) - const showWrap = needsWrap + const { execute: onWrap } = useWrapCallback(wrapInputCurrency, WETH[chainId], wrapTypedValue, true, chainId) const maxAmountInput = useMemo(() => { return maxAmountSpend(balance) }, [balance]) @@ -223,21 +191,12 @@ export default function useLimitOrderExecution({ const { inputError, outPutError } = useValidateInputError({ inputAmount, outputAmount, - balance, displayRate, - parsedActiveOrderMakingAmount: undefined, currencyIn, - wrapInputError, - showWrap, currencyOut, - showInsufficientBalanceError: false, }) const hasInputError = Boolean(inputError || outPutError) - const checkingAllowance = - !(currencyIn && parsedActiveOrderMakingAmount?.currency?.equals(currencyIn)) || - !(currencyIn && currentAllowance?.currency?.equals(currencyIn)) - const isNotFillAllInput = [outputAmount, inputAmount, currencyIn, currencyOut, displayRate].some(e => !e) const estimateUSD = useMemo(() => { @@ -251,15 +210,6 @@ export default function useLimitOrderExecution({ }) }, [inputAmount, outputAmount, tradeInfo, currencyIn, currencyOut]) - const showApproveFlow = - !checkingAllowance && - !showWrap && - !isNotFillAllInput && - (approval === ApprovalState.NOT_APPROVED || - approval === ApprovalState.PENDING || - !enoughAllowance || - (approvalSubmitted && approval === ApprovalState.APPROVED)) - const warningMessage = useWarningCreateOrder({ estimateUSD: estimateUSD.rawInput, currencyIn, @@ -303,30 +253,28 @@ export default function useLimitOrderExecution({ const showPreview = () => { if (!currencyIn || !currencyOut || !outputAmount || !inputAmount || !displayRate) return setFlowState({ ...TRANSACTION_STATE_DEFAULT, showConfirm: true }) - if (!isEdit) { - trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_REVIEW_PLACE_ORDER, { - from_token: currencyIn.symbol, - to_token: currencyOut.symbol, - from_network: chainId, - trade_qty: inputAmount, - }) - trackingHandler(TRACKING_EVENT_TYPE.LO_REVIEW_OPENED, { - side: rateInfo.invert ? 'buy' : 'sell', - from_token: currencyIn.symbol, - from_token_address: getTokenAddress(currencyIn), - to_token: currencyOut.symbol, - to_token_address: getTokenAddress(currencyOut), - pair: `${currencyIn.symbol}/${currencyOut.symbol}`, - limit_price: displayRate, - amount_in: inputAmount, - amount_in_usd: estimateUSD.rawInput || undefined, - amount_out_estimated: outputAmount, - expiry: displayTime, - market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, - price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, - chain: networkName, - }) - } + trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_REVIEW_PLACE_ORDER, { + from_token: currencyIn.symbol, + to_token: currencyOut.symbol, + from_network: chainId, + trade_qty: inputAmount, + }) + trackingHandler(TRACKING_EVENT_TYPE.LO_REVIEW_OPENED, { + side: rateInfo.invert ? 'buy' : 'sell', + from_token: currencyIn.symbol, + from_token_address: getTokenAddress(currencyIn), + to_token: currencyOut.symbol, + to_token_address: getTokenAddress(currencyOut), + pair: `${currencyIn.symbol}/${currencyOut.symbol}`, + limit_price: displayRate, + amount_in: inputAmount, + amount_in_usd: estimateUSD.rawInput || undefined, + amount_out_estimated: outputAmount, + expiry: displayTime, + market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, + price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, + chain: networkName, + }) } const hidePreview = useCallback(() => { @@ -413,26 +361,6 @@ export default function useLimitOrderExecution({ }) }, []) - const onWrapToken = async () => { - try { - if (isNotFillAllInput || wrapInputError || isWrappingEth || hasInputError) return - const amount = formatAmountOrder(inputAmount) - const wethSymbol = WETH[chainId].symbol - const inSymbol = currencyIn?.symbol - setFlowState(state => ({ - ...state, - attemptingTxn: true, - showConfirm: true, - pendingText: t`Wrapping ${amount} ${inSymbol} to ${amount} ${wethSymbol}`, - })) - const hash = await onWrap?.() - if (hash) setTxHashWrapped(hash) - setFlowState(state => ({ ...state, showConfirm: false })) - } catch (error) { - handleError(error) - } - } - const trackingPlaceOrder = useCallback( (type: TRACKING_EVENT_TYPE, data = {}) => { trackingHandler(type, { @@ -493,7 +421,6 @@ export default function useLimitOrderExecution({ inputAmount, outputAmount, expiredAt, - nativeOutput: currencyOut?.isNative || false, }) if (!order_id) return @@ -656,12 +583,6 @@ export default function useLimitOrderExecution({ // External state synchronization. useEffect(() => { approvalRef.current = approval - if (approval === ApprovalState.PENDING) { - setApprovalSubmitted(true) - } - if (approval === ApprovalState.NOT_APPROVED) { - setApprovalSubmitted(false) - } }, [approval]) useEffect(() => { @@ -670,83 +591,17 @@ export default function useLimitOrderExecution({ runProcessingStep(currentStep) }, [processingOrder.currentStep, processingOrder.errorStep, processingOrder.show, runProcessingStep]) - useEffect(() => { - if (!isEdit || !orderInfo?.id) return - setOrderEditing({ - orderId: orderInfo.id, - account, - chainId, - currencyIn, - currencyOut, - inputAmount, - outputAmount, - expiredAt, - nativeOutput: currencyOut?.isNative || false, - }) - }, [ - setOrderEditing, - account, - chainId, - currencyIn, - currencyOut, - inputAmount, - outputAmount, - expiredAt, - orderInfo?.id, - isEdit, - ]) - - const refSubmitCreateOrder = useRef(onSubmitCreateOrder) - refSubmitCreateOrder.current = onSubmitCreateOrder - useEffect(() => { if (!account) return - const unsubscribeCancelled = subscribeNotificationOrderCancelled(account, chainId, data => { - data?.orders.forEach(order => { - const findInfo = ordersNeedCreated.find(e => e.orderId === order.id) - if (!findInfo?.orderId) return - removeOrderNeedCreated(findInfo.orderId) - if (order.isSuccessful && !isEdit) { - refSubmitCreateOrder.current(findInfo) - } - }) - refreshActiveMakingAmount() - }) const unsubscribeExpired = subscribeNotificationOrderExpired(account, chainId, refreshActiveMakingAmount) return () => { - unsubscribeCancelled?.() unsubscribeExpired?.() } - }, [account, chainId, ordersNeedCreated, removeOrderNeedCreated, refreshActiveMakingAmount, isEdit]) - - const hasChangedOrderInfo = useCallback(() => { - return ( - isEdit && - !hasInputError && - (defaultInputAmount !== inputAmount || - defaultRate?.rate !== rateInfo.rate || - defaultExpire?.getTime() !== expiredAt) - ) - }, [ - defaultExpire, - defaultInputAmount, - defaultRate?.rate, - expiredAt, - hasInputError, - inputAmount, - isEdit, - rateInfo.rate, - ]) + }, [account, chainId, refreshActiveMakingAmount]) return { - approval, - approvalSubmitted, - approveCallback, - checkingAllowance, - enoughAllowance, estimateUSD, handleMaxInput, - hasChangedOrderInfo, hasInputError, hidePreview, hideProcessingOrder, @@ -754,20 +609,14 @@ export default function useLimitOrderExecution({ insufficientBalance, insufficientBalanceText, isNotFillAllInput, - isWrappingEth, - onSubmitCreateOrderWithTracking, - onWrapToken, outPutError, processingOrder, retryProcessingOrder, - showApproveFlow, showPreview, - showWrap, startProcessingOrder, trackingPriceSetOnBlur, trackingTouchInput, trackingTouchSelectToken, warningMessage, - wrapInputError, } } diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts index d136bf9bb1..5080172bee 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts @@ -19,41 +19,13 @@ import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' import { useLimitActionHandlers, useLimitState } from 'state/limit/hooks' import { formatTimeDuration } from 'utils/time' -const useInputAmount = ({ - defaultInputAmount, - isEdit, -}: { - defaultInputAmount?: string - isEdit: boolean -}): [string, (v: string) => void] => { - const { inputAmount } = useLimitState() - const { setInputValue } = useLimitActionHandlers() - - const localState = useState(defaultInputAmount || '') - return isEdit ? localState : [inputAmount, setInputValue] -} - export type LimitOrderFormStateArgs = { currencyIn: Currency | undefined currencyOut: Currency | undefined - defaultInputAmount?: string - defaultOutputAmount?: string - defaultExpire?: Date - defaultRate: RateInfo - isEdit: boolean useUrlParams?: boolean } -export default function useLimitOrderFormState({ - currencyIn, - currencyOut, - defaultInputAmount = '', - defaultOutputAmount = '', - defaultExpire, - defaultRate, - isEdit, - useUrlParams, -}: LimitOrderFormStateArgs) { +export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrlParams }: LimitOrderFormStateArgs) { const { chainId: walletChainId, networkInfo } = useActiveWeb3React() const { trackingHandler } = useTracking() const [searchParams, setSearchParams] = useSearchParams() @@ -66,16 +38,17 @@ export default function useLimitOrderFormState({ setCurrencyIn: updateCurrencyIn, setCurrencyOut: updateCurrencyOut, switchCurrency: rotateCurrency, + setInputValue: setInputAmount, } = useLimitActionHandlers() + const { inputAmount } = useLimitState() const autoFillMarketPrice = useRef(false) - const [inputAmount, setInputAmount] = useInputAmount({ defaultInputAmount, isEdit }) - const [outputAmount, setOutputAmount] = useState(defaultOutputAmount) - const [rateInfo, setRateInfo] = useState(defaultRate) + const [outputAmount, setOutputAmount] = useState('') + const [rateInfo, setRateInfo] = useState({ rate: '', invertRate: '', invert: false }) const [expire, setExpire] = useState(DEFAULT_EXPIRED) const [showDatePicker, setShowDatePicker] = useState(false) - const [customDateExpire, setCustomDateExpire] = useState(defaultExpire) + const [customDateExpire, setCustomDateExpire] = useState() const [rotate, setRotate] = useState(false) const [expanded, setExpanded] = useState(false) @@ -243,7 +216,6 @@ export default function useLimitOrderFormState({ } const handleRotateClick = () => { - if (isEdit) return trackingHandler(TRACKING_EVENT_TYPE.LO_SIDE_SELECTED, { side: rateInfo.invert ? 'sell' : 'buy', from_token: currencyOut?.symbol, @@ -293,19 +265,19 @@ export default function useLimitOrderFormState({ } const onResetForm = useCallback(() => { - setInputAmount(defaultInputAmount) - setOutputAmount(defaultOutputAmount) - setRateInfo(defaultRate) + setInputAmount('') + setOutputAmount('') + setRateInfo({ rate: '', invertRate: '', invert: false }) setExpire(DEFAULT_EXPIRED) setCustomDateExpire(undefined) - }, [defaultInputAmount, defaultOutputAmount, defaultRate, setInputAmount]) + }, [setInputAmount]) useEffect(() => { - if (tradeInfo && !autoFillMarketPrice.current && !loadingTrade && !defaultRate?.rate) { + if (tradeInfo && !autoFillMarketPrice.current && !loadingTrade) { autoFillMarketPrice.current = true setPriceRateMarket(true) } - }, [tradeInfo, setPriceRateMarket, loadingTrade, defaultRate?.rate]) + }, [tradeInfo, setPriceRateMarket, loadingTrade]) return { chainId, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts index 7ae774924b..0359f1a259 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts @@ -18,8 +18,7 @@ export default function useSignOrder( return useCallback( async (params: CreateOrderParam) => { - const { currencyIn, currencyOut, inputAmount, outputAmount, signature, salt } = params - if (signature && salt) return { signature, salt } + const { currencyIn, currencyOut, inputAmount, outputAmount } = params if (!currencyIn || !currencyOut || !account) return { signature: '', salt: '' } const payload = getPayloadCreateOrder(params) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx index a1e018d1aa..c0736d26b5 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx @@ -1,95 +1,39 @@ -import { Currency, CurrencyAmount } from '@kyberswap/ks-sdk-core' -import { Trans, t } from '@lingui/macro' -import JSBI from 'jsbi' +import { Currency } from '@kyberswap/ks-sdk-core' +import { t } from '@lingui/macro' import { useMemo } from 'react' import { useActiveWeb3React } from 'hooks' -import { useLimitActionHandlers } from 'state/limit/hooks' import { tryParseAmount } from 'state/swap/hooks' -import { formatDisplayNumber } from 'utils/numbers' const useValidateInputError = ({ inputAmount, outputAmount, - balance, displayRate, - parsedActiveOrderMakingAmount, currencyIn, - wrapInputError, - showWrap, currencyOut, - showInsufficientBalanceError = true, }: { currencyIn: Currency | undefined currencyOut: Currency | undefined - showWrap: boolean - wrapInputError: any - showInsufficientBalanceError?: boolean displayRate: string inputAmount: string outputAmount: string - parsedActiveOrderMakingAmount: CurrencyAmount | undefined - balance: CurrencyAmount | undefined }) => { const { account } = useActiveWeb3React() const parseInputAmount = tryParseAmount(inputAmount, currencyIn ?? undefined) - const { setInputValue } = useLimitActionHandlers() const inputError = useMemo(() => { try { if (!account) return if (parseFloat(inputAmount) === 0 && (parseFloat(outputAmount) === 0 || parseFloat(displayRate) === 0)) { return t`Invalid input amount` } - if (showInsufficientBalanceError && balance && parseInputAmount?.greaterThan(balance)) { - const symbol = currencyIn?.symbol - return t`Insufficient ${symbol} balance` - } - - const remainBalance = parsedActiveOrderMakingAmount ? balance?.subtract(parsedActiveOrderMakingAmount) : undefined - if (showInsufficientBalanceError && parseInputAmount && remainBalance?.lessThan(parseInputAmount)) { - const formatNum = formatDisplayNumber(remainBalance, { - style: 'decimal', - fractionDigits: 6, - allowDisplayNegative: true, - }) - return ( - - - Insufficient {currencyIn?.symbol} balance. -
- setInputValue(remainBalance.toExact())}> - {!remainBalance.equalTo(JSBI.BigInt(0)) ? '~' : ''} - {formatNum} {currencyIn?.symbol} - {' '} - remaining after deducting Active and Open orders. -
-
- ) - } - if (!parseInputAmount) { return t`Your input amount is invalid.` } - - if (showInsufficientBalanceError && showWrap && wrapInputError) return wrapInputError return } catch (error) { return } - }, [ - currencyIn, - balance, - inputAmount, - outputAmount, - displayRate, - parsedActiveOrderMakingAmount, - parseInputAmount, - showWrap, - wrapInputError, - setInputValue, - account, - showInsufficientBalanceError, - ]) + }, [inputAmount, outputAmount, displayRate, parseInputAmount, account]) const outPutError = useMemo(() => { if (outputAmount && !tryParseAmount(outputAmount, currencyOut)) { diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/type.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/type.ts index 4fa434ffe3..0458f6a220 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/type.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/type.ts @@ -112,16 +112,8 @@ export type RateInfo = { export type CancelOrderFunction = (data: { orders: LimitOrder[] cancelType: CancelOrderType - isEdit?: boolean }) => Promise -export type EditOrderInfo = { - cancelType?: CancelOrderType - gasFee?: string - isEdit?: boolean - renderCancelButtons: () => JSX.Element -} - export type CancelOrderResponse = { orders: { operatorSignatureExpiredAt: number }[] } @@ -134,9 +126,5 @@ export type CreateOrderParam = { inputAmount: string outputAmount: string expiredAt: number - nativeOutput: boolean - orderId?: number - signature?: string - salt?: string referral?: string } diff --git a/apps/kyberswap-interface/src/hooks/useTracking.ts b/apps/kyberswap-interface/src/hooks/useTracking.ts index 854bad659f..b1c682b9a7 100644 --- a/apps/kyberswap-interface/src/hooks/useTracking.ts +++ b/apps/kyberswap-interface/src/hooks/useTracking.ts @@ -164,11 +164,9 @@ export enum TRACKING_EVENT_TYPE { LO_CLICK_CANCEL_ORDER, LO_CANCEL_ORDER_SUBMITTED, LO_CLICK_REVIEW_PLACE_ORDER, - LO_CLICK_EDIT_ORDER, LO_DISPLAY_SETTING_CLICK, LO_CLICK_SUBSCRIBE_BTN, LO_CLICK_CANCEL_TYPE, - LO_CLICK_UPDATE_TYPE, LO_CLICK_GET_STARTED, LO_CLICK_WARNING_IN_SWAP, LO_REVIEW_OPENED, @@ -1187,10 +1185,6 @@ export default function useTracking(currencies?: { [field in Field]?: Currency } formoTrack('Limit Order - Review Order Click', payload) break } - case TRACKING_EVENT_TYPE.LO_CLICK_EDIT_ORDER: { - formoTrack('Limit Order - Update Order Click', payload) - break - } case TRACKING_EVENT_TYPE.LO_DISPLAY_SETTING_CLICK: { formoTrack('Limit Order - Display settings on Limit settings', payload) break @@ -1203,10 +1197,6 @@ export default function useTracking(currencies?: { [field in Field]?: Currency } formoTrack('Limit Order - Cancel Order Double Signature Click', payload) break } - case TRACKING_EVENT_TYPE.LO_CLICK_UPDATE_TYPE: { - formoTrack('Limit Order - Update Order Double Signature Click', payload) - break - } case TRACKING_EVENT_TYPE.LO_CLICK_GET_STARTED: { formoTrack('Limit Order - Get Started Click', payload) break diff --git a/apps/kyberswap-interface/src/locales/en-US.po b/apps/kyberswap-interface/src/locales/en-US.po index d6453e9a08..ef55fa5ef3 100644 --- a/apps/kyberswap-interface/src/locales/en-US.po +++ b/apps/kyberswap-interface/src/locales/en-US.po @@ -631,7 +631,6 @@ msgstr "Winner" msgid "TOTAL AMOUNT (USD)" msgstr "TOTAL AMOUNT (USD)" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx #: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "Review your order" msgstr "Review your order" @@ -2040,11 +2039,6 @@ msgstr "Smart Exit canceled: position liquidity is different than the signed amo msgid "You are undelegating your voting power from this address" msgstr "You are undelegating your voting power from this address" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx -msgid "Gasless Edit" -msgstr "Gasless Edit" - #: src/pages/Campaign/components/Information/info/stipLimitOrder.tsx msgid "<0>9,000 ARB is allocated for this campaign each week." msgstr "<0>9,000 ARB is allocated for this campaign each week." @@ -2169,10 +2163,6 @@ msgstr "Closed" msgid "in a 2-day finalization period before they become claimable." msgstr "in a 2-day finalization period before they become claimable." -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -msgid "Editing this order will automatically cancel your existing order and a new order will be created." -msgstr "Editing this order will automatically cancel your existing order and a new order will be created." - #: src/pages/Campaign/components/Information/info/stipAggregator.tsx #: src/pages/Campaign/components/Information/info/stipLimitOrder.tsx msgid "What are the different categories and how does it work?" @@ -3072,10 +3062,6 @@ msgstr "Trade" msgid "Stake KNC, Vote, Earn Rewards." msgstr "Stake KNC, Vote, Earn Rewards." -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx -msgid "Hard Edit (<0>~{0} gas fees)" -msgstr "Hard Edit (<0>~{0} gas fees)" - #: src/components/TransactionConfirmationModal/index.tsx msgid "Show more details" msgstr "Show more details" @@ -5275,10 +5261,6 @@ msgstr "Saving..." msgid "Cancel Orders Failed" msgstr "Cancel Orders Failed" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx -msgid "Hard Edit Instead" -msgstr "Hard Edit Instead" - #: src/pages/RemoveLiquidityProAmm/index.tsx msgid "More Information" msgstr "More Information" @@ -5511,10 +5493,6 @@ msgstr "Please connect wallet to view your Dashboard" msgid "Week {week}" msgstr "Week {week}" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -msgid "Your currently existing order is {filled}% filled." -msgstr "Your currently existing order is {filled}% filled." - #: src/components/ProAmm/ProAmmPooledTokens.tsx msgid "My Pool APR" msgstr "My Pool APR" @@ -5962,11 +5940,6 @@ msgstr "<0>Week 3 July 22 - July 28" msgid "Insufficient liquidity available. Please reload page or increase max slippage and try again!" msgstr "Insufficient liquidity available. Please reload page or increase max slippage and try again!" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -msgid "Edit Order" -msgstr "Edit Order" - #: src/pages/KyberDAO/StakeKNC/StakeKNCComponent.tsx msgid "Unstaking {inputValue} KNC from KyberDAO" msgstr "Unstaking {inputValue} KNC from KyberDAO" @@ -6160,7 +6133,6 @@ msgstr "How often is the data updated?" msgid "Current Cycle" msgstr "Current Cycle" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx #: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx #: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx #: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx @@ -6794,10 +6766,6 @@ msgstr "Insufficient Funds" msgid "Email Address" msgstr "Email Address" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx -msgid "Edit the order without paying gas." -msgstr "Edit the order without paying gas." - #: src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx #: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx msgid "Order Expired" @@ -8462,10 +8430,6 @@ msgstr "Half" msgid "Select chains" msgstr "Select chains" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -msgid "Hard Edit" -msgstr "Hard Edit" - #: src/components/Announcement/helpers.ts msgid "Cancelled by you" msgstr "Cancelled by you" diff --git a/apps/kyberswap-interface/src/locales/zh-CN.po b/apps/kyberswap-interface/src/locales/zh-CN.po index e79a92dd6a..e69716e9e1 100644 --- a/apps/kyberswap-interface/src/locales/zh-CN.po +++ b/apps/kyberswap-interface/src/locales/zh-CN.po @@ -631,7 +631,6 @@ msgstr "" msgid "TOTAL AMOUNT (USD)" msgstr "总金额(美元)" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx #: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "Review your order" msgstr "检查您的订单" @@ -2040,11 +2039,6 @@ msgstr "" msgid "You are undelegating your voting power from this address" msgstr "您正在从该地址撤销投票委托" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx -msgid "Gasless Edit" -msgstr "免 Gas 编辑" - #: src/pages/Campaign/components/Information/info/stipLimitOrder.tsx msgid "<0>9,000 ARB is allocated for this campaign each week." msgstr "本次活动每周分配 <0>9,000 ARB。" @@ -2169,10 +2163,6 @@ msgstr "已关闭" msgid "in a 2-day finalization period before they become claimable." msgstr "在最终 2 天确认期后才可领取" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -msgid "Editing this order will automatically cancel your existing order and a new order will be created." -msgstr "编辑订单将自动取消原订单并创建新订单" - #: src/pages/Campaign/components/Information/info/stipAggregator.tsx #: src/pages/Campaign/components/Information/info/stipLimitOrder.tsx msgid "What are the different categories and how does it work?" @@ -3072,10 +3062,6 @@ msgstr "交易" msgid "Stake KNC, Vote, Earn Rewards." msgstr "质押 KNC、投票、赚取奖励" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx -msgid "Hard Edit (<0>~{0} gas fees)" -msgstr "强制编辑(<0>~{0} Gas 费)" - #: src/components/TransactionConfirmationModal/index.tsx msgid "Show more details" msgstr "显示更多详情" @@ -5275,10 +5261,6 @@ msgstr "保存中……" msgid "Cancel Orders Failed" msgstr "取消订单失败" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx -msgid "Hard Edit Instead" -msgstr "改用强制编辑" - #: src/pages/RemoveLiquidityProAmm/index.tsx msgid "More Information" msgstr "更多信息" @@ -5511,10 +5493,6 @@ msgstr "请连接钱包以查看您的仪表板" msgid "Week {week}" msgstr "" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -msgid "Your currently existing order is {filled}% filled." -msgstr "您当前的订单已成交 {filled}%" - #: src/components/ProAmm/ProAmmPooledTokens.tsx msgid "My Pool APR" msgstr "我的池子 年化收益率" @@ -5962,11 +5940,6 @@ msgstr "<0>第 3 周 7 月 22 日 - 7 月 28 日" msgid "Insufficient liquidity available. Please reload page or increase max slippage and try again!" msgstr "可用流动性不足,请刷新页面或提高最大滑点后重试" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -msgid "Edit Order" -msgstr "编辑订单" - #: src/pages/KyberDAO/StakeKNC/StakeKNCComponent.tsx msgid "Unstaking {inputValue} KNC from KyberDAO" msgstr "从 KyberDAO 解除质押 {inputValue} KNC" @@ -6160,7 +6133,6 @@ msgstr "这些数据多久更新一次?" msgid "Current Cycle" msgstr "当前周期" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx #: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx #: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx #: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx @@ -6794,10 +6766,6 @@ msgstr "资金不足" msgid "Email Address" msgstr "邮箱地址" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx -msgid "Edit the order without paying gas." -msgstr "无需支付 Gas 编辑订单" - #: src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx #: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx msgid "Order Expired" @@ -8462,10 +8430,6 @@ msgstr "一半" msgid "Select chains" msgstr "选择链" -#: src/components/swapv2/LimitOrder/EditOrderModal.tsx -msgid "Hard Edit" -msgstr "强制编辑" - #: src/components/Announcement/helpers.ts msgid "Cancelled by you" msgstr "" diff --git a/apps/kyberswap-interface/src/state/index.ts b/apps/kyberswap-interface/src/state/index.ts index 19f6da93dc..22bae49f09 100644 --- a/apps/kyberswap-interface/src/state/index.ts +++ b/apps/kyberswap-interface/src/state/index.ts @@ -39,7 +39,6 @@ import burn from 'state/burn/reducer' import crossChainSwap from 'state/crossChainSwap' import customizeDexes from 'state/customizeDexes' import { updateVersion } from 'state/global/actions' -import limit from 'state/limit/reducer' import lists from 'state/lists/reducer' import mintV2 from 'state/mint/proamm/reducer' import mint from 'state/mint/reducer' @@ -84,7 +83,6 @@ const store = configureStore({ transactions, crossChainSwap, swap, - limit, mint, mintV2, burn, diff --git a/apps/kyberswap-interface/src/state/limit/actions.ts b/apps/kyberswap-interface/src/state/limit/actions.ts deleted file mode 100644 index 20af8c78dd..0000000000 --- a/apps/kyberswap-interface/src/state/limit/actions.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createAction } from '@reduxjs/toolkit' - -import { CreateOrderParam } from 'components/swapv2/LimitOrder/type' - -export const pushOrderNeedCreated = createAction('limit/pushOrderNeedCreated') -export const removeOrderNeedCreated = createAction('limit/removeOrderNeedCreated') - -export const setOrderEditing = createAction('limit/setOrderEditing') diff --git a/apps/kyberswap-interface/src/state/limit/hooks.ts b/apps/kyberswap-interface/src/state/limit/hooks.ts index 445a15fc4b..918b06dee9 100644 --- a/apps/kyberswap-interface/src/state/limit/hooks.ts +++ b/apps/kyberswap-interface/src/state/limit/hooks.ts @@ -1,20 +1,10 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { useCallback } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import { CreateOrderParam } from 'components/swapv2/LimitOrder/type' -import { AppDispatch, AppState } from 'state/index' import { Field } from 'state/swap/actions' import { useInputCurrency, useOutputCurrency, useSwapActionHandlers, useSwapState } from 'state/swap/hooks' -import { - pushOrderNeedCreated as pushOrderNeedCreatedAction, - removeOrderNeedCreated as removeOrderNeedCreatedAction, - setOrderEditing as setOrderEditingAction, -} from './actions' -import { LimitState } from './reducer' - -export function useLimitState(): LimitState & { +export function useLimitState(): { currencyIn: Currency | undefined currencyOut: Currency | undefined inputAmount: string @@ -24,12 +14,10 @@ export function useLimitState(): LimitState & { const currencyOut = useOutputCurrency() const { typedValue: inputAmount } = useSwapState() - const state = useSelector((state: AppState) => state.limit) - return { ...state, currencyIn, currencyOut, inputAmount } + return { currencyIn, currencyOut, inputAmount } } export function useLimitActionHandlers() { - const dispatch = useDispatch() const { onSwitchTokensV2, onCurrencySelection, onUserInput } = useSwapActionHandlers() const setInputValue = useCallback( @@ -53,34 +41,10 @@ export function useLimitActionHandlers() { [onCurrencySelection], ) - const pushOrderNeedCreated = useCallback( - (order: CreateOrderParam) => { - dispatch(pushOrderNeedCreatedAction(order)) - }, - [dispatch], - ) - - const removeOrderNeedCreated = useCallback( - (orderId: number) => { - dispatch(removeOrderNeedCreatedAction(orderId)) - }, - [dispatch], - ) - - const setOrderEditing = useCallback( - (order: CreateOrderParam) => { - dispatch(setOrderEditingAction(order)) - }, - [dispatch], - ) - return { switchCurrency: onSwitchTokensV2, setCurrencyIn, setCurrencyOut, - pushOrderNeedCreated, - removeOrderNeedCreated, - setOrderEditing, setInputValue, } } diff --git a/apps/kyberswap-interface/src/state/limit/reducer.ts b/apps/kyberswap-interface/src/state/limit/reducer.ts deleted file mode 100644 index bdc6409a80..0000000000 --- a/apps/kyberswap-interface/src/state/limit/reducer.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { createReducer } from '@reduxjs/toolkit' - -import { CreateOrderParam } from 'components/swapv2/LimitOrder/type' - -import { pushOrderNeedCreated, removeOrderNeedCreated, setOrderEditing } from './actions' - -export interface LimitState { - ordersNeedCreated: CreateOrderParam[] - orderEditing: CreateOrderParam | undefined -} - -const initialState: LimitState = { - ordersNeedCreated: [], // orders need to be created when cancel is completed - orderEditing: undefined, // order is editing -} - -export default createReducer(initialState, builder => - builder - .addCase(pushOrderNeedCreated, (state, { payload }) => { - state.ordersNeedCreated = [...state.ordersNeedCreated, payload] - }) - .addCase(removeOrderNeedCreated, (state, { payload: orderId }) => { - state.ordersNeedCreated = state.ordersNeedCreated.filter(e => e.orderId !== orderId) - }) - .addCase(setOrderEditing, (state, { payload: orderEditing }) => { - state.orderEditing = orderEditing - }), -) From 8f7f8719e48318e311ec6daa0c2abb84e5fd3cb4 Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Thu, 18 Jun 2026 11:12:13 +0700 Subject: [PATCH 07/52] refactor(limit-order): simplify create order flow --- .../InboxItemLimitOrder.tsx | 2 +- .../NotificationCenter/LimitOrder.tsx | 2 +- .../src/components/Announcement/helpers.ts | 2 +- .../src/components/Announcement/type.ts | 2 +- .../SwapModal/ConfirmSwapModalContent.tsx | 2 +- .../Form/LimitOrderExpirySection.tsx | 46 +- .../swapv2/LimitOrder/Form/LimitOrderForm.tsx | 309 +++++++------ .../LimitOrder/Form/LimitOrderRateSection.tsx | 71 +-- .../Form/LimitOrderTokenSection.tsx | 123 +++--- .../LimitOrder/{ => Form}/TradePrice.tsx | 0 .../LimitOrder/ListLimitOrder/TabSelector.tsx | 2 +- .../LimitOrder/ListLimitOrder/index.tsx | 2 +- .../LimitOrder/ListOrder/ActionButtons.tsx | 2 +- .../swapv2/LimitOrder/ListOrder/OrderItem.tsx | 2 +- .../LimitOrder/ListOrder/SummaryNotify.tsx | 2 +- .../LimitOrder/ListOrder/TabSelector.tsx | 2 +- .../swapv2/LimitOrder/ListOrder/index.tsx | 37 +- .../ListOrder/useRequestCancelOrder.tsx | 2 +- .../LimitOrder/Modals/CancelButtons.tsx | 5 +- .../LimitOrder/Modals/CancelOrderModal.tsx | 4 +- .../Modals/CancelStatusCountDown.tsx | 2 +- .../LimitOrder/Modals/ConfirmOrderModal.tsx | 10 +- .../Modals/ProcessingOrderModal.tsx | 36 +- .../Modals/{styled.tsx => components.tsx} | 4 +- .../swapv2/LimitOrder/OrderBook/OrderItem.tsx | 2 +- .../swapv2/LimitOrder/OrderBook/index.tsx | 2 +- .../src/components/swapv2/LimitOrder/const.ts | 77 ---- .../components/swapv2/LimitOrder/helpers.ts | 12 +- .../LimitOrder/hooks/useCancellingOrders.ts | 2 +- .../LimitOrder/hooks/useCreateLimitOrder.tsx | 180 ++++++++ .../hooks/useFetchActiveAllOrders.ts | 2 +- .../hooks/useLimitOrderExecution.tsx | 414 +++--------------- .../hooks/useLimitOrderFormState.ts | 21 +- .../hooks/useNotificationLimitOrder.tsx | 2 +- .../LimitOrder/hooks/useProcessingOrder.ts | 190 ++++++++ .../swapv2/LimitOrder/hooks/useSignOrder.ts | 2 +- .../hooks/useWarningCreateOrder.tsx | 23 +- .../components/swapv2/LimitOrder/index.tsx | 26 -- .../swapv2/LimitOrder/{type.ts => types.ts} | 23 + apps/kyberswap-interface/src/hooks/index.ts | 2 +- .../src/pages/PartnerSwap/index.tsx | 26 +- .../src/pages/SwapV3/index.tsx | 4 +- .../src/services/limitOrder.ts | 2 +- .../kyberswap-interface/src/utils/firebase.ts | 2 +- 44 files changed, 868 insertions(+), 817 deletions(-) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{ => Form}/TradePrice.tsx (100%) rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/{styled.tsx => components.tsx} (98%) delete mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/const.ts create mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx create mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useProcessingOrder.ts delete mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/index.tsx rename apps/kyberswap-interface/src/components/swapv2/LimitOrder/{type.ts => types.ts} (84%) diff --git a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx index e757025e0d..6f8140a974 100644 --- a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx @@ -22,7 +22,7 @@ import { import { AnnouncementTemplateLimitOrder } from 'components/Announcement/type' import { CheckCircle } from 'components/Icons' import { TokenLogoWithShadow } from 'components/Logo' -import { LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { APP_PATHS } from 'constants/index' import { NETWORKS_INFO } from 'constants/networks' import { useNavigateToUrl } from 'utils/redirect' diff --git a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx index de321e071d..78df389354 100644 --- a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx @@ -7,7 +7,7 @@ import { PrivateAnnouncementPropCenter } from 'components/Announcement/PrivateAn import { Desc, Time, Title, Wrapper } from 'components/Announcement/PrivateAnnoucement/NotificationCenter/styled' import { AnnouncementTemplateLimitOrder } from 'components/Announcement/type' import Logo from 'components/Logo' -import { LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { APP_PATHS } from 'constants/index' import { formatTime } from 'utils/time' diff --git a/apps/kyberswap-interface/src/components/Announcement/helpers.ts b/apps/kyberswap-interface/src/components/Announcement/helpers.ts index 3351df4cf1..6bf9900fea 100644 --- a/apps/kyberswap-interface/src/components/Announcement/helpers.ts +++ b/apps/kyberswap-interface/src/components/Announcement/helpers.ts @@ -9,7 +9,7 @@ import { SmartExitReason, SmartExitStatus, } from 'components/Announcement/type' -import { LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { EnvKeys, NOTI_ENV } from 'constants/env' import { Metric, SmartExitCondition } from 'pages/Earns/types' import { formatDisplayNumber } from 'utils/numbers' diff --git a/apps/kyberswap-interface/src/components/Announcement/type.ts b/apps/kyberswap-interface/src/components/Announcement/type.ts index d7802ec137..1ac5e276da 100644 --- a/apps/kyberswap-interface/src/components/Announcement/type.ts +++ b/apps/kyberswap-interface/src/components/Announcement/type.ts @@ -1,6 +1,6 @@ import { ReactNode } from 'react' -import { LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { SmartExitDexType } from 'pages/Earns/components/SmartExit/constants' import { SmartExitCondition } from 'pages/Earns/types' import { HistoricalPriceAlert } from 'pages/NotificationCenter/const' diff --git a/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx b/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx index 9b9cf4ee30..8bdae3c3b8 100644 --- a/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx +++ b/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx @@ -24,7 +24,7 @@ import { MouseoverTooltip } from 'components/Tooltip' import { TransactionErrorContent } from 'components/TransactionConfirmationModal' import WarningNote from 'components/WarningNote' import { calcPercentFilledOrder } from 'components/swapv2/LimitOrder/helpers' -import { LimitOrderStatus, LimitOrderTab } from 'components/swapv2/LimitOrder/type' +import { LimitOrderStatus, LimitOrderTab } from 'components/swapv2/LimitOrder/types' import { StyledBalanceMaxMini } from 'components/swapv2/styleds' import { TOKEN_API_URL } from 'constants/env' import { APP_PATHS, PAIR_CATEGORY } from 'constants/index' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx index 9bede4281d..065a386363 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx @@ -1,12 +1,12 @@ import { Trans, t } from '@lingui/macro' -import { Dispatch, SetStateAction } from 'react' import { ReactComponent as DropdownSVG } from 'assets/svg/down.svg' import { DefaultSlippageOption } from 'components/SlippageControl' import { TextDashed } from 'components/Text' import { MouseoverTooltip } from 'components/Tooltip' -import { getExpireOptions } from 'components/swapv2/LimitOrder/const' +import { TIMES_IN_SECS } from 'constants/index' import { cn } from 'utils/cn' +import { formatTimeDuration } from 'utils/time' const DropdownIcon = ({ className, ...rest }: React.SVGProps & { 'data-flip'?: boolean }) => ( & { /> ) +const getExpireOptions = () => + [ + TIMES_IN_SECS.ONE_HOUR, + TIMES_IN_SECS.ONE_DAY, + 7 * TIMES_IN_SECS.ONE_DAY, + 30 * TIMES_IN_SECS.ONE_DAY, + 36500 * TIMES_IN_SECS.ONE_DAY, + ].map(value => ({ value, label: formatTimeDuration(value) })) + type Props = { - expire: number - expanded: boolean - customDateExpire: Date | undefined - displayTime: string - setExpanded: Dispatch> - toggleDatePicker: () => void - onChangeExpire: (val: Date | number) => void + expiry?: { + expire?: number + expanded?: boolean + customDateExpire?: Date + displayTime?: string + } + events?: { + onToggleExpanded?: () => void + onOpenDatePicker?: () => void + onExpireChange?: (val: Date | number) => void + } } export default function LimitOrderExpirySection({ - expire, - expanded, - customDateExpire, - displayTime, - setExpanded, - toggleDatePicker, - onChangeExpire, + expiry: { expire, expanded, customDateExpire, displayTime } = {}, + events = {}, }: Props) { const expireOptions: Array<{ label: string; value?: number; onSelect?: () => void }> = [ ...getExpireOptions(), - { label: 'Custom', onSelect: toggleDatePicker }, + { label: 'Custom', onSelect: events.onOpenDatePicker }, ] return ( @@ -50,7 +58,7 @@ export default function LimitOrderExpirySection({ Expires In -
setExpanded(e => !e)}> +
{displayTime}
@@ -64,7 +72,7 @@ export default function LimitOrderExpirySection({ key={item.label} onClick={() => { if (item.onSelect) item.onSelect() - else if (item.value) onChangeExpire(item.value) + else if (item.value) events.onExpireChange?.(item.value) }} data-active={customDateExpire ? item.label === 'Custom' : item.value === expire} > diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx index ea95345d39..b3c28fc985 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx @@ -1,6 +1,6 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' -import { memo } from 'react' +import { memo, useState } from 'react' import { ButtonLight, ButtonPrimary, ButtonWarning } from 'components/Button' import DateTimePicker from 'components/DateTimePicker' @@ -10,205 +10,198 @@ import LimitOrderRateSection, { useGetDeltaRateLimitOrder, } from 'components/swapv2/LimitOrder/Form/LimitOrderRateSection' import LimitOrderTokenSection from 'components/swapv2/LimitOrder/Form/LimitOrderTokenSection' +import TradePrice from 'components/swapv2/LimitOrder/Form/TradePrice' import ConfirmOrderModal from 'components/swapv2/LimitOrder/Modals/ConfirmOrderModal' import ProcessingOrderModal from 'components/swapv2/LimitOrder/Modals/ProcessingOrderModal' -import TradePrice from 'components/swapv2/LimitOrder/TradePrice' +import useCreateLimitOrder from 'components/swapv2/LimitOrder/hooks/useCreateLimitOrder' import useLimitOrderExecution from 'components/swapv2/LimitOrder/hooks/useLimitOrderExecution' import useLimitOrderFormState from 'components/swapv2/LimitOrder/hooks/useLimitOrderFormState' -import { Z_INDEXS } from 'constants/styles' +import useProcessingOrder from 'components/swapv2/LimitOrder/hooks/useProcessingOrder' +import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { NETWORKS_INFO } from 'hooks/useChainsConfig' +import usePageLocation from 'hooks/usePageLocation' import { useChangeNetwork } from 'hooks/web3/useChangeNetwork' import ErrorWarningPanel from 'pages/Bridge/ErrorWarning' import { useWalletModalToggle } from 'state/application/hooks' +import { useLimitState } from 'state/limit/hooks' import { TransactionFlowState } from 'types/TransactionFlowState' -type BaseProps = { - currencyIn: Currency | undefined - currencyOut: Currency | undefined - note?: string - flowState: TransactionFlowState - setFlowState: React.Dispatch> - zIndexToolTip?: number +type LimitOrderFormProps = { + currencyIn?: Currency + currencyOut?: Currency } -type CreateLimitOrderFormProps = BaseProps & { - useUrlParams?: boolean +const useLimitOrderCurrencies = ({ currencyIn, currencyOut }: LimitOrderFormProps) => { + const limitState = useLimitState() + return { + currencyIn: currencyIn || limitState.currencyIn, + currencyOut: currencyOut || limitState.currencyOut, + } } -const LimitOrderForm = ({ - currencyIn, - currencyOut, - note = '', - flowState, - setFlowState, - zIndexToolTip = Z_INDEXS.TOOL_TIP_ERROR_INPUT_SWAP_FORM, - useUrlParams, -}: CreateLimitOrderFormProps) => { +const LimitOrderForm = ({ currencyIn: currencyInProp, currencyOut: currencyOutProp }: LimitOrderFormProps) => { + const toggleWalletModal = useWalletModalToggle() const { changeNetwork } = useChangeNetwork() const { account } = useActiveWeb3React() - const toggleWalletModal = useWalletModalToggle() - const { - chainId, - walletChainId, - networkInfo, - searchParams, - inputAmount, - outputAmount, - rateInfo, - displayRate, - expire, - showDatePicker, - customDateExpire, - rotate, - expanded, - loadingTrade, - tradeInfo, - expiredAt, - displayTime, - setExpanded, - onSetInput, - onSetOutput, - onChangeRate, - onInvertRate, - handleInputSelect, - switchToWeth, - handleOutputSelect, - handleRotateClick, - toggleDatePicker, - onChangeExpire, - onResetForm, - setPriceRateMarket, - } = useLimitOrderFormState({ + const { isEmbeddedSwap } = usePageLocation() + + const [flowState, setFlowState] = useState(TRANSACTION_STATE_DEFAULT) + + const { currencyIn, currencyOut } = useLimitOrderCurrencies({ + currencyIn: currencyInProp, + currencyOut: currencyOutProp, + }) + + const form = useLimitOrderFormState({ currencyIn, currencyOut, - useUrlParams, + useUrlParams: isEmbeddedSwap, }) - const deltaRate = useGetDeltaRateLimitOrder({ marketPrice: tradeInfo, rateInfo }) - const { - estimateUSD, - handleMaxInput, - hasInputError, - hidePreview, - hideProcessingOrder, - inputError, - insufficientBalance, - insufficientBalanceText, - isNotFillAllInput, - outPutError, - processingOrder, - retryProcessingOrder, - showPreview, - startProcessingOrder, - trackingPriceSetOnBlur, - trackingTouchInput, - trackingTouchSelectToken, - warningMessage, - } = useLimitOrderExecution({ + + const deltaRate = useGetDeltaRateLimitOrder({ marketPrice: form.tradeInfo, rateInfo: form.rateInfo }) + + const order = { currencyIn, currencyOut, - setFlowState, - chainId, - networkName: networkInfo.name, - searchParams, - inputAmount, - outputAmount, - displayRate, - expiredAt, - displayTime, - rateInfo, - tradeInfo, + chainId: form.chainId, + networkName: form.networkInfo.name, + inputAmount: form.inputAmount, + outputAmount: form.outputAmount, + displayRate: form.displayRate, + expiredAt: form.expiredAt, + displayTime: form.displayTime, + rateInfo: form.rateInfo, + tradeInfo: form.tradeInfo, deltaRate, - onSetInput, - onResetForm, - switchToWeth, + } + + const execution = useLimitOrderExecution({ + order, + setFlowState, + onSetInput: form.onSetInput, + onResetForm: form.onResetForm, + switchToWeth: form.switchToWeth, + }) + + const { balance, estimateUSD, preview, processing: executionProcessing, tracking, validation } = execution + + const createOrder = useCreateLimitOrder({ + order, + setFlowState, + searchParams: form.searchParams, + estimateUSD, + onError: execution.handleError, + onSuccess: execution.resetForm, }) - const styleTooltip = { maxWidth: '250px', zIndex: zIndexToolTip } - const disableReviewButton = isNotFillAllInput || !!hasInputError || insufficientBalance + const processing = useProcessingOrder({ + ...executionProcessing, + onCreateOrder: createOrder.submitCreateOrderWithTracking, + onError: execution.handleError, + setFlowState, + }) + + const disableReviewButton = validation.isNotFillAllInput || !!validation.hasInputError || balance.insufficientBalance const reviewButtonContent = ( - {insufficientBalance && insufficientBalanceText ? insufficientBalanceText : Review Order} + {balance.insufficientBalance && balance.insufficientBalanceText ? ( + balance.insufficientBalanceText + ) : ( + Review Order + )} ) + const actionButton = - chainId !== walletChainId ? ( - changeNetwork(chainId)}> - Switch to {NETWORKS_INFO[chainId].name} + form.chainId !== form.walletChainId ? ( + changeNetwork(form.chainId)}> + Switch to {NETWORKS_INFO[form.chainId].name} ) : !account ? ( Connect - ) : warningMessage.length > 0 && !disableReviewButton ? ( - {reviewButtonContent} + ) : validation.warningMessage.length > 0 && !disableReviewButton ? ( + {reviewButtonContent} ) : ( - + {reviewButtonContent} ) return ( <> -
- {useUrlParams ? : null} +
+ {isEmbeddedSwap ? : null} form.setExpanded(expanded => !expanded), + onOpenDatePicker: form.toggleDatePicker, + onExpireChange: form.onChangeExpire, + }} /> {currencyIn && currencyOut ? ( ) : null} - {warningMessage.map((mess, i) => ( + {validation.warningMessage.map((mess, i) => ( ))} @@ -216,35 +209,35 @@ const LimitOrderForm = ({
) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx index ea6d8ce3b4..34dde70b41 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx @@ -7,13 +7,11 @@ import CurrencyLogo from 'components/CurrencyLogo' import InfoHelper from 'components/InfoHelper' import NumericalInput from 'components/NumericalInput' import { removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' -import { RateInfo } from 'components/swapv2/LimitOrder/type' +import { DeltaRateLimitOrder, RateInfo } from 'components/swapv2/LimitOrder/types' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import useTheme from 'hooks/useTheme' import { cn } from 'utils/cn' -export type DeltaRateLimitOrder = { rawPercent: number | undefined; percent: string; profit: boolean } - export function useGetDeltaRateLimitOrder({ marketPrice, rateInfo, @@ -156,36 +154,41 @@ const PercentInputChip = ({ value, onUserInput }: { value: string; onUserInput: } type Props = { - currencyIn: Currency | undefined - currencyOut: Currency | undefined - displayRate: string - rateInfo: RateInfo - tradeInfo: BaseTradeInfo | undefined - onChangeRate: (value: string) => void - onInvertRate: (invert: boolean) => void - setPriceRateMarket: () => void - trackingTouchInput: () => void - trackingPriceSetOnBlur: () => void + tokens?: RateSectionTokens + rate?: RateSectionState + events?: RateSectionEvents } -export default function LimitOrderRateSection({ - currencyIn, - currencyOut, - displayRate, - rateInfo, - tradeInfo, - onChangeRate, - onInvertRate, - setPriceRateMarket, - trackingTouchInput, - trackingPriceSetOnBlur, -}: Props) { +type RateSectionTokens = { + currencyIn?: Currency + currencyOut?: Currency +} + +type RateSectionState = { + displayRate?: string + rateInfo?: RateInfo + tradeInfo?: BaseTradeInfo +} + +type RateSectionEvents = { + onRateChange?: (value: string) => void + onInvertRate?: (invert: boolean) => void + onSetMarketRate?: () => void + onRateInputFocus?: () => void + onRateInputBlur?: () => void +} + +const DEFAULT_RATE_INFO: RateInfo = { rate: '', invertRate: '', invert: false } +const RATE_DELTA_OPTIONS = [10, 20, 50] + +export default function LimitOrderRateSection({ tokens = {}, rate = {}, events = {} }: Props) { + const { currencyIn, currencyOut } = tokens + const { displayRate = '', rateInfo = DEFAULT_RATE_INFO, tradeInfo } = rate const deltaRate = useGetDeltaRateLimitOrder({ marketPrice: tradeInfo, rateInfo }) const marketRate = tradeInfo ? removeTrailingZero((rateInfo.invert ? tradeInfo.invertRate : tradeInfo.marketRate).toPrecision(6)) : '' const unitCurrency = rateInfo.invert ? currencyIn : currencyOut - const rateDeltaOptions = [10, 20, 50] const percentInputValue = deltaRate.rawPercent === undefined || !Number.isFinite(deltaRate.rawPercent) ? '' @@ -195,12 +198,12 @@ export default function LimitOrderRateSection({ if (!tradeInfo) return const market = rateInfo.invert ? tradeInfo.invertRate : tradeInfo.marketRate const nextRate = market * (1 + (rateInfo.invert ? -percent : percent) / 100) - onChangeRate(removeTrailingZero(nextRate.toFixed(16)) ?? '') + events.onRateChange?.(removeTrailingZero(nextRate.toFixed(16)) ?? '') } const onChangePercent = (value: string) => { if (!value || value === '-') { - onChangeRate('') + events.onRateChange?.('') return } setRateByDelta(Number(value)) @@ -219,7 +222,7 @@ export default function LimitOrderRateSection({
@@ -245,14 +248,14 @@ export default function LimitOrderRateSection({
- {rateDeltaOptions.map(percent => ( + {RATE_DELTA_OPTIONS.map(percent => ( setRateByDelta(percent)}> +{percent}% ))}
{tradeInfo ? ( - ) : null} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx index 6d53736e08..6d99a37b0e 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx @@ -1,6 +1,6 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans } from '@lingui/macro' -import { CSSProperties, ReactNode } from 'react' +import { ReactNode } from 'react' import ArrowRotate from 'components/ArrowRotate' import CurrencyInputPanel from 'components/CurrencyInputPanel' @@ -11,75 +11,74 @@ const Label = ({ children }: { children: ReactNode }) => ( ) type Props = { - chainId: number - currencyIn: Currency | undefined - currencyOut: Currency | undefined - inputAmount: string - outputAmount: string - inputError: string | ReactNode - outPutError: string | ReactNode - estimateUsdIn: string | undefined - estimateUsdOut: string | undefined - rotate: boolean - styleTooltip: CSSProperties - onSetInput: (input: string) => void - onSetOutput: (output: string) => void - handleMaxInput: () => void - handleInputSelect: (currency: Currency) => void - handleOutputSelect: (currency: Currency) => void - handleRotateClick: () => void - trackingTouchInput: () => void - trackingTouchSelectToken: () => void + chainId?: number + tokens?: TokenSectionTokens + errors?: TokenSectionErrors + estimateUsd?: TokenSectionEstimateUsd + events?: TokenSectionEvents } +type TokenSectionTokens = { + currencyIn?: Currency + currencyOut?: Currency + inputAmount?: string + outputAmount?: string + rotate?: boolean +} + +type TokenSectionErrors = { + input: string | ReactNode + output: string | ReactNode +} + +type TokenSectionEstimateUsd = { + input: string | undefined + output: string | undefined +} + +type TokenSectionEvents = { + onInputAmountChange?: (input: string) => void + onOutputAmountChange?: (output: string) => void + onMaxInput?: () => void + onInputTokenSelect?: (currency: Currency) => void + onOutputTokenSelect?: (currency: Currency) => void + onRotate?: () => void + onInputFocus?: () => void + onTokenSelectorOpen?: () => void +} + +const DEFAULT_ERRORS: TokenSectionErrors = { input: undefined, output: undefined } +const DEFAULT_ESTIMATE_USD: TokenSectionEstimateUsd = { input: undefined, output: undefined } + export default function LimitOrderTokenSection({ chainId, - currencyIn, - currencyOut, - inputAmount, - outputAmount, - inputError, - outPutError, - estimateUsdIn, - estimateUsdOut, - rotate, - styleTooltip, - onSetInput, - onSetOutput, - handleMaxInput, - handleInputSelect, - handleOutputSelect, - handleRotateClick, - trackingTouchInput, - trackingTouchSelectToken, + tokens = {}, + errors = DEFAULT_ERRORS, + estimateUsd = DEFAULT_ESTIMATE_USD, + events = {}, }: Props) { + const { currencyIn, currencyOut, inputAmount = '', outputAmount = '', rotate } = tokens + return (
- + You Sell @@ -94,30 +93,30 @@ export default function LimitOrderTokenSection({
- + You Buy diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/TradePrice.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/TradePrice.tsx similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/TradePrice.tsx rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/TradePrice.tsx diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx index d314ff468f..c8bb0a4a77 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx @@ -3,7 +3,7 @@ import { useGetNumberOfInsufficientFundOrdersQuery } from 'services/limitOrder' import TabButton from 'components/TabButton' import { MouseoverTooltip } from 'components/Tooltip' -import { LimitOrderTab } from 'components/swapv2/LimitOrder/type' +import { LimitOrderTab } from 'components/swapv2/LimitOrder/types' import { useActiveWeb3React } from 'hooks' const TAB_BUTTON_CLASS = 'h-fit w-fit !flex-none px-4 py-3 text-sm font-medium max-sm:w-1/2' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/index.tsx index cbcf6c7ac7..90899c69e5 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/index.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/index.tsx @@ -4,7 +4,7 @@ import { useSearchParams } from 'react-router-dom' import TabSelector from 'components/swapv2/LimitOrder/ListLimitOrder/TabSelector' import ListMyOrder from 'components/swapv2/LimitOrder/ListOrder' import OrderBook from 'components/swapv2/LimitOrder/OrderBook' -import { LimitOrderTab } from 'components/swapv2/LimitOrder/type' +import { LimitOrderTab } from 'components/swapv2/LimitOrder/types' export default function ListLimitOrder({ customChainId }: { customChainId?: ChainId }) { const [searchParams, setSearchParams] = useSearchParams() diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/ActionButtons.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/ActionButtons.tsx index 2be2f64c45..291f15675a 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/ActionButtons.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/ActionButtons.tsx @@ -7,7 +7,7 @@ import CopyHelper from 'components/Copy' import WarningIcon from 'components/Icons/WarningIcon' import { MouseoverTooltipDesktopOnly } from 'components/Tooltip' import { isActiveStatus } from 'components/swapv2/LimitOrder/helpers' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import useInterval from 'hooks/useInterval' import useTheme from 'hooks/useTheme' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx index 401da7e4e3..65b51743f0 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx @@ -16,7 +16,7 @@ import { formatRateLimitOrder, isActiveStatus, } from 'components/swapv2/LimitOrder/helpers' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { NETWORKS_INFO } from 'constants/networks' import { NativeCurrencies } from 'constants/tokens' import useTheme from 'hooks/useTheme' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx index f52dade57d..9a8dc9064c 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx @@ -8,7 +8,7 @@ import { formatAmountOrder, formatRateLimitOrder, } from 'components/swapv2/LimitOrder/helpers' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' export default function SummaryNotify({ type, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/TabSelector.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/TabSelector.tsx index c91275e909..405d95e7e1 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/TabSelector.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/TabSelector.tsx @@ -1,6 +1,6 @@ import { t } from '@lingui/macro' -import { LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { cn } from 'utils/cn' const TabButton = ({ active, ...props }: { active: boolean } & React.HTMLAttributes) => ( diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx index 465cc0fd22..ed622ed747 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx @@ -18,7 +18,6 @@ import TabSelector from 'components/swapv2/LimitOrder/ListOrder/TabSelector' import TableHeader from 'components/swapv2/LimitOrder/ListOrder/TableHeader' import useRequestCancelOrder from 'components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder' import CancelOrderModal from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' -import { ACTIVE_ORDER_OPTIONS, CLOSE_ORDER_OPTIONS } from 'components/swapv2/LimitOrder/const' import { formatAmountOrder, formatRateLimitOrder, @@ -26,7 +25,7 @@ import { isActiveStatus, } from 'components/swapv2/LimitOrder/helpers' import useCancellingOrders from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { EMPTY_ARRAY, RTK_QUERY_TAGS, TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { useInvalidateTagLimitOrder } from 'hooks/useInvalidateTags' @@ -48,6 +47,40 @@ export const NoResultWrapper = ({ className, ...rest }: HTMLAttributes ) +const ACTIVE_ORDER_OPTIONS = () => [ + { + label: t`All Active Orders`, + value: LimitOrderStatus.ACTIVE, + }, + { + label: t`Open Orders`, + value: LimitOrderStatus.OPEN, + }, + { + label: t`Partially Filled Orders`, + value: LimitOrderStatus.PARTIALLY_FILLED, + }, +] + +const CLOSE_ORDER_OPTIONS = () => [ + { + label: t`All Closed Orders`, + value: LimitOrderStatus.CLOSED, + }, + { + label: t`Filled Orders`, + value: LimitOrderStatus.FILLED, + }, + { + label: t`Cancelled Orders`, + value: LimitOrderStatus.CANCELLED, + }, + { + label: t`Expired Orders`, + value: LimitOrderStatus.EXPIRED, + }, +] + const TableFooter = ({ children = [], isTabActive }: { children: ReactNode[]; isTabActive: boolean }) => { const totalChild = children.filter(Boolean).length return totalChild ? ( diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx index 825f27334f..4284f4cc68 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx @@ -17,7 +17,7 @@ import { CancelOrderResponse, CancelOrderType, LimitOrder, -} from 'components/swapv2/LimitOrder/type' +} from 'components/swapv2/LimitOrder/types' import { LIMIT_ORDER_ABI } from 'constants/abis' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React, useWeb3React } from 'hooks' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx index 331eea2e83..51451363a2 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx @@ -8,9 +8,8 @@ import Column from 'components/Column' import { GasStation } from 'components/Icons' import { MouseoverTooltip } from 'components/Tooltip' import { CancelStatus } from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' -import { DOCS_LINKS } from 'components/swapv2/LimitOrder/const' -import { getPayloadTracking } from 'components/swapv2/LimitOrder/helpers' -import { CancelOrderType, LimitOrder } from 'components/swapv2/LimitOrder/type' +import { DOCS_LINKS, getPayloadTracking } from 'components/swapv2/LimitOrder/helpers' +import { CancelOrderType, LimitOrder } from 'components/swapv2/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import useTheme from 'hooks/useTheme' import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx index cbc337b2bc..a557a564a0 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx @@ -7,12 +7,12 @@ import Modal from 'components/Modal' import { useEstimateFee, useProcessCancelOrder } from 'components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder' import CancelButtons from 'components/swapv2/LimitOrder/Modals/CancelButtons' import CancelStatusCountDown from 'components/swapv2/LimitOrder/Modals/CancelStatusCountDown' -import { Container, Header, Label, ListInfo, Note, Rate, Value } from 'components/swapv2/LimitOrder/Modals/styled' +import { Container, Header, Label, ListInfo, Note, Rate, Value } from 'components/swapv2/LimitOrder/Modals/components' import { calcPercentFilledOrder, formatAmountOrder } from 'components/swapv2/LimitOrder/helpers' import useAllActiveOrders, { useIsSupportSoftCancelOrder, } from 'components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders' -import { CancelOrderFunction, CancelOrderType, LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { CancelOrderFunction, CancelOrderType, LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { NativeCurrencies } from 'constants/tokens' import { useCurrencyV2 } from 'hooks/Tokens' import { useBaseTradeInfoLimitOrder } from 'hooks/useBaseTradeInfo' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx index a75fb12ad2..0306220df5 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx @@ -8,7 +8,7 @@ import { Clock } from 'components/Icons' import WarningIcon from 'components/Icons/WarningIcon' import Loader from 'components/Loader' import { CancelStatus } from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' -import { DOCS_LINKS } from 'components/swapv2/LimitOrder/const' +import { DOCS_LINKS } from 'components/swapv2/LimitOrder/helpers' import useInterval from 'hooks/useInterval' import { ExternalLink } from 'theme' import { TransactionFlowState } from 'types/TransactionFlowState' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx index 130aa9c913..b701d4fa57 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx @@ -7,10 +7,9 @@ import { ButtonPrimary, ButtonWarning } from 'components/Button' import Column from 'components/Column' import CurrencyLogo from 'components/CurrencyLogo' import TransactionConfirmationModal, { TransactionErrorContent } from 'components/TransactionConfirmationModal' -import { Container, Header, ListInfo, Note, Rate, Value } from 'components/swapv2/LimitOrder/Modals/styled' -import { WORSE_PRICE_DIFF_THRESHOLD } from 'components/swapv2/LimitOrder/const' -import { formatAmountOrder } from 'components/swapv2/LimitOrder/helpers' -import { RateInfo } from 'components/swapv2/LimitOrder/type' +import { Container, Header, ListInfo, Rate, Value } from 'components/swapv2/LimitOrder/Modals/components' +import { WORSE_PRICE_DIFF_THRESHOLD, formatAmountOrder } from 'components/swapv2/LimitOrder/helpers' +import { RateInfo } from 'components/swapv2/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import ErrorWarningPanel from 'pages/Bridge/ErrorWarning' @@ -29,7 +28,6 @@ export default memo(function ConfirmOrderModal({ expiredAt, marketPrice, rateInfo, - note, warningMessage, percentDiff, }: { @@ -43,7 +41,6 @@ export default memo(function ConfirmOrderModal({ expiredAt: number marketPrice: BaseTradeInfo | undefined rateInfo: RateInfo - note?: string warningMessage: ReactNode[] percentDiff: number }) { @@ -154,7 +151,6 @@ export default memo(function ConfirmOrderModal({ symbolIn={currencyIn?.symbol} symbolOut={currencyOut?.symbol} /> - {warningMessage?.length > 0 && ( diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx index 912e64c9ac..d0d9dc9a3e 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx @@ -1,5 +1,6 @@ import { ChainId, Currency } from '@kyberswap/ks-sdk-core' import { t } from '@lingui/macro' +import { useEffect } from 'react' import { AlertCircle, RefreshCw, X } from 'react-feather' import { ButtonLight } from 'components/Button' @@ -10,7 +11,7 @@ import type { ProcessingOrderState, ProcessingOrderStep, ProcessingOrderStepStatus, -} from 'components/swapv2/LimitOrder/hooks/useLimitOrderExecution' +} from 'components/swapv2/LimitOrder/hooks/useProcessingOrder' import { NativeCurrencies } from 'constants/tokens' import { cn } from 'utils/cn' @@ -45,10 +46,22 @@ const getStepLabel = ({ }) => { const nativeSymbol = NativeCurrencies[chainId].symbol const inputSymbol = currencyIn?.wrapped.symbol - if (step === 'wrap') return t`Wrapping ${nativeSymbol}...` - if (step === 'approve') return t`Approving ${inputSymbol}...` - if (step === 'create' && status === 'success') return t`Order successfully listed!` - return t`Signing order...` + + if (step === 'wrap') { + if (status === 'active') return t`Wrapping ${nativeSymbol}` + if (status === 'success') return t`Wrapped ${nativeSymbol}` + return t`Wrap ${nativeSymbol}` + } + + if (step === 'approve') { + if (status === 'active') return t`Approving ${inputSymbol}` + if (status === 'success') return t`Approved ${inputSymbol}` + return t`Approve ${inputSymbol}` + } + + if (status === 'active') return t`Signing order` + if (status === 'success') return t`Order successfully listed` + return t`Sign order` } export default function ProcessingOrderModal({ @@ -56,14 +69,21 @@ export default function ProcessingOrderModal({ currencyIn, state, onDismiss, - onRetry, + onRetryStep, + onRunStep, }: { chainId: ChainId currencyIn: Currency | undefined state: ProcessingOrderState onDismiss: () => void - onRetry: () => void + onRetryStep: (step: ProcessingOrderStep) => void + onRunStep: (step: ProcessingOrderStep) => void }) { + useEffect(() => { + if (!state.show || !state.currentStep || state.errorStep) return + onRunStep(state.currentStep) + }, [onRunStep, state.currentStep, state.errorStep, state.show]) + return (
@@ -92,7 +112,7 @@ export default function ProcessingOrderModal({ {status === 'error' ? ( onRetryStep(step)} width="auto" className="h-8 shrink-0 gap-1 rounded-full px-4 py-0 text-primary" > diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/styled.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/components.tsx similarity index 98% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/styled.tsx rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/components.tsx index 40f54bdced..6c35abb0c4 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/styled.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/components.tsx @@ -5,9 +5,9 @@ import { X } from 'react-feather' import Column from 'components/Column' import { Swap as SwapIcon } from 'components/Icons' -import TradePrice from 'components/swapv2/LimitOrder/TradePrice' +import TradePrice from 'components/swapv2/LimitOrder/Form/TradePrice' import { formatAmountOrder, formatRateLimitOrder } from 'components/swapv2/LimitOrder/helpers' -import { LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/type' +import { LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/types' import { NativeCurrencies } from 'constants/tokens' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import { cn } from 'utils/cn' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx index fb4fc24ee0..ac2de26522 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx @@ -3,7 +3,7 @@ import { CSSProperties, useMemo } from 'react' import { useMedia } from 'react-use' import CurrencyLogo from 'components/CurrencyLogo' -import { LimitOrderFromTokenPairFormatted } from 'components/swapv2/LimitOrder/type' +import { LimitOrderFromTokenPairFormatted } from 'components/swapv2/LimitOrder/types' import { NETWORKS_INFO } from 'hooks/useChainsConfig' import { useLimitState } from 'state/limit/hooks' import { MEDIA_WIDTHS } from 'theme' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx index 12ddb72421..0aeafd132c 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx @@ -12,7 +12,7 @@ import { NoResultWrapper } from 'components/swapv2/LimitOrder/ListOrder' import OrderItem, { ChainImage } from 'components/swapv2/LimitOrder/OrderBook/OrderItem' import TableHeader from 'components/swapv2/LimitOrder/OrderBook/TableHeader' import { groupToMap } from 'components/swapv2/LimitOrder/helpers' -import { LimitOrderFromTokenPair, LimitOrderFromTokenPairFormatted } from 'components/swapv2/LimitOrder/type' +import { LimitOrderFromTokenPair, LimitOrderFromTokenPairFormatted } from 'components/swapv2/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import { useBaseTradeInfoLimitOrder } from 'hooks/useBaseTradeInfo' import useShowLoadingAtLeastTime from 'hooks/useShowLoadingAtLeastTime' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/const.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/const.ts deleted file mode 100644 index 2a63f02e91..0000000000 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/const.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { ChainId } from '@kyberswap/ks-sdk-core' -import { t } from '@lingui/macro' - -import { TIMES_IN_SECS } from 'constants/index' -import { formatTimeDuration } from 'utils/time' - -import { LimitOrderStatus } from './type' - -export const DEFAULT_EXPIRED = 36500 * TIMES_IN_SECS.ONE_DAY - -export const getExpireOptions = () => - [ - // 10 * TIMES_IN_SECS.ONE_MIN, - // 30 * TIMES_IN_SECS.ONE_MIN, - TIMES_IN_SECS.ONE_HOUR, - TIMES_IN_SECS.ONE_DAY, - // 3 * TIMES_IN_SECS.ONE_DAY, - 7 * TIMES_IN_SECS.ONE_DAY, - 30 * TIMES_IN_SECS.ONE_DAY, - // 100 years for forever - 36500 * TIMES_IN_SECS.ONE_DAY, - ].map(e => ({ value: e, label: formatTimeDuration(e) })) - -export const ACTIVE_ORDER_OPTIONS = () => [ - { - label: t`All Active Orders`, - value: LimitOrderStatus.ACTIVE, - }, - { - label: t`Open Orders`, - value: LimitOrderStatus.OPEN, - }, - { - label: t`Partially Filled Orders`, - value: LimitOrderStatus.PARTIALLY_FILLED, - }, -] -export const CLOSE_ORDER_OPTIONS = () => [ - { - label: t`All Closed Orders`, - value: LimitOrderStatus.CLOSED, - }, - { - label: t`Filled Orders`, - value: LimitOrderStatus.FILLED, - }, - { - label: t`Cancelled Orders`, - value: LimitOrderStatus.CANCELLED, - }, - { - label: t`Expired Orders`, - value: LimitOrderStatus.EXPIRED, - }, -] - -const _USD_THRESHOLD: { [chainId: number]: number } = { - [ChainId.MAINNET]: 300, -} -export const USD_THRESHOLD = new Proxy(_USD_THRESHOLD, { - get(target, p) { - const prop = p as any as ChainId - if (p && target[prop]) return target[prop] - return 10 - }, -}) - -export const WORSE_PRICE_DIFF_THRESHOLD = -5 -export const BETTER_PRICE_DIFF_THRESHOLD = 30 - -export const DOCS_LINKS = { - GASLESS_CANCEL: - 'https://docs.kyberswap.com/kyberswap-solutions/limit-order/concepts/gasless-cancellation#gasless-cancel', - HARD_CANCEL: 'https://docs.kyberswap.com/kyberswap-solutions/limit-order/concepts/gasless-cancellation#hard-cancel', - CANCEL_GUIDE: 'https://docs.kyberswap.com/kyberswap-solutions/limit-order/user-guides/cancel-limit-orders', - USER_GUIDE: 'https://docs.kyberswap.com/kyberswap-solutions/limit-order', -} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts index 6209352809..1d2b4ace52 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts @@ -2,7 +2,7 @@ import { Currency, Fraction } from '@kyberswap/ks-sdk-core' import { t } from '@lingui/macro' import JSBI from 'jsbi' -import { CreateOrderParam, LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { CreateOrderParam, LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { RESERVE_USD_DECIMALS } from 'constants/index' import { tryParseAmount } from 'state/swap/hooks' import { friendlyError } from 'utils/errorMessage' @@ -12,6 +12,16 @@ import { parseUnits } from 'utils/viem' export const isActiveStatus = (status: LimitOrderStatus) => [LimitOrderStatus.ACTIVE, LimitOrderStatus.OPEN, LimitOrderStatus.PARTIALLY_FILLED].includes(status) +export const WORSE_PRICE_DIFF_THRESHOLD = -5 + +export const DOCS_LINKS = { + GASLESS_CANCEL: + 'https://docs.kyberswap.com/kyberswap-solutions/limit-order/concepts/gasless-cancellation#gasless-cancel', + HARD_CANCEL: 'https://docs.kyberswap.com/kyberswap-solutions/limit-order/concepts/gasless-cancellation#hard-cancel', + CANCEL_GUIDE: 'https://docs.kyberswap.com/kyberswap-solutions/limit-order/user-guides/cancel-limit-orders', + USER_GUIDE: 'https://docs.kyberswap.com/kyberswap-solutions/limit-order', +} + // js number to fraction export function parseFraction(value: string, decimals = RESERVE_USD_DECIMALS) { try { diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts index 51e27bcedf..5fc0602e68 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts @@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { useGetLOConfigQuery } from 'services/limitOrder' import { isActiveStatus } from 'components/swapv2/LimitOrder/helpers' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import { OrderNonces, subscribeCancellingOrders } from 'utils/firebase' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx new file mode 100644 index 0000000000..baa293cd79 --- /dev/null +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx @@ -0,0 +1,180 @@ +import { Currency } from '@kyberswap/ks-sdk-core' +import { t } from '@lingui/macro' +import { useCallback } from 'react' +import { useCreateOrderMutation } from 'services/limitOrder' + +import { NotificationType } from 'components/Announcement/type' +import { getTipLinkAttribution } from 'components/TipLinkGeneratorModal/shared' +import { SummaryNotifyOrderPlaced } from 'components/swapv2/LimitOrder/ListOrder/SummaryNotify' +import { calcUsdPrices, getPayloadCreateOrder, removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' +import useSignOrder from 'components/swapv2/LimitOrder/hooks/useSignOrder' +import { CreateOrderParam, LimitOrderCreateContext } from 'components/swapv2/LimitOrder/types' +import { useActiveWeb3React } from 'hooks' +import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' +import { useNotify } from 'state/application/hooks' +import { TransactionFlowState } from 'types/TransactionFlowState' +import { getCookieValue } from 'utils' + +const getTokenAddress = (currency: Currency | undefined) => (currency?.isNative ? 'NATIVE' : currency?.wrapped?.address) + +type UseCreateLimitOrderArgs = { + order: LimitOrderCreateContext + setFlowState: React.Dispatch> + searchParams: URLSearchParams + estimateUSD: ReturnType + onError: (error: any) => void + onSuccess: () => void +} + +export default function useCreateLimitOrder({ + order, + setFlowState, + searchParams, + estimateUSD, + onError, + onSuccess, +}: UseCreateLimitOrderArgs) { + const { + currencyIn, + currencyOut, + chainId, + networkName, + inputAmount, + outputAmount, + displayRate, + expiredAt, + displayTime, + rateInfo, + tradeInfo, + deltaRate, + } = order + const { account } = useActiveWeb3React() + const { trackingHandler } = useTracking() + const notify = useNotify() + const signOrder = useSignOrder(undefined) + + const [submitOrder] = useCreateOrderMutation() + + const trackPlaceOrder = useCallback( + (type: TRACKING_EVENT_TYPE, data = {}) => { + trackingHandler(type, { + from_token: currencyIn?.symbol, + to_token: currencyOut?.symbol, + from_network: networkName, + trade_qty: inputAmount, + ...data, + }) + }, + [currencyIn?.symbol, currencyOut?.symbol, inputAmount, networkName, trackingHandler], + ) + + const submitCreateOrder = useCallback( + async (params: CreateOrderParam) => { + try { + const { currencyIn, currencyOut, account, inputAmount, outputAmount, expiredAt } = params + if (!currencyIn || !currencyOut || !account || !inputAmount || !outputAmount || !expiredAt) { + throw new Error('wrong input') + } + + const refCode = getCookieValue('refCode') + const clientId = searchParams.get('clientId') + + const { signature, salt } = await signOrder({ ...params, referral: refCode }) + const payload = getPayloadCreateOrder(params) + setFlowState(state => ({ ...state, pendingText: t`Placing order` })) + const response = await submitOrder({ ...payload, salt, signature, referral: refCode, clientId }).unwrap() + setFlowState(state => ({ ...state, showConfirm: false })) + + notify( + { + type: NotificationType.SUCCESS, + title: t`Order Placed`, + summary: , + }, + 10000, + ) + onSuccess() + return response?.id + } catch (error) { + onError(error) + return + } + }, + [notify, onError, onSuccess, searchParams, setFlowState, signOrder, submitOrder], + ) + + const submitCreateOrderWithTracking = useCallback(async () => { + trackPlaceOrder(TRACKING_EVENT_TYPE.LO_CLICK_PLACE_ORDER) + const order_id = await submitCreateOrder({ + currencyIn, + currencyOut, + chainId, + account, + inputAmount, + outputAmount, + expiredAt, + }) + if (!order_id) return + + trackPlaceOrder(TRACKING_EVENT_TYPE.LO_PLACE_ORDER_SUCCESS, { order_id }) + trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_PLACED, { + side: rateInfo.invert ? 'buy' : 'sell', + from_token: currencyIn?.symbol, + from_token_address: getTokenAddress(currencyIn), + to_token: currencyOut?.symbol, + to_token_address: getTokenAddress(currencyOut), + pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, + limit_price: displayRate, + market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, + price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, + amount_in: inputAmount, + amount_in_usd: estimateUSD.rawInput || undefined, + amount_out_estimated: outputAmount, + expiry: displayTime, + chain: networkName, + order_id, + volume: estimateUSD.rawInput || undefined, + }) + + const tipLink = getTipLinkAttribution(searchParams) + if (tipLink) { + trackingHandler(TRACKING_EVENT_TYPE.TIP_LINK_TRADE, { + trade_type: 'limit_order', + trade_status: 'placed', + tip_charged: false, + ...tipLink, + input_token: currencyIn?.symbol, + output_token: currencyOut?.symbol, + input_token_address: getTokenAddress(currencyIn), + output_token_address: getTokenAddress(currencyOut), + pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, + chain: networkName, + chain_id: chainId, + volume: estimateUSD.rawInput || undefined, + order_id, + }) + } + return order_id + }, [ + account, + chainId, + currencyIn, + currencyOut, + deltaRate.rawPercent, + displayRate, + displayTime, + estimateUSD.rawInput, + expiredAt, + inputAmount, + networkName, + outputAmount, + rateInfo.invert, + searchParams, + submitCreateOrder, + trackPlaceOrder, + trackingHandler, + tradeInfo, + ]) + + return { submitCreateOrderWithTracking } +} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts index 892a25077f..6bde156544 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts @@ -2,7 +2,7 @@ import { ChainId } from '@kyberswap/ks-sdk-core' import { useCallback, useMemo } from 'react' import { useGetLOConfigQuery, useGetListOrdersQuery } from 'services/limitOrder' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { useActiveWeb3React } from 'hooks' export const useIsSupportSoftCancelOrder = () => { diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx index 53b5c7130e..56d9ff5702 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx @@ -1,55 +1,31 @@ -import { ChainId, Currency, CurrencyAmount, Token, TokenAmount, WETH } from '@kyberswap/ks-sdk-core' +import { Currency, CurrencyAmount, Token, TokenAmount, WETH } from '@kyberswap/ks-sdk-core' import { t } from '@lingui/macro' import JSBI from 'jsbi' -import { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { useCreateOrderMutation, useGetLOConfigQuery, useGetTotalActiveMakingAmountQuery } from 'services/limitOrder' +import { useCallback, useEffect, useMemo } from 'react' +import { useGetLOConfigQuery, useGetTotalActiveMakingAmountQuery } from 'services/limitOrder' -import { NotificationType } from 'components/Announcement/type' -import { getTipLinkAttribution } from 'components/TipLinkGeneratorModal/shared' -import type { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/LimitOrderRateSection' -import { SummaryNotifyOrderPlaced } from 'components/swapv2/LimitOrder/ListOrder/SummaryNotify' -import { - calcUsdPrices, - getErrorMessage, - getPayloadCreateOrder, - removeTrailingZero, -} from 'components/swapv2/LimitOrder/helpers' -import useSignOrder from 'components/swapv2/LimitOrder/hooks/useSignOrder' +import { calcUsdPrices, getErrorMessage, removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' +import { ProcessingOrderStep } from 'components/swapv2/LimitOrder/hooks/useProcessingOrder' import useValidateInputError from 'components/swapv2/LimitOrder/hooks/useValidateInputError' import useWarningCreateOrder from 'components/swapv2/LimitOrder/hooks/useWarningCreateOrder' import useWrapEthStatus from 'components/swapv2/LimitOrder/hooks/useWrapEthStatus' -import { CreateOrderParam, RateInfo } from 'components/swapv2/LimitOrder/type' +import { LimitOrderCreateContext } from 'components/swapv2/LimitOrder/types' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { NativeCurrencies } from 'constants/tokens' import { useTokenAllowance } from 'data/Allowances' import { useActiveWeb3React } from 'hooks' import { ApprovalState, useApproveCallback } from 'hooks/useApproveCallback' -import type { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' import useWrapCallback from 'hooks/useWrapCallback' -import { useNotify } from 'state/application/hooks' import { tryParseAmount } from 'state/swap/hooks' import { useCurrencyBalance } from 'state/wallet/hooks' import { TransactionFlowState } from 'types/TransactionFlowState' -import { getCookieValue } from 'utils' import { subscribeNotificationOrderExpired } from 'utils/firebase' import { maxAmountSpend } from 'utils/maxAmountSpend' type UseLimitOrderExecutionArgs = { - currencyIn: Currency | undefined - currencyOut: Currency | undefined + order: LimitOrderCreateContext setFlowState: React.Dispatch> - chainId: ChainId - networkName: string - searchParams: URLSearchParams - inputAmount: string - outputAmount: string - displayRate: string - expiredAt: number - displayTime: string - rateInfo: RateInfo - tradeInfo: BaseTradeInfo | undefined - deltaRate: DeltaRateLimitOrder onSetInput: (input: string) => void onResetForm: () => void switchToWeth: () => void @@ -57,46 +33,28 @@ type UseLimitOrderExecutionArgs = { const getTokenAddress = (currency: Currency | undefined) => (currency?.isNative ? 'NATIVE' : currency?.wrapped?.address) -export type ProcessingOrderStep = 'wrap' | 'approve' | 'create' -export type ProcessingOrderStepStatus = 'idle' | 'active' | 'success' | 'error' - -export type ProcessingOrderState = { - show: boolean - steps: ProcessingOrderStep[] - currentStep?: ProcessingOrderStep - errorStep?: ProcessingOrderStep - completedSteps: ProcessingOrderStep[] -} - export default function useLimitOrderExecution({ - currencyIn, - currencyOut, + order, setFlowState, - chainId, - networkName, - searchParams, - inputAmount, - outputAmount, - displayRate, - expiredAt, - displayTime, - rateInfo, - tradeInfo, - deltaRate, onSetInput, onResetForm, switchToWeth, }: UseLimitOrderExecutionArgs) { + const { + currencyIn, + currencyOut, + chainId, + networkName, + inputAmount, + outputAmount, + displayRate, + displayTime, + rateInfo, + tradeInfo, + deltaRate, + } = order const { account } = useActiveWeb3React() - const notify = useNotify() const { trackingHandler } = useTracking() - const [processingOrder, setProcessingOrder] = useState({ - show: false, - steps: [], - completedSteps: [], - }) - const processingStepStartedRef = useRef() - const approvalRef = useRef(ApprovalState.UNKNOWN) // Balances, allowance, and form readiness. const { data: activeOrderMakingAmount = '', refetch: getActiveMakingAmount } = useGetTotalActiveMakingAmountQuery( @@ -187,6 +145,13 @@ export default function useLimitOrderExecution({ limitOrderContract || undefined, !enoughAllowance, ) + const processingSteps = useMemo(() => { + const steps: ProcessingOrderStep[] = [] + if (needsWrap) steps.push('wrap') + if (needsWrap || (!currencyIn?.isNative && approval !== ApprovalState.APPROVED)) steps.push('approve') + steps.push('create') + return steps + }, [approval, currencyIn?.isNative, needsWrap]) const { inputError, outPutError } = useValidateInputError({ inputAmount, @@ -317,280 +282,6 @@ export default function useLimitOrderExecution({ refreshActiveMakingAmount() }, [onResetForm, refreshActiveMakingAmount]) - const markProcessingStepSuccess = useCallback((step: ProcessingOrderStep) => { - processingStepStartedRef.current = undefined - setProcessingOrder(state => { - if (!state.show || state.currentStep !== step) return state - const completedSteps = state.completedSteps.includes(step) - ? state.completedSteps - : [...state.completedSteps, step] - const nextStep = state.steps[state.steps.indexOf(step) + 1] - return { - ...state, - currentStep: nextStep, - completedSteps, - } - }) - }, []) - - const markProcessingStepError = useCallback((step: ProcessingOrderStep) => { - processingStepStartedRef.current = undefined - setProcessingOrder(state => { - if (!state.show || state.currentStep !== step) return state - return { - ...state, - errorStep: step, - } - }) - }, []) - - const hideProcessingOrder = useCallback(() => { - processingStepStartedRef.current = undefined - setProcessingOrder({ show: false, steps: [], completedSteps: [] }) - }, []) - - const retryProcessingOrder = useCallback(() => { - processingStepStartedRef.current = undefined - setProcessingOrder(state => { - if (!state.errorStep) return state - return { - ...state, - currentStep: state.errorStep, - errorStep: undefined, - } - }) - }, []) - - const trackingPlaceOrder = useCallback( - (type: TRACKING_EVENT_TYPE, data = {}) => { - trackingHandler(type, { - from_token: currencyIn?.symbol, - to_token: currencyOut?.symbol, - from_network: networkName, - trade_qty: inputAmount, - ...data, - }) - }, - [currencyIn?.symbol, currencyOut?.symbol, inputAmount, networkName, trackingHandler], - ) - - const signOrder = useSignOrder(setFlowState) - const [submitOrder] = useCreateOrderMutation() - const onSubmitCreateOrder = useCallback( - async (params: CreateOrderParam) => { - try { - const { currencyIn, currencyOut, account, inputAmount, outputAmount, expiredAt } = params - if (!currencyIn || !currencyOut || !account || !inputAmount || !outputAmount || !expiredAt) { - throw new Error('wrong input') - } - - const refCode = getCookieValue('refCode') - const clientId = searchParams.get('clientId') - - const { signature, salt } = await signOrder({ ...params, referral: refCode }) - const payload = getPayloadCreateOrder(params) - setFlowState(state => ({ ...state, pendingText: t`Placing order` })) - const response = await submitOrder({ ...payload, salt, signature, referral: refCode, clientId }).unwrap() - setFlowState(state => ({ ...state, showConfirm: false })) - - notify( - { - type: NotificationType.SUCCESS, - title: t`Order Placed`, - summary: , - }, - 10000, - ) - resetForm() - return response?.id - } catch (error) { - handleError(error) - return - } - }, - [handleError, notify, resetForm, searchParams, setFlowState, signOrder, submitOrder], - ) - - const onSubmitCreateOrderWithTracking = useCallback(async () => { - trackingPlaceOrder(TRACKING_EVENT_TYPE.LO_CLICK_PLACE_ORDER) - const order_id = await onSubmitCreateOrder({ - currencyIn, - currencyOut, - chainId, - account, - inputAmount, - outputAmount, - expiredAt, - }) - if (!order_id) return - - trackingPlaceOrder(TRACKING_EVENT_TYPE.LO_PLACE_ORDER_SUCCESS, { order_id }) - trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_PLACED, { - side: rateInfo.invert ? 'buy' : 'sell', - from_token: currencyIn?.symbol, - from_token_address: getTokenAddress(currencyIn), - to_token: currencyOut?.symbol, - to_token_address: getTokenAddress(currencyOut), - pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, - limit_price: displayRate, - market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, - price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, - amount_in: inputAmount, - amount_in_usd: estimateUSD.rawInput || undefined, - amount_out_estimated: outputAmount, - expiry: displayTime, - chain: networkName, - order_id, - volume: estimateUSD.rawInput || undefined, - }) - - const tipLink = getTipLinkAttribution(searchParams) - if (tipLink) { - trackingHandler(TRACKING_EVENT_TYPE.TIP_LINK_TRADE, { - trade_type: 'limit_order', - trade_status: 'placed', - tip_charged: false, - ...tipLink, - input_token: currencyIn?.symbol, - output_token: currencyOut?.symbol, - input_token_address: getTokenAddress(currencyIn), - output_token_address: getTokenAddress(currencyOut), - pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, - chain: networkName, - chain_id: chainId, - volume: estimateUSD.rawInput || undefined, - order_id, - }) - } - return order_id - }, [ - account, - chainId, - currencyIn, - currencyOut, - deltaRate.rawPercent, - displayRate, - displayTime, - estimateUSD.rawInput, - expiredAt, - inputAmount, - networkName, - onSubmitCreateOrder, - outputAmount, - rateInfo.invert, - searchParams, - trackingHandler, - trackingPlaceOrder, - tradeInfo, - ]) - - const runProcessingStep = useCallback( - (step: ProcessingOrderStep) => { - if (step === 'wrap') { - if (!needsWrap) { - markProcessingStepSuccess('wrap') - return - } - if (isWrappingEth || processingStepStartedRef.current === 'wrap') return - processingStepStartedRef.current = 'wrap' - ;(async () => { - try { - const hash = await onWrap?.() - if (!hash) { - markProcessingStepError('wrap') - return - } - setTxHashWrapped(hash) - } catch (error) { - handleError(error) - markProcessingStepError('wrap') - } - })() - return - } - - if (step === 'approve') { - if (approval === ApprovalState.APPROVED) { - markProcessingStepSuccess('approve') - return - } - if (approval === ApprovalState.UNKNOWN || approval === ApprovalState.PENDING) return - if (processingStepStartedRef.current === 'approve') return - processingStepStartedRef.current = 'approve' - ;(async () => { - try { - await approveCallback() - setTimeout(() => { - if (approvalRef.current === ApprovalState.NOT_APPROVED) { - markProcessingStepError('approve') - } - }, 800) - } catch (error) { - handleError(error) - markProcessingStepError('approve') - } - })() - return - } - - if (processingStepStartedRef.current === 'create') return - processingStepStartedRef.current = 'create' - ;(async () => { - try { - const orderId = await onSubmitCreateOrderWithTracking() - if (orderId) { - markProcessingStepSuccess('create') - return - } - markProcessingStepError('create') - } catch (error) { - handleError(error) - markProcessingStepError('create') - } - })() - }, - [ - approval, - approveCallback, - handleError, - isWrappingEth, - markProcessingStepError, - markProcessingStepSuccess, - needsWrap, - onSubmitCreateOrderWithTracking, - onWrap, - setTxHashWrapped, - ], - ) - - const startProcessingOrder = useCallback(() => { - const steps: ProcessingOrderStep[] = [] - if (needsWrap) steps.push('wrap') - if (needsWrap || (!currencyIn?.isNative && approval !== ApprovalState.APPROVED)) steps.push('approve') - steps.push('create') - const firstStep = steps[0] - processingStepStartedRef.current = undefined - setFlowState(state => ({ ...state, showConfirm: false, errorMessage: undefined })) - setProcessingOrder({ - show: true, - steps, - currentStep: firstStep, - completedSteps: [], - }) - runProcessingStep(firstStep) - }, [approval, currencyIn?.isNative, needsWrap, runProcessingStep, setFlowState]) - - // External state synchronization. - useEffect(() => { - approvalRef.current = approval - }, [approval]) - - useEffect(() => { - const currentStep = processingOrder.currentStep - if (!processingOrder.show || !currentStep || processingOrder.errorStep) return - runProcessingStep(currentStep) - }, [processingOrder.currentStep, processingOrder.errorStep, processingOrder.show, runProcessingStep]) - useEffect(() => { if (!account) return const unsubscribeExpired = subscribeNotificationOrderExpired(account, chainId, refreshActiveMakingAmount) @@ -601,22 +292,37 @@ export default function useLimitOrderExecution({ return { estimateUSD, - handleMaxInput, - hasInputError, - hidePreview, - hideProcessingOrder, - inputError, - insufficientBalance, - insufficientBalanceText, - isNotFillAllInput, - outPutError, - processingOrder, - retryProcessingOrder, - showPreview, - startProcessingOrder, - trackingPriceSetOnBlur, - trackingTouchInput, - trackingTouchSelectToken, - warningMessage, + handleError, + resetForm, + balance: { + handleMaxInput, + insufficientBalance, + insufficientBalanceText, + }, + preview: { + hidePreview, + showPreview, + }, + processing: { + approval, + approveCallback, + isWrappingEth, + needsWrap, + onWrap, + setTxHashWrapped, + steps: processingSteps, + }, + tracking: { + trackingPriceSetOnBlur, + trackingTouchInput, + trackingTouchSelectToken, + }, + validation: { + hasInputError, + inputError, + isNotFillAllInput, + outPutError, + warningMessage, + }, } } diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts index 5080172bee..f7c5146120 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts @@ -3,7 +3,6 @@ import dayjs from 'dayjs' import { useCallback, useEffect, useRef, useState } from 'react' import { useSearchParams } from 'react-router-dom' -import { DEFAULT_EXPIRED } from 'components/swapv2/LimitOrder/const' import { calcInvert, calcOutput, @@ -11,7 +10,8 @@ import { parseFraction, removeTrailingZero, } from 'components/swapv2/LimitOrder/helpers' -import { RateInfo } from 'components/swapv2/LimitOrder/type' +import { RateInfo } from 'components/swapv2/LimitOrder/types' +import { TIMES_IN_SECS } from 'constants/index' import { SUPPORTED_NETWORKS } from 'constants/networks' import { useActiveWeb3React } from 'hooks' import { useBaseTradeInfoLimitOrder } from 'hooks/useBaseTradeInfo' @@ -25,6 +25,9 @@ export type LimitOrderFormStateArgs = { useUrlParams?: boolean } +const DEFAULT_EXPIRED = 36500 * TIMES_IN_SECS.ONE_DAY +const DEFAULT_RATE_INFO: RateInfo = { rate: '', invertRate: '', invert: false } + export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrlParams }: LimitOrderFormStateArgs) { const { chainId: walletChainId, networkInfo } = useActiveWeb3React() const { trackingHandler } = useTracking() @@ -45,7 +48,7 @@ export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrl const autoFillMarketPrice = useRef(false) const [outputAmount, setOutputAmount] = useState('') - const [rateInfo, setRateInfo] = useState({ rate: '', invertRate: '', invert: false }) + const [rateInfo, setRateInfo] = useState(DEFAULT_RATE_INFO) const [expire, setExpire] = useState(DEFAULT_EXPIRED) const [showDatePicker, setShowDatePicker] = useState(false) const [customDateExpire, setCustomDateExpire] = useState() @@ -58,6 +61,10 @@ export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrl const expiredAt = customDateExpire?.getTime() || Date.now() + expire * 1000 const displayTime = customDateExpire ? dayjs(customDateExpire).format('DD/MM/YYYY HH:mm') : formatTimeDuration(expire) + const clearRate = useCallback(() => { + setRateInfo(rateInfo => ({ ...rateInfo, invertRate: '', rate: '', rateFraction: undefined })) + }, []) + const setCurrencyIn = useCallback( (currency: Currency | undefined) => { if (useUrlParams) { @@ -196,9 +203,9 @@ export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrl return } setCurrencyIn(currency) - resetRate && setRateInfo(rateInfo => ({ ...rateInfo, invertRate: '', rate: '', rateFraction: undefined })) + resetRate && clearRate() }, - [currencyOut, setCurrencyIn, switchCurrency], + [clearRate, currencyOut, setCurrencyIn, switchCurrency], ) const switchToWeth = useCallback(() => { @@ -212,7 +219,7 @@ export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrl return } setCurrencyOut(currency) - setRateInfo(rateInfo => ({ ...rateInfo, invertRate: '', rate: '', rateFraction: undefined })) + clearRate() } const handleRotateClick = () => { @@ -267,7 +274,7 @@ export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrl const onResetForm = useCallback(() => { setInputAmount('') setOutputAmount('') - setRateInfo({ rate: '', invertRate: '', invert: false }) + setRateInfo(DEFAULT_RATE_INFO) setExpire(DEFAULT_EXPIRED) setCustomDateExpire(undefined) }, [setInputAmount]) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx index 52db0a87a7..88591f3c99 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx @@ -4,7 +4,7 @@ import { useAckNotificationOrderMutation } from 'services/limitOrder' import { NotificationType } from 'components/Announcement/type' import SummaryNotify from 'components/swapv2/LimitOrder/ListOrder/SummaryNotify' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { APP_PATHS } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { useNotify } from 'state/application/hooks' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useProcessingOrder.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useProcessingOrder.ts new file mode 100644 index 0000000000..17368a125e --- /dev/null +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useProcessingOrder.ts @@ -0,0 +1,190 @@ +import { useCallback, useEffect, useRef, useState } from 'react' + +import { ApprovalState } from 'hooks/useApproveCallback' +import { TransactionFlowState } from 'types/TransactionFlowState' + +export type ProcessingOrderStep = 'wrap' | 'approve' | 'create' +export type ProcessingOrderStepStatus = 'idle' | 'active' | 'success' | 'error' + +export type ProcessingOrderState = { + show: boolean + steps: ProcessingOrderStep[] + currentStep?: ProcessingOrderStep + errorStep?: ProcessingOrderStep + completedSteps: ProcessingOrderStep[] +} + +type UseProcessingOrderArgs = { + approval: ApprovalState + approveCallback: () => Promise + steps: ProcessingOrderStep[] + isWrappingEth: boolean + onWrap: (() => Promise) | undefined + setTxHashWrapped: (hash: string) => void + onCreateOrder: () => Promise + onError: (error: any) => void + setFlowState: React.Dispatch> +} + +const DEFAULT_PROCESSING_ORDER: ProcessingOrderState = { + show: false, + steps: [], + completedSteps: [], +} + +export default function useProcessingOrder({ + approval, + approveCallback, + steps, + isWrappingEth, + onWrap, + setTxHashWrapped, + onCreateOrder, + onError, + setFlowState, +}: UseProcessingOrderArgs) { + const [processingOrder, setProcessingOrder] = useState(DEFAULT_PROCESSING_ORDER) + const processingStepStartedRef = useRef() + const approvalRef = useRef(ApprovalState.UNKNOWN) + + const markProcessingStepSuccess = useCallback((step: ProcessingOrderStep) => { + processingStepStartedRef.current = undefined + setProcessingOrder(state => { + if (!state.show || state.currentStep !== step) return state + const completedSteps = state.completedSteps.includes(step) + ? state.completedSteps + : [...state.completedSteps, step] + const nextStep = state.steps[state.steps.indexOf(step) + 1] + return { + ...state, + currentStep: nextStep, + completedSteps, + } + }) + }, []) + + const markProcessingStepError = useCallback((step: ProcessingOrderStep) => { + processingStepStartedRef.current = undefined + setProcessingOrder(state => { + if (!state.show || state.currentStep !== step) return state + return { + ...state, + errorStep: step, + } + }) + }, []) + + const hideProcessingOrder = useCallback(() => { + processingStepStartedRef.current = undefined + setProcessingOrder(DEFAULT_PROCESSING_ORDER) + }, []) + + const retryProcessingStep = useCallback((step: ProcessingOrderStep) => { + processingStepStartedRef.current = undefined + setProcessingOrder(state => { + if (state.errorStep !== step) return state + return { + ...state, + currentStep: step, + errorStep: undefined, + } + }) + }, []) + + const runProcessingStep = useCallback( + (step: ProcessingOrderStep) => { + if (step === 'wrap') { + if (isWrappingEth || processingStepStartedRef.current === 'wrap') return + processingStepStartedRef.current = 'wrap' + ;(async () => { + try { + const hash = await onWrap?.() + if (!hash) { + markProcessingStepError('wrap') + return + } + setTxHashWrapped(hash) + } catch (error) { + onError(error) + markProcessingStepError('wrap') + } + })() + return + } + + if (step === 'approve') { + if (approval === ApprovalState.APPROVED) { + markProcessingStepSuccess('approve') + return + } + if (approval === ApprovalState.UNKNOWN || approval === ApprovalState.PENDING) return + if (processingStepStartedRef.current === 'approve') return + processingStepStartedRef.current = 'approve' + ;(async () => { + try { + await approveCallback() + setTimeout(() => { + if (approvalRef.current === ApprovalState.NOT_APPROVED) { + markProcessingStepError('approve') + } + }, 800) + } catch (error) { + onError(error) + markProcessingStepError('approve') + } + })() + return + } + + if (processingStepStartedRef.current === 'create') return + processingStepStartedRef.current = 'create' + ;(async () => { + try { + const orderId = await onCreateOrder() + if (orderId) { + markProcessingStepSuccess('create') + return + } + markProcessingStepError('create') + } catch (error) { + onError(error) + markProcessingStepError('create') + } + })() + }, + [ + approval, + approveCallback, + isWrappingEth, + markProcessingStepError, + markProcessingStepSuccess, + onCreateOrder, + onError, + onWrap, + setTxHashWrapped, + ], + ) + + const startProcessingOrder = useCallback(() => { + processingStepStartedRef.current = undefined + setFlowState(state => ({ ...state, showConfirm: false, errorMessage: undefined })) + setProcessingOrder({ + show: true, + steps, + currentStep: steps[0], + completedSteps: [], + }) + }, [setFlowState, steps]) + + useEffect(() => { + approvalRef.current = approval + }, [approval]) + + return { + hideProcessingOrder, + processingOrder, + retryProcessingStep, + runProcessingStep, + startProcessingOrder, + } +} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts index 0359f1a259..a2a0742615 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts @@ -2,7 +2,7 @@ import { useCallback } from 'react' import { useCreateOrderSignatureMutation } from 'services/limitOrder' import { formatAmountOrder, getPayloadCreateOrder } from 'components/swapv2/LimitOrder/helpers' -import { CreateOrderParam } from 'components/swapv2/LimitOrder/type' +import { CreateOrderParam } from 'components/swapv2/LimitOrder/types' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { TransactionFlowState } from 'types/TransactionFlowState' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx index b4c6e5dec4..a2b6c58e08 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx @@ -1,13 +1,9 @@ -import { Currency, CurrencyAmount } from '@kyberswap/ks-sdk-core' +import { ChainId, Currency, CurrencyAmount } from '@kyberswap/ks-sdk-core' import { Trans } from '@lingui/macro' import { useMemo } from 'react' -import { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/Form/LimitOrderRateSection' -import { - BETTER_PRICE_DIFF_THRESHOLD, - USD_THRESHOLD, - WORSE_PRICE_DIFF_THRESHOLD, -} from 'components/swapv2/LimitOrder/const' +import { WORSE_PRICE_DIFF_THRESHOLD } from 'components/swapv2/LimitOrder/helpers' +import { DeltaRateLimitOrder } from 'components/swapv2/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import { formatDisplayNumber } from 'utils/numbers' @@ -15,6 +11,19 @@ const HightLight = ({ children }: { children: React.ReactNode }) => ( {children} ) +const BETTER_PRICE_DIFF_THRESHOLD = 30 + +const _USD_THRESHOLD: { [chainId: number]: number } = { + [ChainId.MAINNET]: 300, +} +const USD_THRESHOLD = new Proxy(_USD_THRESHOLD, { + get(target, p) { + const prop = p as any as ChainId + if (p && target[prop]) return target[prop] + return 10 + }, +}) + export default function useWarningCreateOrder({ currencyIn, outputAmount, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/index.tsx deleted file mode 100644 index 6464bc1bc7..0000000000 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/index.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { memo, useState } from 'react' - -import LimitOrderForm from 'components/swapv2/LimitOrder/Form/LimitOrderForm' -import { TRANSACTION_STATE_DEFAULT } from 'constants/index' -import { useLimitState } from 'state/limit/hooks' -import { TransactionFlowState } from 'types/TransactionFlowState' - -function LimitOrderComp() { - const { currencyIn, currencyOut } = useLimitState() - - // modal and loading - const [flowState, setFlowState] = useState(TRANSACTION_STATE_DEFAULT) - - return ( -
- -
- ) -} - -export default memo(LimitOrderComp) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/type.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/types.ts similarity index 84% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/type.ts rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/types.ts index 0458f6a220..bc0c2fe975 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/type.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/types.ts @@ -1,5 +1,7 @@ import { ChainId, Currency, Fraction } from '@kyberswap/ks-sdk-core' +import type { BaseTradeInfo } from 'hooks/useBaseTradeInfo' + export enum LimitOrderTab { ORDER_BOOK = 'order_book', MY_ORDER = 'my_order', @@ -109,6 +111,12 @@ export type RateInfo = { rateFraction?: Fraction // to calc with big number } +export type DeltaRateLimitOrder = { + rawPercent: number | undefined + percent: string + profit: boolean +} + export type CancelOrderFunction = (data: { orders: LimitOrder[] cancelType: CancelOrderType @@ -128,3 +136,18 @@ export type CreateOrderParam = { expiredAt: number referral?: string } + +export type LimitOrderCreateContext = { + currencyIn: Currency | undefined + currencyOut: Currency | undefined + chainId: ChainId + networkName: string + inputAmount: string + outputAmount: string + displayRate: string + expiredAt: number + displayTime: string + rateInfo: RateInfo + tradeInfo: BaseTradeInfo | undefined + deltaRate: DeltaRateLimitOrder +} diff --git a/apps/kyberswap-interface/src/hooks/index.ts b/apps/kyberswap-interface/src/hooks/index.ts index b5f0801ad5..0bbcabd482 100644 --- a/apps/kyberswap-interface/src/hooks/index.ts +++ b/apps/kyberswap-interface/src/hooks/index.ts @@ -61,7 +61,7 @@ export function useWeb3React() { return useMemo( () => ({ - account: '0x0193a8a52D77E27bDd4f12E0cDd52d8Ff1d97d68', + account: account.address, chainId: account.chainId, connector: account.connector, active: account.address !== undefined, diff --git a/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx b/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx index 6036cf4c44..760a9d1881 100644 --- a/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx +++ b/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx @@ -1,5 +1,4 @@ import { ChainId, Currency, WETH } from '@kyberswap/ks-sdk-core' -import { t } from '@lingui/macro' import { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useNavigate, useParams, useSearchParams } from 'react-router-dom' import { usePreviousDistinct } from 'react-use' @@ -16,7 +15,7 @@ import SettingsPanel from 'components/swapv2/SwapSettingsPanel' import useRequiredDegenMode from 'components/swapv2/SwapSettingsPanel/useRequiredDegenMode' import TokenInfoTab from 'components/swapv2/TokenInfo' import { Container, InfoComponentsWrapper, PageWrapper, SwapFormWrapper } from 'components/swapv2/styleds' -import { MAX_FEE_IN_BIPS, TRANSACTION_STATE_DEFAULT } from 'constants/index' +import { MAX_FEE_IN_BIPS } from 'constants/index' import { SUPPORTED_NETWORKS } from 'constants/networks' import { DEFAULT_OUTPUT_TOKEN_BY_CHAIN, NativeCurrencies, PRICE_CHART_QUOTE_TOKEN_BY_CHAIN } from 'constants/tokens' import { useActiveWeb3React } from 'hooks' @@ -35,7 +34,6 @@ import { Field } from 'state/swap/actions' import { usePermitData } from 'state/swap/hooks' import { useDegenModeManager, useUserSlippageTolerance, useUserTransactionTTL } from 'state/user/hooks' import { useCurrencyBalances } from 'state/wallet/hooks' -import { TransactionFlowState } from 'types/TransactionFlowState' import { ChargeFeeBy, DetailedRouteSummary } from 'types/route' import { isAddress } from 'utils' import { getTradeComposition } from 'utils/aggregationRouting' @@ -289,11 +287,6 @@ export default function PartnerSwap({ mode = 'partner' }: Props) { omniView: true, } - // modal and loading - const [flowState, setFlowState] = useState(TRANSACTION_STATE_DEFAULT) - - const currencyName = currencyOut?.wrapped.name - const currencySymbol = currencyOut?.wrapped.symbol return ( <> @@ -328,22 +321,7 @@ export default function PartnerSwap({ mode = 'partner' }: Props) { {activeTab === TAB.LIQUIDITY_SOURCES && ( setActiveTab(TAB.SETTINGS)} chainId={swapChainId} /> )} - {activeTab === TAB.LIMIT && ( -
- -
- )} + {activeTab === TAB.LIMIT && } {activeTab === TAB.CROSS_CHAIN && } {activeTab === TAB.CROSS_CHAIN_SOURCES && ( setActiveTab(TAB.SETTINGS)} /> diff --git a/apps/kyberswap-interface/src/pages/SwapV3/index.tsx b/apps/kyberswap-interface/src/pages/SwapV3/index.tsx index 6c2bb38912..9927161686 100644 --- a/apps/kyberswap-interface/src/pages/SwapV3/index.tsx +++ b/apps/kyberswap-interface/src/pages/SwapV3/index.tsx @@ -6,7 +6,7 @@ import { FarmingPoolBanner, TrendingPoolBanner } from 'components/EarnBanner' import { HStack, Stack } from 'components/Stack' import { SwitchLocaleLink } from 'components/SwitchLocaleLink' import { TutorialIds } from 'components/Tutorial/TutorialSwap/constant' -import LimitOrder from 'components/swapv2/LimitOrder' +import LimitOrderForm from 'components/swapv2/LimitOrder/Form/LimitOrderForm' import ListLimitOrder from 'components/swapv2/LimitOrder/ListLimitOrder' import LiquiditySourcesPanel from 'components/swapv2/LiquiditySourcesPanel' import SettingsPanel from 'components/swapv2/SwapSettingsPanel' @@ -152,7 +152,7 @@ export default function Swap() { /> )} {activeTab === TAB.LIQUIDITY_SOURCES && setActiveTab(TAB.SETTINGS)} />} - {activeTab === TAB.LIMIT && } + {activeTab === TAB.LIMIT && } {activeTab === TAB.CROSS_CHAIN && } {activeTab === TAB.CROSS_CHAIN_SOURCES && ( setActiveTab(TAB.SETTINGS)} /> diff --git a/apps/kyberswap-interface/src/services/limitOrder.ts b/apps/kyberswap-interface/src/services/limitOrder.ts index 1e37582c92..a73204e32d 100644 --- a/apps/kyberswap-interface/src/services/limitOrder.ts +++ b/apps/kyberswap-interface/src/services/limitOrder.ts @@ -1,7 +1,7 @@ import { ChainId } from '@kyberswap/ks-sdk-core' import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -import { LimitOrder, LimitOrderFromTokenPair, LimitOrderStatus } from 'components/swapv2/LimitOrder/type' +import { LimitOrder, LimitOrderFromTokenPair, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { LIMIT_ORDER_API } from 'constants/env' import { RTK_QUERY_TAGS } from 'constants/index' diff --git a/apps/kyberswap-interface/src/utils/firebase.ts b/apps/kyberswap-interface/src/utils/firebase.ts index d9757bc92e..aab1b3122a 100644 --- a/apps/kyberswap-interface/src/utils/firebase.ts +++ b/apps/kyberswap-interface/src/utils/firebase.ts @@ -3,7 +3,7 @@ import firebase from 'firebase/compat/app' import { Firestore, collection, doc, getFirestore, onSnapshot, query } from 'firebase/firestore' import { PopupContentAnnouncement } from 'components/Announcement/type' -import { LimitOrder } from 'components/swapv2/LimitOrder/type' +import { LimitOrder } from 'components/swapv2/LimitOrder/types' import { ENV_KEY, ENV_LEVEL, FIREBASE } from 'constants/env' import { ENV_TYPE } from 'constants/type' From 421faac22390b8c80501546b09ac54f1b22e58e9 Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Thu, 18 Jun 2026 11:20:51 +0700 Subject: [PATCH 08/52] Chore --- .../hooks/useLimitOrderExecution.tsx | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx index 56d9ff5702..51cabe859f 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx @@ -56,24 +56,17 @@ export default function useLimitOrderExecution({ const { account } = useActiveWeb3React() const { trackingHandler } = useTracking() - // Balances, allowance, and form readiness. + // Base order data from API and typed input. const { data: activeOrderMakingAmount = '', refetch: getActiveMakingAmount } = useGetTotalActiveMakingAmountQuery( { chainId, tokenAddress: currencyIn?.wrapped.address ?? '', account: account ?? '' }, { skip: !currencyIn || !account }, ) - const { isWrappingEth, setTxHashWrapped } = useWrapEthStatus(switchToWeth) - const parseInputAmount = tryParseAmount(inputAmount, currencyIn ?? undefined) + const { currentData } = useGetLOConfigQuery(chainId) const limitOrderContract = currentData?.contract - const currentAllowance = useTokenAllowance( - currencyIn as Token, - account ?? undefined, - limitOrderContract, - ) as CurrencyAmount - const parsedActiveOrderMakingAmount = useMemo(() => { try { if (currencyIn && activeOrderMakingAmount) { @@ -86,10 +79,12 @@ export default function useLimitOrderExecution({ return undefined }, [currencyIn, activeOrderMakingAmount]) + // Balance and wrap requirements. const balance = useCurrencyBalance(currencyIn, chainId) const nativeCurrency = NativeCurrencies[chainId] const nativeBalance = useCurrencyBalance(nativeCurrency, chainId) const isWrappedNativeInput = !!currencyIn?.equals(WETH[chainId]) + const wrapAmountForOrder = useMemo(() => { if (!currencyIn || !isWrappedNativeInput || !parseInputAmount || !balance?.currency.equals(currencyIn)) { return undefined @@ -98,10 +93,14 @@ export default function useLimitOrderExecution({ const deficit = JSBI.subtract(parseInputAmount.quotient, balance.quotient) return CurrencyAmount.fromRawAmount(nativeCurrency, deficit) }, [balance, currencyIn, isWrappedNativeInput, nativeCurrency, parseInputAmount]) + const needsWrap = !!currencyIn?.isNative || !!wrapAmountForOrder const wrapInputCurrency = currencyIn?.isNative ? currencyIn : wrapAmountForOrder ? nativeCurrency : currencyIn const wrapTypedValue = wrapAmountForOrder ? wrapAmountForOrder.toExact() : inputAmount + + const { isWrappingEth, setTxHashWrapped } = useWrapEthStatus(switchToWeth) const { execute: onWrap } = useWrapCallback(wrapInputCurrency, WETH[chainId], wrapTypedValue, true, chainId) + const maxAmountInput = useMemo(() => { return maxAmountSpend(balance) }, [balance]) @@ -113,8 +112,7 @@ export default function useLimitOrderExecution({ return nativeBalance.lessThan(wrapAmountForOrder) }, [balance, currencyIn, isWrappedNativeInput, nativeBalance, nativeCurrency, parseInputAmount, wrapAmountForOrder]) - const insufficientBalanceSymbol = currencyIn?.symbol - const insufficientBalanceText = insufficientBalance ? t`Insufficient ${insufficientBalanceSymbol} balance` : undefined + const insufficientBalanceText = insufficientBalance ? t`Insufficient Balance` : undefined const handleMaxInput = useCallback(() => { if (!maxAmountInput) return @@ -123,12 +121,20 @@ export default function useLimitOrderExecution({ } catch (error) {} }, [maxAmountInput, onSetInput]) + // Allowance and process-modal steps. + const currentAllowance = useTokenAllowance( + currencyIn as Token, + account ?? undefined, + limitOrderContract, + ) as CurrencyAmount + const missingAllowance = useMemo(() => { if (currentAllowance?.equalTo(0)) return true if (currencyIn?.isNative || !parseInputAmount) return false const allowanceSubtracted = parsedActiveOrderMakingAmount ? currentAllowance?.subtract(parsedActiveOrderMakingAmount) : undefined + if ( !allowanceSubtracted || allowanceSubtracted.greaterThan(parseInputAmount) || @@ -145,6 +151,7 @@ export default function useLimitOrderExecution({ limitOrderContract || undefined, !enoughAllowance, ) + const processingSteps = useMemo(() => { const steps: ProcessingOrderStep[] = [] if (needsWrap) steps.push('wrap') @@ -153,6 +160,7 @@ export default function useLimitOrderExecution({ return steps }, [approval, currencyIn?.isNative, needsWrap]) + // Form validation and warning messages. const { inputError, outPutError } = useValidateInputError({ inputAmount, outputAmount, @@ -184,7 +192,7 @@ export default function useLimitOrderExecution({ missingAllowance, }) - // User-facing actions. + // Tracking callbacks used by form inputs. const trackingTouchInput = useCallback(() => { trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'touch enter amount box') }, [trackingHandler]) @@ -215,15 +223,19 @@ export default function useLimitOrderExecution({ trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'touch enter token box') }, [trackingHandler]) + // Preview modal and shared error handling. const showPreview = () => { if (!currencyIn || !currencyOut || !outputAmount || !inputAmount || !displayRate) return + setFlowState({ ...TRANSACTION_STATE_DEFAULT, showConfirm: true }) + trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_REVIEW_PLACE_ORDER, { from_token: currencyIn.symbol, to_token: currencyOut.symbol, from_network: chainId, trade_qty: inputAmount, }) + trackingHandler(TRACKING_EVENT_TYPE.LO_REVIEW_OPENED, { side: rateInfo.invert ? 'buy' : 'sell', from_token: currencyIn.symbol, @@ -251,6 +263,7 @@ export default function useLimitOrderExecution({ const errorMessage = getErrorMessage(error) const isUserRejected = errorMessage.toLowerCase().includes('user denied') || errorMessage.toLowerCase().includes('user rejected') + trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_FAILED, { side: rateInfo.invert ? 'buy' : 'sell', from_token: currencyIn?.symbol, @@ -262,6 +275,7 @@ export default function useLimitOrderExecution({ error_message: errorMessage, chain: networkName, }) + setFlowState(state => ({ ...state, attemptingTxn: false, @@ -271,6 +285,7 @@ export default function useLimitOrderExecution({ [setFlowState, trackingHandler, rateInfo.invert, currencyIn, currencyOut, displayRate, inputAmount, networkName], ) + // Keep active making amount fresh after order state updates. const refreshActiveMakingAmount = useCallback(() => { try { getActiveMakingAmount() From 33743da40d43860e1940014f72f33489e9b8131d Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Thu, 18 Jun 2026 12:59:49 +0700 Subject: [PATCH 09/52] refactor(limit): polish order form structure --- .../components/Announcement/Popups/index.tsx | 2 +- .../src/components/SwapForm/index.tsx | 2 +- .../WalletPopup/Transactions/index.tsx | 2 +- .../Form/LimitOrderExpirySection.tsx | 49 +++-- .../swapv2/LimitOrder/Form/LimitOrderForm.tsx | 186 +++++++++--------- .../LimitOrder/Form/LimitOrderRateSection.tsx | 98 +++------ .../Form/LimitOrderTokenSection.tsx | 23 +-- .../swapv2/LimitOrder/Form/TradePrice.tsx | 6 +- .../LimitOrder/ListLimitOrder/TabSelector.tsx | 6 +- .../LimitOrder/ListLimitOrder/index.tsx | 4 +- .../swapv2/LimitOrder/ListOrder/OrderItem.tsx | 6 +- .../LimitOrder/ListOrder/SummaryNotify.tsx | 6 +- .../swapv2/LimitOrder/ListOrder/index.tsx | 8 +- .../ListOrder/useRequestCancelOrder.tsx | 6 +- .../LimitOrder/Modals/CancelOrderModal.tsx | 7 +- .../Modals/CancelStatusCountDown.tsx | 6 +- .../LimitOrder/Modals/ConfirmOrderModal.tsx | 42 ++-- .../Modals/ProcessingOrderModal.tsx | 6 +- .../swapv2/LimitOrder/Modals/components.tsx | 4 +- .../swapv2/LimitOrder/OrderBook/OrderItem.tsx | 6 +- .../LimitOrder/OrderBook/TableHeader.tsx | 4 +- .../swapv2/LimitOrder/OrderBook/index.tsx | 4 +- .../components/swapv2/LimitOrder/helpers.ts | 8 +- .../LimitOrder/hooks/useCancellingOrders.ts | 2 +- .../LimitOrder/hooks/useCreateLimitOrder.tsx | 6 +- .../hooks/useFetchActiveAllOrders.ts | 2 +- .../hooks/useLimitOrderExecution.tsx | 10 +- .../hooks/useLimitOrderFormState.ts | 5 +- .../hooks/useNotificationLimitOrder.tsx | 3 +- .../LimitOrder/hooks/useProcessingOrder.ts | 4 +- .../swapv2/LimitOrder/hooks/useSignOrder.ts | 4 +- .../hooks/useValidateInputError.tsx | 3 +- .../hooks/useWarningCreateOrder.tsx | 4 +- .../LimitOrder/hooks/useWrapEthStatus.ts | 2 +- .../src/pages/SwapV3/index.tsx | 2 +- 35 files changed, 257 insertions(+), 281 deletions(-) diff --git a/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx b/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx index 806e1cdba0..4b30717cf3 100644 --- a/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx +++ b/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx @@ -6,7 +6,7 @@ import SnippetPopup from 'components/Announcement/Popups/SnippetPopup' import TopRightPopup from 'components/Announcement/Popups/TopRightPopup' import { PopupType, PrivateAnnouncementType } from 'components/Announcement/type' import { ButtonEmpty } from 'components/Button' -import useNotificationLimitOrder from 'components/swapv2/LimitOrder/hooks/useNotificationLimitOrder' +import { useNotificationLimitOrder } from 'components/swapv2/LimitOrder/hooks/useNotificationLimitOrder' import { TIMES_IN_SECS } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { diff --git a/apps/kyberswap-interface/src/components/SwapForm/index.tsx b/apps/kyberswap-interface/src/components/SwapForm/index.tsx index b84155e7c1..0dd5f23355 100644 --- a/apps/kyberswap-interface/src/components/SwapForm/index.tsx +++ b/apps/kyberswap-interface/src/components/SwapForm/index.tsx @@ -308,7 +308,7 @@ const SwapForm: React.FC = props => { {!isWrapOrUnwrap && }
-
+
{!isWrapOrUnwrap && ( diff --git a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx index bbec6bbbd9..906662b630 100644 --- a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx +++ b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx @@ -11,7 +11,7 @@ import Row, { RowBetween } from 'components/Row' import Tab from 'components/WalletPopup/Transactions/Tab' import TransactionItem from 'components/WalletPopup/Transactions/TransactionItem' import { NUMBERS } from 'components/WalletPopup/Transactions/helper' -import useCancellingOrders, { CancellingOrderInfo } from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' +import { CancellingOrderInfo, useCancellingOrders } from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' import { useActiveWeb3React } from 'hooks' import { fetchListTokenByAddresses, findCacheToken, useIsLoadedTokenDefault } from 'hooks/Tokens' import { isSupportKyberDao } from 'hooks/kyberdao' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx index 065a386363..0aa2994c1a 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx @@ -38,17 +38,17 @@ type Props = { } } -export default function LimitOrderExpirySection({ +const LimitOrderExpirySection = ({ expiry: { expire, expanded, customDateExpire, displayTime } = {}, events = {}, -}: Props) { +}: Props) => { const expireOptions: Array<{ label: string; value?: number; onSelect?: () => void }> = [ ...getExpireOptions(), { label: 'Custom', onSelect: events.onOpenDatePicker }, ] return ( -
+
-
-
- {expireOptions.map(item => { - return ( - { - if (item.onSelect) item.onSelect() - else if (item.value) events.onExpireChange?.(item.value) - }} - data-active={customDateExpire ? item.label === 'Custom' : item.value === expire} - > - {item.label} - - ) - })} +
+
+
+
+ {expireOptions.map(item => { + return ( + { + if (item.onSelect) item.onSelect() + else if (item.value) events.onExpireChange?.(item.value) + }} + data-active={customDateExpire ? item.label === 'Custom' : item.value === expire} + > + {item.label} + + ) + })} +
+
) } + +export default LimitOrderExpirySection diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx index b3c28fc985..97846ef284 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx @@ -5,6 +5,7 @@ import { memo, useState } from 'react' import { ButtonLight, ButtonPrimary, ButtonWarning } from 'components/Button' import DateTimePicker from 'components/DateTimePicker' import { NetworkSelector } from 'components/NetworkSelector' +import { Stack } from 'components/Stack' import LimitOrderExpirySection from 'components/swapv2/LimitOrder/Form/LimitOrderExpirySection' import LimitOrderRateSection, { useGetDeltaRateLimitOrder, @@ -13,10 +14,10 @@ import LimitOrderTokenSection from 'components/swapv2/LimitOrder/Form/LimitOrder import TradePrice from 'components/swapv2/LimitOrder/Form/TradePrice' import ConfirmOrderModal from 'components/swapv2/LimitOrder/Modals/ConfirmOrderModal' import ProcessingOrderModal from 'components/swapv2/LimitOrder/Modals/ProcessingOrderModal' -import useCreateLimitOrder from 'components/swapv2/LimitOrder/hooks/useCreateLimitOrder' -import useLimitOrderExecution from 'components/swapv2/LimitOrder/hooks/useLimitOrderExecution' -import useLimitOrderFormState from 'components/swapv2/LimitOrder/hooks/useLimitOrderFormState' -import useProcessingOrder from 'components/swapv2/LimitOrder/hooks/useProcessingOrder' +import { useCreateLimitOrder } from 'components/swapv2/LimitOrder/hooks/useCreateLimitOrder' +import { useLimitOrderExecution } from 'components/swapv2/LimitOrder/hooks/useLimitOrderExecution' +import { useLimitOrderFormState } from 'components/swapv2/LimitOrder/hooks/useLimitOrderFormState' +import { useProcessingOrder } from 'components/swapv2/LimitOrder/hooks/useProcessingOrder' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { NETWORKS_INFO } from 'hooks/useChainsConfig' @@ -113,100 +114,101 @@ const LimitOrderForm = ({ currencyIn: currencyInProp, currencyOut: currencyOutPr ) - const actionButton = - form.chainId !== form.walletChainId ? ( - changeNetwork(form.chainId)}> - Switch to {NETWORKS_INFO[form.chainId].name} - - ) : !account ? ( - - Connect - - ) : validation.warningMessage.length > 0 && !disableReviewButton ? ( - {reviewButtonContent} - ) : ( - - {reviewButtonContent} - - ) - return ( <> -
+ {isEmbeddedSwap ? : null} - - - - - form.setExpanded(expanded => !expanded), - onOpenDatePicker: form.toggleDatePicker, - onExpireChange: form.onChangeExpire, - }} - /> - - {currencyIn && currencyOut ? ( - + + + - ) : null} - {validation.warningMessage.map((mess, i) => ( - - ))} + form.setExpanded(expanded => !expanded), + onOpenDatePicker: form.toggleDatePicker, + onExpireChange: form.onChangeExpire, + }} + /> - {actionButton} -
+ {currencyIn && currencyOut ? ( + + ) : null} + + + {validation.warningMessage.length > 0 && ( + + {validation.warningMessage.map((mess, i) => ( + + ))} + + )} + + {form.chainId !== form.walletChainId ? ( + changeNetwork(form.chainId)}> + Switch to {NETWORKS_INFO[form.chainId].name} + + ) : !account ? ( + + Connect + + ) : validation.warningMessage.length > 0 && !disableReviewButton ? ( + {reviewButtonContent} + ) : ( + + {reviewButtonContent} + + )} + { const { deltaText, percent } = useMemo(() => { try { if (marketPrice && rateInfo.rate && rateInfo.invertRate) { @@ -52,56 +49,19 @@ const RateLabel = ({ children, className, ...rest }: React.HTMLAttributes ) -const DeltaRate = ({ - marketPrice, - rateInfo, - symbol, - invert, -}: { - marketPrice: BaseTradeInfo | undefined - rateInfo: RateInfo - symbol: string - invert: boolean -}) => { - const theme = useTheme() - - const { percent, profit } = useGetDeltaRateLimitOrder({ marketPrice, rateInfo }) - const color = profit ? theme.apr : theme.warning - const colorClass = profit ? 'text-apr' : 'text-warning' - const styledPercent = {percent} +const DeltaRate = ({ symbol, invert }: { symbol: string; invert: boolean }) => { return ( {invert ? Buy {symbol} at rate : Sell {symbol} at rate} - {percent ? ( - <> -  {percent} - Your selected price is {styledPercent} better than the current market price. - ) : ( - Your selected price is {styledPercent} worse than the current market price. - ) - } - /> - - ) : null} ) } -const RateCard = ({ children, className, ...rest }: React.HTMLAttributes) => ( -
- {children} -
-) - const RateChip = ({ children, className, ...rest }: React.ButtonHTMLAttributes) => ( - )}
-
-
+
+
+ {unitCurrency && ( +
+ {unitCurrency.symbol} +
+ )}
@@ -255,11 +203,17 @@ export default function LimitOrderRateSection({ tokens = {}, rate = {}, events = ))}
{tradeInfo ? ( - ) : null}
- + ) } + +export default LimitOrderRateSection diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx index 6d99a37b0e..f414cc21b8 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx @@ -2,8 +2,8 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans } from '@lingui/macro' import { ReactNode } from 'react' -import ArrowRotate from 'components/ArrowRotate' import CurrencyInputPanel from 'components/CurrencyInputPanel' +import ReverseTokenSelectionButton from 'components/SwapForm/ReverseTokenSelectionButton' import Tooltip from 'components/Tooltip' const Label = ({ children }: { children: ReactNode }) => ( @@ -23,7 +23,6 @@ type TokenSectionTokens = { currencyOut?: Currency inputAmount?: string outputAmount?: string - rotate?: boolean } type TokenSectionErrors = { @@ -50,17 +49,17 @@ type TokenSectionEvents = { const DEFAULT_ERRORS: TokenSectionErrors = { input: undefined, output: undefined } const DEFAULT_ESTIMATE_USD: TokenSectionEstimateUsd = { input: undefined, output: undefined } -export default function LimitOrderTokenSection({ +const LimitOrderTokenSection = ({ chainId, tokens = {}, errors = DEFAULT_ERRORS, estimateUsd = DEFAULT_ESTIMATE_USD, events = {}, -}: Props) { - const { currencyIn, currencyOut, inputAmount = '', outputAmount = '', rotate } = tokens +}: Props) => { + const { currencyIn, currencyOut, inputAmount = '', outputAmount = '' } = tokens return ( -
+
-
- -
+ events.onRotate?.()} />
) } + +export default LimitOrderTokenSection diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/TradePrice.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/TradePrice.tsx index 6c6f598052..df320380ab 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/TradePrice.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/TradePrice.tsx @@ -20,7 +20,7 @@ interface TradePriceProps { icon?: ReactNode } -export default function TradePrice({ +const TradePrice = ({ price, style = {}, label, @@ -30,7 +30,7 @@ export default function TradePrice({ symbolOut, loading, icon, -}: TradePriceProps) { +}: TradePriceProps) => { const [showInverted, setShowInverted] = useState(false) let formattedPrice try { @@ -74,3 +74,5 @@ export default function TradePrice({ ) } + +export default TradePrice diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx index c8bb0a4a77..ffcc4333f5 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx @@ -8,13 +8,13 @@ import { useActiveWeb3React } from 'hooks' const TAB_BUTTON_CLASS = 'h-fit w-fit !flex-none px-4 py-3 text-sm font-medium max-sm:w-1/2' -export default function TabSelector({ +const TabSelector = ({ activeTab, setActiveTab, }: { activeTab: LimitOrderTab setActiveTab: (n: LimitOrderTab) => void -}) { +}) => { const { chainId, account } = useActiveWeb3React() const { data: numberOfInsufficientFundOrders } = useGetNumberOfInsufficientFundOrdersQuery( { chainId, maker: account || '' }, @@ -56,3 +56,5 @@ export default function TabSelector({
) } + +export default TabSelector diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/index.tsx index 90899c69e5..a3a7651df9 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/index.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListLimitOrder/index.tsx @@ -6,7 +6,7 @@ import ListMyOrder from 'components/swapv2/LimitOrder/ListOrder' import OrderBook from 'components/swapv2/LimitOrder/OrderBook' import { LimitOrderTab } from 'components/swapv2/LimitOrder/types' -export default function ListLimitOrder({ customChainId }: { customChainId?: ChainId }) { +const ListLimitOrder = ({ customChainId }: { customChainId?: ChainId }) => { const [searchParams, setSearchParams] = useSearchParams() const activeTab = (searchParams.get('activeTab') as LimitOrderTab) || LimitOrderTab.ORDER_BOOK @@ -26,3 +26,5 @@ export default function ListLimitOrder({ customChainId }: { customChainId?: Chai
) } + +export default ListLimitOrder diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx index 65b51743f0..abee7f34b9 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx @@ -245,7 +245,7 @@ const IndexText = ({ children }: { children?: React.ReactNode }) => ( const WarningText = ({ children }: { children: React.ReactNode }) => {children} -export default function OrderItem({ +const OrderItem = ({ order, index, onCancelOrder, @@ -261,7 +261,7 @@ export default function OrderItem({ tokenPrices: Record isLast: boolean hasOrderCancelling: boolean -}) { +}) => { const [expand, setExpand] = useState(false) const upToSmall = useMedia(`(max-width: ${MEDIA_WIDTHS.upToSmall}px)`) const isCancelling = isOrderCancelling(order) @@ -490,3 +490,5 @@ export default function OrderItem({ ) } + +export default OrderItem diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx index 9a8dc9064c..494739ec56 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx @@ -10,7 +10,7 @@ import { } from 'components/swapv2/LimitOrder/helpers' import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' -export default function SummaryNotify({ +const SummaryNotify = ({ type, message, orders = [], @@ -18,7 +18,7 @@ export default function SummaryNotify({ type?: LimitOrderStatus message?: string orders?: LimitOrder[] -}) { +}) => { const isMultiOrder = orders.length > 1 const order = orders[0] const { @@ -136,6 +136,8 @@ export default function SummaryNotify({ return

{message || msg}

} +export default SummaryNotify + export const SummaryNotifyOrderPlaced = ({ currencyIn, currencyOut, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx index ed622ed747..a6b0224c1d 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx @@ -16,7 +16,7 @@ import Select from 'components/Select' import OrderItem from 'components/swapv2/LimitOrder/ListOrder/OrderItem' import TabSelector from 'components/swapv2/LimitOrder/ListOrder/TabSelector' import TableHeader from 'components/swapv2/LimitOrder/ListOrder/TableHeader' -import useRequestCancelOrder from 'components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder' +import { useRequestCancelOrder } from 'components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder' import CancelOrderModal from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' import { formatAmountOrder, @@ -24,7 +24,7 @@ import { getPayloadTracking, isActiveStatus, } from 'components/swapv2/LimitOrder/helpers' -import useCancellingOrders from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' +import { useCancellingOrders } from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { EMPTY_ARRAY, RTK_QUERY_TAGS, TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React } from 'hooks' @@ -93,7 +93,7 @@ const TableFooter = ({ children = [], isTabActive }: { children: ReactNode[]; is ) : null } -export default function ListMyOrder({ customChainId }: { customChainId?: ChainId }) { +const ListMyOrder = ({ customChainId }: { customChainId?: ChainId }) => { const { account, chainId: walletChainId, networkInfo } = useActiveWeb3React() const chainId = customChainId || walletChainId const [curPage, setCurPage] = useState(1) @@ -381,3 +381,5 @@ export default function ListMyOrder({ customChainId }: { customChainId?: ChainId
) } + +export default ListMyOrder diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx index 4284f4cc68..9d7dfa9557 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx @@ -11,7 +11,7 @@ import { import { wagmiConfig } from 'components/Web3Provider' import { CancelStatus } from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' import { formatAmountOrder, getErrorMessage, getPayloadTracking } from 'components/swapv2/LimitOrder/helpers' -import useCancellingOrders from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' +import { useCancellingOrders } from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' import { CancelOrderFunction, CancelOrderResponse, @@ -66,7 +66,7 @@ const useGetEncodeLimitOrder = () => { ) } -const useRequestCancelOrder = ({ +export const useRequestCancelOrder = ({ orders, isCancelAll, totalOrder, @@ -298,5 +298,3 @@ export const useEstimateFee = ({ isCancelAll = false, orders }: { isCancelAll?: return gasFeeHardCancel } - -export default useRequestCancelOrder diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx index a557a564a0..1c1706dc57 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx @@ -9,7 +9,8 @@ import CancelButtons from 'components/swapv2/LimitOrder/Modals/CancelButtons' import CancelStatusCountDown from 'components/swapv2/LimitOrder/Modals/CancelStatusCountDown' import { Container, Header, Label, ListInfo, Note, Rate, Value } from 'components/swapv2/LimitOrder/Modals/components' import { calcPercentFilledOrder, formatAmountOrder } from 'components/swapv2/LimitOrder/helpers' -import useAllActiveOrders, { +import { + useAllActiveOrders, useIsSupportSoftCancelOrder, } from 'components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders' import { CancelOrderFunction, CancelOrderType, LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' @@ -27,7 +28,7 @@ export enum CancelStatus { } const styleLogo = { width: 20, height: 20 } -function CancelOrderModal({ +const CancelOrderModal = ({ isCancelAll, customChainId, order, @@ -43,7 +44,7 @@ function CancelOrderModal({ onDismiss: () => void flowState: TransactionFlowState isOpen: boolean -}) { +}) => { const currencyIn = useCurrencyV2(order?.makerAsset, customChainId) || undefined const currencyOut = useCurrencyV2(order?.takerAsset, customChainId) || undefined const { tradeInfo: marketPrice } = useBaseTradeInfoLimitOrder(currencyIn, currencyOut) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx index 0306220df5..060ff693ec 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx @@ -20,7 +20,7 @@ const CountDownWrapper = ({ children, className }: { children: React.ReactNode;
{children}
) -export default function CancelStatusCountDown({ +const CancelStatusCountDown = ({ expiredTime, cancelStatus, setCancelStatus, @@ -30,7 +30,7 @@ export default function CancelStatusCountDown({ cancelStatus: CancelStatus setCancelStatus: (v: CancelStatus) => void flowState: TransactionFlowState -}) { +}) => { const { errorMessage, attemptingTxn } = flowState const pendingText = flowState.pendingText || t`Canceling order` @@ -118,3 +118,5 @@ export default function CancelStatusCountDown({ ) } + +export default CancelStatusCountDown diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx index b701d4fa57..042c6ad6dc 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx @@ -1,7 +1,7 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' import dayjs from 'dayjs' -import { ReactNode, memo, useMemo, useState } from 'react' +import { ReactNode, useMemo, useState } from 'react' import { ButtonPrimary, ButtonWarning } from 'components/Button' import Column from 'components/Column' @@ -15,9 +15,22 @@ import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import ErrorWarningPanel from 'pages/Bridge/ErrorWarning' import { TransactionFlowState } from 'types/TransactionFlowState' -const styleLogo = { width: 20, height: 20 } +type Props = { + onSubmit: () => void + onDismiss: () => void + flowState: TransactionFlowState + currencyIn: Currency | undefined + currencyOut: Currency | undefined + inputAmount: string + outputAmount: string + expiredAt: number + marketPrice: BaseTradeInfo | undefined + rateInfo: RateInfo + warningMessage: ReactNode[] + percentDiff: number +} -export default memo(function ConfirmOrderModal({ +const ConfirmOrderModal = ({ onSubmit, currencyIn, currencyOut, @@ -30,20 +43,7 @@ export default memo(function ConfirmOrderModal({ rateInfo, warningMessage, percentDiff, -}: { - onSubmit: () => void - onDismiss: () => void - flowState: TransactionFlowState - currencyIn: Currency | undefined - currencyOut: Currency | undefined - inputAmount: string - outputAmount: string - expiredAt: number - marketPrice: BaseTradeInfo | undefined - rateInfo: RateInfo - warningMessage: ReactNode[] - percentDiff: number -}) { +}: Props) => { const { account } = useActiveWeb3React() const [confirmed, setConfirmed] = useState(false) const shouldShowConfirmFlow = percentDiff < WORSE_PRICE_DIFF_THRESHOLD @@ -54,7 +54,7 @@ export default memo(function ConfirmOrderModal({ label: t`I pay`, content: currencyIn && inputAmount && ( - + {formatAmountOrder(inputAmount)} {currencyIn?.symbol} @@ -65,7 +65,7 @@ export default memo(function ConfirmOrderModal({ label: t`and receive`, content: outputAmount && ( - + {formatAmountOrder(outputAmount)} {currencyOut?.symbol} @@ -195,4 +195,6 @@ export default memo(function ConfirmOrderModal({ pendingText={flowState.pendingText || t`Placing order`} /> ) -}) +} + +export default ConfirmOrderModal diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx index d0d9dc9a3e..297cb2f067 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx @@ -64,7 +64,7 @@ const getStepLabel = ({ return t`Sign order` } -export default function ProcessingOrderModal({ +const ProcessingOrderModal = ({ chainId, currencyIn, state, @@ -78,7 +78,7 @@ export default function ProcessingOrderModal({ onDismiss: () => void onRetryStep: (step: ProcessingOrderStep) => void onRunStep: (step: ProcessingOrderStep) => void -}) { +}) => { useEffect(() => { if (!state.show || !state.currentStep || state.errorStep) return onRunStep(state.currentStep) @@ -128,3 +128,5 @@ export default function ProcessingOrderModal({ ) } + +export default ProcessingOrderModal diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/components.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/components.tsx index 6c35abb0c4..f7d5e0083d 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/components.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/components.tsx @@ -60,7 +60,7 @@ export const Note = ({ note }: { note?: string }) => type ListDataType = { label: string; content: ReactNode }[] -export function ListInfo({ +export const ListInfo = ({ title, listData, marketPrice, @@ -72,7 +72,7 @@ export function ListInfo({ marketPrice: BaseTradeInfo | undefined symbolIn: string | undefined symbolOut: string | undefined -}) { +}) => { return ( {title && } diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx index ac2de26522..d9d052887a 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx @@ -44,7 +44,7 @@ const AmountInfo = ({
) -export default function OrderItem({ +const OrderItem = ({ reverse, order, style, @@ -52,7 +52,7 @@ export default function OrderItem({ reverse?: boolean order: LimitOrderFromTokenPairFormatted style: CSSProperties -}) { +}) => { const upToExtraSmall = useMedia(`(max-width: ${MEDIA_WIDTHS.upToExtraSmall}px)`) const { currencyIn: makerCurrency, currencyOut: takerCurrency } = useLimitState() @@ -78,3 +78,5 @@ export default function OrderItem({ ) } + +export default OrderItem diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx index 315bddf608..8262a1831c 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx @@ -5,7 +5,7 @@ import { ItemWrapper } from 'components/swapv2/LimitOrder/OrderBook/OrderItem' import { useLimitState } from 'state/limit/hooks' import { MEDIA_WIDTHS } from 'theme' -export default function TableHeader() { +const TableHeader = () => { const upToExtraSmall = useMedia(`(max-width: ${MEDIA_WIDTHS.upToExtraSmall}px)`) const { currencyIn, currencyOut } = useLimitState() @@ -47,3 +47,5 @@ export default function TableHeader() { ) } + +export default TableHeader diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx index 0aeafd132c..4cc5274545 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx @@ -128,7 +128,7 @@ const formatOrders = ( return mergedOrders } -export default function OrderBook() { +const OrderBook = () => { const upToSmall = useMedia(`(max-width: ${MEDIA_WIDTHS.upToSmall}px)`) const { chainId, networkInfo } = useActiveWeb3React() @@ -261,3 +261,5 @@ export default function OrderBook() {
) } + +export default OrderBook diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts index 1d2b4ace52..6314aea053 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts @@ -23,7 +23,7 @@ export const DOCS_LINKS = { } // js number to fraction -export function parseFraction(value: string, decimals = RESERVE_USD_DECIMALS) { +export const parseFraction = (value: string, decimals = RESERVE_USD_DECIMALS) => { try { return new Fraction( parseUnits(value, decimals).toString(), @@ -44,7 +44,7 @@ export const removeTrailingZero = (num: string) => { return num.replace(/^([\d,]+)$|^([\d,]+)\.0*$|^([\d,]+\.[0-9]*?)0*$/, '$1$2$3') } -export function calcOutput(input: string, rate: string | Fraction, decimalsOut: number) { +export const calcOutput = (input: string, rate: string | Fraction, decimalsOut: number) => { try { const value = parseFraction(input).multiply(typeof rate === 'string' ? parseFraction(rate) : rate) return removeTrailingZero(value.toFixed(decimalsOut)) @@ -53,7 +53,7 @@ export function calcOutput(input: string, rate: string | Fraction, decimalsOut: } } -export function calcRate(input: string, output: string, decimalsOut: number) { +export const calcRate = (input: string, output: string, decimalsOut: number) => { try { if (input && input === output) return '1' const rate = parseFraction(output, decimalsOut).divide(parseFraction(input)) @@ -64,7 +64,7 @@ export function calcRate(input: string, output: string, decimalsOut: number) { } // calc 1/value -export function calcInvert(value: string) { +export const calcInvert = (value: string) => { try { if (parseFloat(value) === 1) return '1' return removeTrailingZero(new Fraction(1).divide(parseFraction(value)).toFixed(16)) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts index 5fc0602e68..f0067b06ed 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts @@ -13,7 +13,7 @@ export type CancellingOrderInfo = { isOrderCancelling: (order: LimitOrder) => boolean } -export default function useCancellingOrders(): CancellingOrderInfo { +export const useCancellingOrders = (): CancellingOrderInfo => { const { account, chainId } = useActiveWeb3React() const [cancellingOrdersIds, setCancellingOrdersIds] = useState([]) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx index baa293cd79..33094674c5 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx @@ -7,7 +7,7 @@ import { NotificationType } from 'components/Announcement/type' import { getTipLinkAttribution } from 'components/TipLinkGeneratorModal/shared' import { SummaryNotifyOrderPlaced } from 'components/swapv2/LimitOrder/ListOrder/SummaryNotify' import { calcUsdPrices, getPayloadCreateOrder, removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' -import useSignOrder from 'components/swapv2/LimitOrder/hooks/useSignOrder' +import { useSignOrder } from 'components/swapv2/LimitOrder/hooks/useSignOrder' import { CreateOrderParam, LimitOrderCreateContext } from 'components/swapv2/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' @@ -26,14 +26,14 @@ type UseCreateLimitOrderArgs = { onSuccess: () => void } -export default function useCreateLimitOrder({ +export const useCreateLimitOrder = ({ order, setFlowState, searchParams, estimateUSD, onError, onSuccess, -}: UseCreateLimitOrderArgs) { +}: UseCreateLimitOrderArgs) => { const { currencyIn, currencyOut, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts index 6bde156544..3be0e40bfe 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts @@ -19,7 +19,7 @@ export const useIsSupportSoftCancelOrder = () => { ) } -export default function useAllActiveOrders(disabled = false, customChainId?: ChainId) { +export const useAllActiveOrders = (disabled = false, customChainId?: ChainId) => { const { account, chainId } = useActiveWeb3React() const { data } = useGetListOrdersQuery( { chainId: customChainId ?? chainId, maker: account, status: LimitOrderStatus.ACTIVE, pageSize: 100 }, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx index 51cabe859f..58800cf597 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx @@ -6,9 +6,9 @@ import { useGetLOConfigQuery, useGetTotalActiveMakingAmountQuery } from 'service import { calcUsdPrices, getErrorMessage, removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' import { ProcessingOrderStep } from 'components/swapv2/LimitOrder/hooks/useProcessingOrder' -import useValidateInputError from 'components/swapv2/LimitOrder/hooks/useValidateInputError' -import useWarningCreateOrder from 'components/swapv2/LimitOrder/hooks/useWarningCreateOrder' -import useWrapEthStatus from 'components/swapv2/LimitOrder/hooks/useWrapEthStatus' +import { useValidateInputError } from 'components/swapv2/LimitOrder/hooks/useValidateInputError' +import { useWarningCreateOrder } from 'components/swapv2/LimitOrder/hooks/useWarningCreateOrder' +import { useWrapEthStatus } from 'components/swapv2/LimitOrder/hooks/useWrapEthStatus' import { LimitOrderCreateContext } from 'components/swapv2/LimitOrder/types' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { NativeCurrencies } from 'constants/tokens' @@ -33,13 +33,13 @@ type UseLimitOrderExecutionArgs = { const getTokenAddress = (currency: Currency | undefined) => (currency?.isNative ? 'NATIVE' : currency?.wrapped?.address) -export default function useLimitOrderExecution({ +export const useLimitOrderExecution = ({ order, setFlowState, onSetInput, onResetForm, switchToWeth, -}: UseLimitOrderExecutionArgs) { +}: UseLimitOrderExecutionArgs) => { const { currencyIn, currencyOut, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts index f7c5146120..480d854797 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts @@ -28,7 +28,7 @@ export type LimitOrderFormStateArgs = { const DEFAULT_EXPIRED = 36500 * TIMES_IN_SECS.ONE_DAY const DEFAULT_RATE_INFO: RateInfo = { rate: '', invertRate: '', invert: false } -export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrlParams }: LimitOrderFormStateArgs) { +export const useLimitOrderFormState = ({ currencyIn, currencyOut, useUrlParams }: LimitOrderFormStateArgs) => { const { chainId: walletChainId, networkInfo } = useActiveWeb3React() const { trackingHandler } = useTracking() const [searchParams, setSearchParams] = useSearchParams() @@ -52,7 +52,6 @@ export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrl const [expire, setExpire] = useState(DEFAULT_EXPIRED) const [showDatePicker, setShowDatePicker] = useState(false) const [customDateExpire, setCustomDateExpire] = useState() - const [rotate, setRotate] = useState(false) const [expanded, setExpanded] = useState(false) const { loading: loadingTrade, tradeInfo } = useBaseTradeInfoLimitOrder(currencyIn, currencyOut, chainId) @@ -229,7 +228,6 @@ export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrl to_token: currencyIn?.symbol, chain: networkInfo.name, }) - setRotate(prev => !prev) switchCurrency() setInputAmount(outputAmount) setOutputAmount(inputAmount) @@ -298,7 +296,6 @@ export default function useLimitOrderFormState({ currencyIn, currencyOut, useUrl expire, showDatePicker, customDateExpire, - rotate, expanded, loadingTrade, tradeInfo, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx index 88591f3c99..f67a9d6f62 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx @@ -23,7 +23,7 @@ const isTransactionFailed = (txHash: string, transactions: GroupedTxsByHash | un return transactionInfo ? getTransactionStatus(transactionInfo).error : false } -const useNotificationLimitOrder = () => { +export const useNotificationLimitOrder = () => { const notify = useNotify() const { account, chainId } = useActiveWeb3React() const showedNotificationOrderIds = useRef<{ [id: string]: boolean }>({}) @@ -176,4 +176,3 @@ const useNotificationLimitOrder = () => { } }, [account, chainId, notify, ackNotificationOrder, ackNotiLocal, transactions]) } -export default useNotificationLimitOrder diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useProcessingOrder.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useProcessingOrder.ts index 17368a125e..9aeedeab33 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useProcessingOrder.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useProcessingOrder.ts @@ -32,7 +32,7 @@ const DEFAULT_PROCESSING_ORDER: ProcessingOrderState = { completedSteps: [], } -export default function useProcessingOrder({ +export const useProcessingOrder = ({ approval, approveCallback, steps, @@ -42,7 +42,7 @@ export default function useProcessingOrder({ onCreateOrder, onError, setFlowState, -}: UseProcessingOrderArgs) { +}: UseProcessingOrderArgs) => { const [processingOrder, setProcessingOrder] = useState(DEFAULT_PROCESSING_ORDER) const processingStepStartedRef = useRef() const approvalRef = useRef(ApprovalState.UNKNOWN) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts index a2a0742615..38831b68ec 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts @@ -10,9 +10,7 @@ import { formatSignature } from 'utils/transaction' import { Address } from 'utils/viem' import { signTypedDataRaw } from 'utils/walletClient' -export default function useSignOrder( - setFlowState: React.Dispatch> | undefined, -) { +export const useSignOrder = (setFlowState: React.Dispatch> | undefined) => { const { account, chainId } = useActiveWeb3React() const [getMessageSignature] = useCreateOrderSignatureMutation() diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx index c0736d26b5..b5fbcc1d24 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx @@ -5,7 +5,7 @@ import { useMemo } from 'react' import { useActiveWeb3React } from 'hooks' import { tryParseAmount } from 'state/swap/hooks' -const useValidateInputError = ({ +export const useValidateInputError = ({ inputAmount, outputAmount, displayRate, @@ -43,4 +43,3 @@ const useValidateInputError = ({ }, [outputAmount, currencyOut]) return { inputError, outPutError } } -export default useValidateInputError diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx index a2b6c58e08..d2ce4bd8b9 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx @@ -24,7 +24,7 @@ const USD_THRESHOLD = new Proxy(_USD_THRESHOLD, { }, }) -export default function useWarningCreateOrder({ +export const useWarningCreateOrder = ({ currencyIn, outputAmount, displayRate, @@ -38,7 +38,7 @@ export default function useWarningCreateOrder({ deltaRate: DeltaRateLimitOrder estimateUSD: number missingAllowance: boolean | CurrencyAmount -}) { +}) => { const { chainId } = useActiveWeb3React() const warningMessage = useMemo(() => { const messages = [] diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWrapEthStatus.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWrapEthStatus.ts index 967410895f..53aced8741 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWrapEthStatus.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWrapEthStatus.ts @@ -3,7 +3,7 @@ import { usePrevious } from 'react-use' import { useIsTransactionPending } from 'state/transactions/hooks' -export default function useWrapEthStatus(switchToWeth: () => void) { +export const useWrapEthStatus = (switchToWeth: () => void) => { const [txHashWrapped, setTxHashWrapped] = useState() const isWrappingEth = useIsTransactionPending(txHashWrapped) diff --git a/apps/kyberswap-interface/src/pages/SwapV3/index.tsx b/apps/kyberswap-interface/src/pages/SwapV3/index.tsx index 9927161686..ab9d0e3fab 100644 --- a/apps/kyberswap-interface/src/pages/SwapV3/index.tsx +++ b/apps/kyberswap-interface/src/pages/SwapV3/index.tsx @@ -132,7 +132,7 @@ export default function Swap() { {isSwapPage && ( Date: Thu, 18 Jun 2026 15:40:17 +0700 Subject: [PATCH 10/52] chore(limit): polish order form UI --- .../components/SwapForm/SlippageSetting.tsx | 2 +- .../Form/LimitOrderExpirySection.tsx | 114 ++++++++++++------ .../swapv2/LimitOrder/Form/LimitOrderForm.tsx | 17 ++- .../swapv2/LimitOrder/Form/MarketPrice.tsx | 49 ++++++++ .../swapv2/LimitOrder/Form/TradePrice.tsx | 78 ------------ .../swapv2/LimitOrder/Modals/components.tsx | 12 +- .../hooks/useLimitOrderExecution.tsx | 2 - .../hooks/useWarningCreateOrder.tsx | 45 +------ 8 files changed, 138 insertions(+), 181 deletions(-) create mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/MarketPrice.tsx delete mode 100644 apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/TradePrice.tsx diff --git a/apps/kyberswap-interface/src/components/SwapForm/SlippageSetting.tsx b/apps/kyberswap-interface/src/components/SwapForm/SlippageSetting.tsx index 90c3708456..b7e6f726a0 100644 --- a/apps/kyberswap-interface/src/components/SwapForm/SlippageSetting.tsx +++ b/apps/kyberswap-interface/src/components/SwapForm/SlippageSetting.tsx @@ -110,7 +110,7 @@ const SlippageSetting = ({ rightComponent, tooltip, slippageInfo }: Props) => {
diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx index 0aa2994c1a..a14825100a 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx @@ -1,29 +1,37 @@ import { Trans, t } from '@lingui/macro' +import { ButtonHTMLAttributes } from 'react' +import { Calendar, ChevronDown } from 'react-feather' -import { ReactComponent as DropdownSVG } from 'assets/svg/down.svg' -import { DefaultSlippageOption } from 'components/SlippageControl' +import { HStack, Stack } from 'components/Stack' +import { DropdownIcon } from 'components/SwapForm/SlippageSetting' import { TextDashed } from 'components/Text' import { MouseoverTooltip } from 'components/Tooltip' import { TIMES_IN_SECS } from 'constants/index' import { cn } from 'utils/cn' -import { formatTimeDuration } from 'utils/time' -const DropdownIcon = ({ className, ...rest }: React.SVGProps & { 'data-flip'?: boolean }) => ( - & { active?: boolean; custom?: boolean }) => ( + + ) + })} +
setCustomDate(date, hour, min)} /> @@ -189,7 +205,7 @@ export default function DateTimePicker({
{dayjs(expireResult).format('DD/MM/YYYY HH:mm')}
-
+
(null) + const popperRef = useRef() + const outsideRefs = useMemo(() => [ref, popperRef], []) - useOnClickOutside(ref, () => { - setShowMenu(false) - onHideMenu?.() - }) + useOnClickOutside( + outsideRefs, + () => { + setShowMenu(false) + onHideMenu?.() + }, + { ignoreReachPortal: false }, + ) const selectedInfo = options.find(item => getOptionValue(item) === selected) const shouldShowPlaceholder = hasPlaceholder && (selectedValue === null || selectedValue === undefined) && !selectedInfo @@ -150,6 +156,10 @@ export default function Select({ } const [popperElement, setPopperElement] = useState(null) + const setPopperRef = (node: HTMLDivElement | null) => { + popperRef.current = node || undefined + setPopperElement(node) + } const { styles } = usePopper(ref.current, popperElement, { placement: placement, @@ -178,7 +188,7 @@ export default function Select({ {showMenu && (
( node: RefObject | RefObject[], handler: undefined | (() => void), + { ignoreReachPortal = true }: { ignoreReachPortal?: boolean } = {}, ) { const handlerRef = useRef void)>(handler) handlerRef.current = handler @@ -11,7 +12,10 @@ export function useOnClickOutside( useEffect(() => { const handleClickOutside = (e: MouseEvent | TouchEvent) => { let nodes: RefObject[] - if ([...document.getElementsByTagName('reach-portal')].some((el: Element) => el.contains(e.target as Node))) { + if ( + ignoreReachPortal && + [...document.getElementsByTagName('reach-portal')].some((el: Element) => el.contains(e.target as Node)) + ) { return } if (Array.isArray(node)) nodes = node @@ -27,5 +31,5 @@ export function useOnClickOutside( return () => { document.removeEventListener(isMobile ? 'touchstart' : 'mousedown', handleClickOutside) } - }, [node]) + }, [ignoreReachPortal, node]) } diff --git a/apps/kyberswap-interface/src/tailwind.css b/apps/kyberswap-interface/src/tailwind.css index 5ff68d608b..7994bf5b3d 100644 --- a/apps/kyberswap-interface/src/tailwind.css +++ b/apps/kyberswap-interface/src/tailwind.css @@ -192,7 +192,9 @@ } } @media (max-width: 768px) { - .ks-dialog-content[data-reach-dialog-content]:not([data-has-explicit-width='true']):not([data-mobile-full-width='true']) { + .ks-dialog-content[data-reach-dialog-content]:not([data-has-explicit-width='true']):not( + [data-mobile-full-width='true'] + ) { width: 85vw; } .ks-dialog-content[data-reach-dialog-content][data-mobile='true']:not([data-has-explicit-width='true']) { @@ -400,13 +402,42 @@ color: var(--ks-primary); font-weight: bold; } - .ks-date-picker .custom-calendar .react-calendar__decade-view button, - .ks-date-picker .custom-calendar .react-calendar__century-view button, - .ks-date-picker .custom-calendar .react-calendar__year-view button { - padding: 14px 0.5em; + .ks-date-picker .custom-calendar .react-calendar__decade-view button:not(:disabled):hover, + .ks-date-picker .custom-calendar .react-calendar__century-view button:not(:disabled):hover, + .ks-date-picker .custom-calendar .react-calendar__year-view button:not(:disabled):hover { + background-color: var(--ks-buttonGray); + } + .ks-date-picker + .custom-calendar + :is( + .react-calendar__year-view__months, + .react-calendar__decade-view__years, + .react-calendar__century-view__decades + ) { + gap: 4px; + } + .ks-date-picker + .custom-calendar + :is(.react-calendar__decade-view, .react-calendar__century-view, .react-calendar__year-view) + button { + border-radius: 8px; + padding: 10px 0.5em; + font-weight: bold; + } + .ks-date-picker .custom-calendar .react-calendar__year-view__months__month { + flex-basis: calc((100% - 8px) / 3) !important; + max-width: calc((100% - 8px) / 3); + } + .ks-date-picker + .custom-calendar + :is(.react-calendar__decade-view__years__year, .react-calendar__century-view__decades__decade) { + flex-basis: calc((100% - 16px) / 3) !important; + max-width: calc((100% - 16px) / 3); } .ks-date-picker .custom-calendar .react-calendar__navigation { - margin: 0; + display: flex; + gap: 2px; + margin-bottom: 8px; font-weight: 500; height: auto; } @@ -415,9 +446,12 @@ font-size: 14px; color: var(--ks-text); background-color: transparent; + margin-inline: 8px; + border-radius: 8px; } - .ks-date-picker .custom-calendar .react-calendar__navigation__label:hover { - background-color: transparent; + .ks-date-picker .custom-calendar .react-calendar__navigation__label:enabled:hover, + .ks-date-picker .custom-calendar .react-calendar__navigation__label:enabled:focus { + background-color: var(--ks-buttonBlack); } .ks-date-picker .custom-calendar .react-calendar__navigation__arrow { font-size: 20px; @@ -430,9 +464,16 @@ line-height: 1; min-width: unset; } + .ks-date-picker .custom-calendar .react-calendar__navigation__arrow:enabled:hover, + .ks-date-picker .custom-calendar .react-calendar__navigation__arrow:enabled:focus { + background-color: var(--ks-buttonBlack); + } .ks-date-picker .custom-calendar .react-calendar__navigation__arrow:disabled { background-color: rgba(28, 28, 28, 0.4); } + .ks-date-picker .custom-calendar .react-calendar__viewContainer { + min-height: 232px; + } .ks-date-picker .custom-calendar .react-calendar__month-view__days button { height: 34px; padding: 0; @@ -460,6 +501,7 @@ .react-calendar__month-view__days button.react-calendar__month-view__days__day--neighboringMonth { font-style: italic; + color: var(--ks-subText); } @media (max-width: 992px) { .ks-date-picker .custom-date-picker .custom-calendar .react-calendar__month-view__days button { @@ -583,10 +625,7 @@ } .ks-slider::-webkit-slider-thumb:hover, .ks-slider::-webkit-slider-thumb:focus { - box-shadow: - 0 0 1px rgba(0, 0, 0, 0.1), - 0 4px 8px rgba(0, 0, 0, 0.08), - 0 16px 24px rgba(0, 0, 0, 0.06), + box-shadow: 0 0 1px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08), 0 16px 24px rgba(0, 0, 0, 0.06), 0 24px 32px rgba(0, 0, 0, 0.04); } .ks-slider::-moz-range-thumb { @@ -599,10 +638,7 @@ } .ks-slider::-moz-range-thumb:hover, .ks-slider::-moz-range-thumb:focus { - box-shadow: - 0 0 1px rgba(0, 0, 0, 0.1), - 0 4px 8px rgba(0, 0, 0, 0.08), - 0 16px 24px rgba(0, 0, 0, 0.06), + box-shadow: 0 0 1px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08), 0 16px 24px rgba(0, 0, 0, 0.06), 0 24px 32px rgba(0, 0, 0, 0.04); } .ks-slider::-ms-thumb { @@ -614,10 +650,7 @@ } .ks-slider::-ms-thumb:hover, .ks-slider::-ms-thumb:focus { - box-shadow: - 0 0 1px rgba(0, 0, 0, 0.1), - 0 4px 8px rgba(0, 0, 0, 0.08), - 0 16px 24px rgba(0, 0, 0, 0.06), + box-shadow: 0 0 1px rgba(0, 0, 0, 0.1), 0 4px 8px rgba(0, 0, 0, 0.08), 0 16px 24px rgba(0, 0, 0, 0.06), 0 24px 32px rgba(0, 0, 0, 0.04); } .ks-slider::-webkit-slider-runnable-track { @@ -665,18 +698,34 @@ /* PositionDetail enter animations (rendered with arbitrary `animate-[ks-pd-*]` values). */ @keyframes ks-pd-fade-in { - from { opacity: 0; transform: translateY(4px); } - to { opacity: 1; transform: translateY(0); } + from { + opacity: 0; + transform: translateY(4px); + } + to { + opacity: 1; + transform: translateY(0); + } } @keyframes ks-pd-slide-down { - from { opacity: 0; transform: translateY(-8px); } - to { opacity: 1; transform: translateY(0); } + from { + opacity: 0; + transform: translateY(-8px); + } + to { + opacity: 1; + transform: translateY(0); + } } /* TopBanner marquee — slide distance set via --ks-marquee-shift on the consumer. */ @keyframes ks-top-banner-marquee { - from { transform: translateX(0); } - to { transform: translateX(calc(-1 * var(--ks-marquee-shift, 0px))); } + from { + transform: translateX(0); + } + to { + transform: translateX(calc(-1 * var(--ks-marquee-shift, 0px))); + } } /* Used by — animates an ellipsis after some text (e.g. "Loading..."). */ @@ -973,23 +1022,13 @@ .ks-transactions-tab[data-scrollable='true'][data-scroll-left='true']::before { left: 0; transform: translateX(-1px); - background: linear-gradient( - -90deg, - rgba(0, 0, 0, 0) 0%, - var(--ks-background) 90%, - var(--ks-background) 100% - ); + background: linear-gradient(-90deg, rgba(0, 0, 0, 0) 0%, var(--ks-background) 90%, var(--ks-background) 100%); } .ks-transactions-tab[data-scrollable='true'][data-scroll-right='true']::after { right: 0; transform: translateX(1px); justify-content: flex-end; - background: linear-gradient( - 90deg, - rgba(0, 0, 0, 0) 0%, - var(--ks-background) 90%, - var(--ks-background) 100% - ); + background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, var(--ks-background) 90%, var(--ks-background) 100%); } } From 585e1c5916c2b73b7d42af4dea9cedacf7a6723b Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Thu, 18 Jun 2026 16:47:06 +0700 Subject: [PATCH 12/52] refactor(limit): simplify rate side handling Remove the obsolete rate invert state from the limit order create flow and keep the selected price info helper tied to the sell-rate view. --- .../LimitOrder/Form/LimitOrderRateSection.tsx | 44 ++++++++++++------- .../LimitOrder/hooks/useCreateLimitOrder.tsx | 4 +- .../hooks/useLimitOrderExecution.tsx | 20 +++------ .../hooks/useLimitOrderFormState.ts | 17 +++---- .../src/components/swapv2/LimitOrder/types.ts | 1 - 5 files changed, 41 insertions(+), 45 deletions(-) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx index 10d12d13a1..00c8af901a 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx @@ -2,11 +2,13 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans } from '@lingui/macro' import { useEffect, useMemo, useState } from 'react' +import InfoHelper from 'components/InfoHelper' import NumericalInput from 'components/NumericalInput' import { Stack } from 'components/Stack' import { removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' import { DeltaRateLimitOrder, RateInfo } from 'components/swapv2/LimitOrder/types' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' +import useTheme from 'hooks/useTheme' import { cn } from 'utils/cn' export const useGetDeltaRateLimitOrder = ({ @@ -19,11 +21,9 @@ export const useGetDeltaRateLimitOrder = ({ const { deltaText, percent } = useMemo(() => { try { if (marketPrice && rateInfo.rate && rateInfo.invertRate) { - const { rate, invert, invertRate } = rateInfo - const ourRate = Number(invert ? invertRate : rate) - const marketRate = Number(invert ? marketPrice.invertRate : marketPrice.marketRate) - let percent = ((ourRate - marketRate) / marketRate) * 100 - if (invert) percent = -percent + const ourRate = Number(rateInfo.rate) + const marketRate = Number(marketPrice.marketRate) + const percent = ((ourRate - marketRate) / marketRate) * 100 const delta = Number(percent) const sign = delta > 0 ? '+' : '' const deltaText = `${Math.abs(delta) > 100 ? '>100' : `${sign}${delta.toFixed(2)}`}%` @@ -49,10 +49,28 @@ const RateLabel = ({ children, className, ...rest }: React.HTMLAttributes ) -const DeltaRate = ({ symbol, invert }: { symbol: string; invert: boolean }) => { +const DeltaRate = ({ symbol, deltaRate }: { symbol: string; deltaRate: DeltaRateLimitOrder }) => { + const theme = useTheme() + const { percent, profit } = deltaRate + const color = profit ? theme.apr : theme.warning + const colorClass = profit ? 'text-apr' : 'text-warning' + const styledPercent = {percent} + return ( - {invert ? Buy {symbol} at rate : Sell {symbol} at rate} + Sell {symbol} at rate + {percent ? ( + Your selected price is {styledPercent} better than the current market price. + ) : ( + Your selected price is {styledPercent} worse than the current market price. + ) + } + /> + ) : null} ) } @@ -137,14 +155,14 @@ type RateSectionEvents = { onRateInputBlur?: () => void } -const DEFAULT_RATE_INFO: RateInfo = { rate: '', invertRate: '', invert: false } +const DEFAULT_RATE_INFO: RateInfo = { rate: '', invertRate: '' } const RATE_DELTA_OPTIONS = [10, 20, 50] const LimitOrderRateSection = ({ tokens = {}, rate = {}, events = {} }: Props) => { const { currencyIn, currencyOut } = tokens const { displayRate = '', rateInfo = DEFAULT_RATE_INFO, tradeInfo } = rate const deltaRate = useGetDeltaRateLimitOrder({ marketPrice: tradeInfo, rateInfo }) - const unitCurrency = rateInfo.invert ? currencyIn : currencyOut + const unitCurrency = currencyOut const percentInputValue = deltaRate.rawPercent === undefined || !Number.isFinite(deltaRate.rawPercent) ? '' @@ -152,8 +170,7 @@ const LimitOrderRateSection = ({ tokens = {}, rate = {}, events = {} }: Props) = const setRateByDelta = (percent: number) => { if (!tradeInfo) return - const market = rateInfo.invert ? tradeInfo.invertRate : tradeInfo.marketRate - const nextRate = market * (1 + (rateInfo.invert ? -percent : percent) / 100) + const nextRate = tradeInfo.marketRate * (1 + percent / 100) events.onRateChange?.(removeTrailingZero(nextRate.toFixed(16)) ?? '') } @@ -168,10 +185,7 @@ const LimitOrderRateSection = ({ tokens = {}, rate = {}, events = {} }: Props) = return (
- +
diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx index 33094674c5..1c206b65bb 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx @@ -44,7 +44,6 @@ export const useCreateLimitOrder = ({ displayRate, expiredAt, displayTime, - rateInfo, tradeInfo, deltaRate, } = order @@ -118,7 +117,7 @@ export const useCreateLimitOrder = ({ trackPlaceOrder(TRACKING_EVENT_TYPE.LO_PLACE_ORDER_SUCCESS, { order_id }) trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_PLACED, { - side: rateInfo.invert ? 'buy' : 'sell', + side: 'sell', from_token: currencyIn?.symbol, from_token_address: getTokenAddress(currencyIn), to_token: currencyOut?.symbol, @@ -168,7 +167,6 @@ export const useCreateLimitOrder = ({ inputAmount, networkName, outputAmount, - rateInfo.invert, searchParams, submitCreateOrder, trackPlaceOrder, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx index 0fa6577e27..c3effd8203 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx @@ -49,7 +49,6 @@ export const useLimitOrderExecution = ({ outputAmount, displayRate, displayTime, - rateInfo, tradeInfo, deltaRate, } = order @@ -198,7 +197,7 @@ export const useLimitOrderExecution = ({ const trackingPriceSetOnBlur = useCallback(() => { if (!displayRate || !currencyIn || !currencyOut) return trackingHandler(TRACKING_EVENT_TYPE.LO_PRICE_SET, { - side: rateInfo.invert ? 'buy' : 'sell', + side: 'sell', limit_price: displayRate, market_price: tradeInfo ? removeTrailingZero(tradeInfo.marketRate.toFixed(16)) : undefined, price_difference_pct: deltaRate.rawPercent ? Number(deltaRate.rawPercent) : undefined, @@ -206,16 +205,7 @@ export const useLimitOrderExecution = ({ to_token: currencyOut.symbol, chain: networkName, }) - }, [ - displayRate, - currencyIn, - currencyOut, - rateInfo.invert, - tradeInfo, - deltaRate.rawPercent, - networkName, - trackingHandler, - ]) + }, [displayRate, currencyIn, currencyOut, tradeInfo, deltaRate.rawPercent, networkName, trackingHandler]) const trackingTouchSelectToken = useCallback(() => { trackingHandler(TRACKING_EVENT_TYPE.LO_ENTER_DETAIL, 'touch enter token box') @@ -235,7 +225,7 @@ export const useLimitOrderExecution = ({ }) trackingHandler(TRACKING_EVENT_TYPE.LO_REVIEW_OPENED, { - side: rateInfo.invert ? 'buy' : 'sell', + side: 'sell', from_token: currencyIn.symbol, from_token_address: getTokenAddress(currencyIn), to_token: currencyOut.symbol, @@ -263,7 +253,7 @@ export const useLimitOrderExecution = ({ errorMessage.toLowerCase().includes('user denied') || errorMessage.toLowerCase().includes('user rejected') trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_FAILED, { - side: rateInfo.invert ? 'buy' : 'sell', + side: 'sell', from_token: currencyIn?.symbol, to_token: currencyOut?.symbol, pair: currencyIn && currencyOut ? `${currencyIn.symbol}/${currencyOut.symbol}` : undefined, @@ -280,7 +270,7 @@ export const useLimitOrderExecution = ({ errorMessage, })) }, - [setFlowState, trackingHandler, rateInfo.invert, currencyIn, currencyOut, displayRate, inputAmount, networkName], + [setFlowState, trackingHandler, currencyIn, currencyOut, displayRate, inputAmount, networkName], ) // Keep active making amount fresh after order state updates. diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts index 480d854797..49eaba2cf0 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts @@ -26,7 +26,7 @@ export type LimitOrderFormStateArgs = { } const DEFAULT_EXPIRED = 36500 * TIMES_IN_SECS.ONE_DAY -const DEFAULT_RATE_INFO: RateInfo = { rate: '', invertRate: '', invert: false } +const DEFAULT_RATE_INFO: RateInfo = { rate: '', invertRate: '' } export const useLimitOrderFormState = ({ currencyIn, currencyOut, useUrlParams }: LimitOrderFormStateArgs) => { const { chainId: walletChainId, networkInfo } = useActiveWeb3React() @@ -56,7 +56,7 @@ export const useLimitOrderFormState = ({ currencyIn, currencyOut, useUrlParams } const { loading: loadingTrade, tradeInfo } = useBaseTradeInfoLimitOrder(currencyIn, currencyOut, chainId) - const displayRate = rateInfo.invert ? rateInfo.invertRate : rateInfo.rate + const displayRate = rateInfo.rate const expiredAt = customDateExpire?.getTime() || Date.now() + expire * 1000 const displayTime = customDateExpire ? dayjs(customDateExpire).format('DD/MM/YYYY HH:mm') : formatTimeDuration(expire) @@ -151,7 +151,7 @@ export const useLimitOrderFormState = ({ currencyIn, currencyOut, useUrlParams } const onChangeRate = (val: string) => { if (currencyOut) { - onSetRate(rateInfo.invert ? '' : val, rateInfo.invert ? val : '') + onSetRate(val, '') } } @@ -164,7 +164,7 @@ export const useLimitOrderFormState = ({ currencyIn, currencyOut, useUrlParams } onSetRate(marketRate, removeTrailingZero(tradeInfo.invertRate.toFixed(16)) ?? '') if (!autoFillInput) { trackingHandler(TRACKING_EVENT_TYPE.LO_PRICE_SET, { - side: rateInfo.invert ? 'buy' : 'sell', + side: 'sell', limit_price: marketRate, market_price: marketRate, price_difference_pct: 0, @@ -175,7 +175,7 @@ export const useLimitOrderFormState = ({ currencyIn, currencyOut, useUrlParams } } } catch (error) {} }, - [loadingTrade, trackingHandler, onSetRate, tradeInfo, rateInfo.invert, currencyIn, currencyOut, networkInfo.name], + [loadingTrade, trackingHandler, onSetRate, tradeInfo, currencyIn, currencyOut, networkInfo.name], ) const onSetOutput = (output: string) => { @@ -191,10 +191,6 @@ export const useLimitOrderFormState = ({ currencyIn, currencyOut, useUrlParams } setOutputAmount(output) } - const onInvertRate = (invert: boolean) => { - setRateInfo(rateInfo => ({ ...rateInfo, invert })) - } - const handleInputSelect = useCallback( (currency: Currency, resetRate = true) => { if (currencyOut && currency?.equals(currencyOut)) { @@ -223,7 +219,7 @@ export const useLimitOrderFormState = ({ currencyIn, currencyOut, useUrlParams } const handleRotateClick = () => { trackingHandler(TRACKING_EVENT_TYPE.LO_SIDE_SELECTED, { - side: rateInfo.invert ? 'sell' : 'buy', + side: 'buy', from_token: currencyOut?.symbol, to_token: currencyIn?.symbol, chain: networkInfo.name, @@ -305,7 +301,6 @@ export const useLimitOrderFormState = ({ currencyIn, currencyOut, useUrlParams } onSetInput, onSetOutput, onChangeRate, - onInvertRate, handleInputSelect, switchToWeth, handleOutputSelect, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/types.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/types.ts index bc0c2fe975..c6360ca8cd 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/types.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/types.ts @@ -107,7 +107,6 @@ export enum CancelOrderType { export type RateInfo = { rate: string // to store user input invertRate: string // to store user input - invert: boolean rateFraction?: Fraction // to calc with big number } From 02225c0d24c07db0595719e089761dddcea11f8b Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Thu, 18 Jun 2026 19:06:16 +0700 Subject: [PATCH 13/52] fix(limit-order): sync rate percent active state --- .../LimitOrder/Form/LimitOrderRateSection.tsx | 78 ++++++++++++++++--- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx index 00c8af901a..3f0a21cb9d 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx @@ -1,5 +1,5 @@ import { Currency } from '@kyberswap/ks-sdk-core' -import { Trans } from '@lingui/macro' +import { Trans, t } from '@lingui/macro' import { useEffect, useMemo, useState } from 'react' import InfoHelper from 'components/InfoHelper' @@ -75,11 +75,19 @@ const DeltaRate = ({ symbol, deltaRate }: { symbol: string; deltaRate: DeltaRate ) } -const RateChip = ({ children, className, ...rest }: React.ButtonHTMLAttributes) => ( +const RateChip = ({ + children, + className, + isActive, + ...rest +}: React.ButtonHTMLAttributes & { isActive?: boolean }) => ( + ) + })}
) } diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx index a6b0224c1d..b5b7326604 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/index.tsx @@ -44,7 +44,10 @@ import { const PAGE_SIZE = 10 export const NoResultWrapper = ({ className, ...rest }: HTMLAttributes) => ( -
+
) const ACTIVE_ORDER_OPTIONS = () => [ @@ -281,15 +284,13 @@ const ListMyOrder = ({ customChainId }: { customChainId?: ChainId }) => { const isTabActive = isActiveStatus(orderType) return ( -
-
- -
+
+ -
+
- - -
- {loading ? ( - - ) : ( -
- - - {orders.map((order, index) => ( - - ))} - - {orders.length !== 0 ? ( - - {isTabActive && ( - - - - Cancel All - - - )} - {totalOrder > PAGE_SIZE && ( - - )} - - ) : ( - - - - {keyword ? ( - No orders found. - ) : isTabActive ? ( - You don't have any open orders yet. - ) : ( - You don't have any order history. - )} - - - )} -
- )} - - -
- ) -} - -export default ListMyOrder diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx index 1c1706dc57..d83c26a20f 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx @@ -4,10 +4,10 @@ import { useEffect, useMemo, useState } from 'react' import Logo from 'components/Logo' import Modal from 'components/Modal' -import { useEstimateFee, useProcessCancelOrder } from 'components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder' import CancelButtons from 'components/swapv2/LimitOrder/Modals/CancelButtons' import CancelStatusCountDown from 'components/swapv2/LimitOrder/Modals/CancelStatusCountDown' import { Container, Header, Label, ListInfo, Note, Rate, Value } from 'components/swapv2/LimitOrder/Modals/components' +import { useEstimateFee, useProcessCancelOrder } from 'components/swapv2/LimitOrder/MyOrders/useRequestCancelOrder' import { calcPercentFilledOrder, formatAmountOrder } from 'components/swapv2/LimitOrder/helpers' import { useAllActiveOrders, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/OrderItem.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/OrderItem.tsx new file mode 100644 index 0000000000..b5f1861218 --- /dev/null +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/OrderItem.tsx @@ -0,0 +1,204 @@ +import { Token } from '@kyberswap/ks-sdk-core' +import { Trans, t } from '@lingui/macro' +import { useMemo } from 'react' +import { Trash } from 'react-feather' +import { useNavigate, useSearchParams } from 'react-router-dom' + +import { calcPercentFilledOrder, isActiveStatus } from 'components/swapv2/LimitOrder/helpers' +import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +import { NETWORKS_INFO } from 'constants/networks' +import { NativeCurrencies } from 'constants/tokens' +import { useTokenBalance } from 'state/wallet/hooks' +import { cn } from 'utils/cn' +import { toCurrencyAmount } from 'utils/currencyAmount' +import { formatDisplayNumber, uint256ToFraction } from 'utils/numbers' + +const formatAmountWithSymbol = (amount: string, symbol?: string) => `${amount} ${symbol ?? ''}`.trim() + +const formatOrderDisplayAmount = (amount: string, decimals: number) => + formatDisplayNumber(uint256ToFraction(amount, decimals).toFixed(18), { significantDigits: 6 }) + +const formatOrderDisplayRate = (order: LimitOrder) => { + const rate = uint256ToFraction(order.makingAmount, order.makerAssetDecimals).divide( + uint256ToFraction(order.takingAmount, order.takerAssetDecimals), + ) + return formatDisplayNumber(rate.toFixed(18), { significantDigits: 6 }) +} + +const formatStatus = (status: LimitOrderStatus) => { + switch (status) { + case LimitOrderStatus.ACTIVE: + case LimitOrderStatus.OPEN: + return t`Active` + case LimitOrderStatus.PARTIALLY_FILLED: + return t`Partially Filled` + case LimitOrderStatus.FILLED: + return t`Filled` + case LimitOrderStatus.CANCELLING: + return t`Cancelling` + case LimitOrderStatus.CANCELLED: + return t`Cancelled` + case LimitOrderStatus.EXPIRED: + return t`Expired` + case LimitOrderStatus.INSUFFICIENT_FUNDS: + return t`Insufficient funds` + default: + return status.replace('_', ' ') + } +} + +const getNeededMakingAmount = (order: LimitOrder) => { + const makingToken = new Token(order.chainId, order.makerAsset, order.makerAssetDecimals, order.makerAssetSymbol, '') + const makingAmount = toCurrencyAmount(makingToken, order.makingAmount) + const filledMakingAmount = toCurrencyAmount(makingToken, order.filledMakingAmount) + + return makingAmount.subtract(filledMakingAmount) +} + +const SizeInfo = ({ amount, symbol, filled }: { amount: string; symbol: string; filled: string }) => { + const progress = filled.startsWith('<') ? 0.01 : Number(filled.replace(/,/g, '')) || 0 + + return ( +
+
+ {formatAmountWithSymbol(amount, symbol)} +
+
+ + + + + Fill {filled}% + +
+
+ ) +} + +const AmountText = ({ amount, symbol, muted }: { amount?: string; symbol?: string; muted?: boolean }) => ( +
+ {amount ? formatAmountWithSymbol(amount, symbol) : '--'} +
+) + +const StatusPill = ({ status, warning }: { status: LimitOrderStatus; warning?: boolean }) => { + const active = isActiveStatus(status) + const danger = [LimitOrderStatus.CANCELLED, LimitOrderStatus.CANCELLING].includes(status) + const caution = warning || [LimitOrderStatus.EXPIRED, LimitOrderStatus.INSUFFICIENT_FUNDS].includes(status) + + return ( + + {warning ? t`Insufficient funds` : formatStatus(status)} + + ) +} + +const OrderItem = ({ + order, + onCancelOrder, + isOrderCancelling, +}: { + order: LimitOrder + onCancelOrder: (order: LimitOrder) => void + isOrderCancelling: (order: LimitOrder) => boolean +}) => { + const navigate = useNavigate() + const [searchParams] = useSearchParams() + const isCancelling = isOrderCancelling(order) + const status = isCancelling ? LimitOrderStatus.CANCELLING : order.status + const isOrderActive = isActiveStatus(order.status) + + const native = NativeCurrencies[order.chainId] + const isNative = order.nativeOutput && order.takerAssetSymbol.toLowerCase() === native?.wrapped.symbol?.toLowerCase() + const takerSymbol = isNative ? native?.symbol || order.takerAssetSymbol : order.takerAssetSymbol + const filledPercent = calcPercentFilledOrder(order.filledTakingAmount, order.takingAmount, order.takerAssetDecimals) + const availableAmount = useMemo(() => getNeededMakingAmount(order), [order]) + const displayRate = formatOrderDisplayRate(order) + + const makingToken = useMemo(() => { + return new Token(order.chainId, order.makerAsset, order.makerAssetDecimals, order.makerAssetSymbol, '') + }, [order.chainId, order.makerAsset, order.makerAssetDecimals, order.makerAssetSymbol]) + const makingTokenBalance = useTokenBalance(makingToken) + const insufficientFund = isOrderActive && makingTokenBalance ? makingTokenBalance.lessThan(availableAmount) : false + + const highlight = + searchParams.get('highlight') === 'true' && + order.makerAsset.toLowerCase() === searchParams.get('search')?.toLowerCase() && + isOrderActive + + const onClickOrder = () => { + navigate({ + search: new URLSearchParams({ + inputCurrency: order.makerAsset, + outputCurrency: order.takerAsset, + }).toString(), + }) + } + + return ( +
+ + Network + + + +
+ {displayRate} +
+ + + + + + {isOrderActive && ( + + )} + +
+ ) +} + +export default OrderItem diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/SummaryNotify.tsx similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx rename to apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/SummaryNotify.tsx diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/index.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/index.tsx new file mode 100644 index 0000000000..6eb44dfef8 --- /dev/null +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/index.tsx @@ -0,0 +1,412 @@ +import { ChainId } from '@kyberswap/ks-sdk-core' +import { Trans, t } from '@lingui/macro' +import { HTMLAttributes, useCallback, useEffect, useState } from 'react' +import { useNavigate, useSearchParams } from 'react-router-dom' +import { useGetListOrdersQuery } from 'services/limitOrder' + +import { ReactComponent as NoDataIcon } from 'assets/svg/no_data.svg' +import InfoHelper from 'components/InfoHelper' +import Pagination from 'components/Pagination' +import SearchInput from 'components/SearchInput' +import Select from 'components/Select' +import CancelOrderModal from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' +import OrderItem from 'components/swapv2/LimitOrder/MyOrders/OrderItem' +import { useRequestCancelOrder } from 'components/swapv2/LimitOrder/MyOrders/useRequestCancelOrder' +import { + formatAmountOrder, + formatRateLimitOrder, + getPayloadTracking, + isActiveStatus, +} from 'components/swapv2/LimitOrder/helpers' +import { useCancellingOrders } from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' +import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +import { RTK_QUERY_TAGS, TRANSACTION_STATE_DEFAULT } from 'constants/index' +import { useActiveWeb3React } from 'hooks' +import { useInvalidateTagLimitOrder } from 'hooks/useInvalidateTags' +import usePageLocation from 'hooks/usePageLocation' +import useParsedQueryString from 'hooks/useParsedQueryString' +import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' +import RefetchIndicator from 'pages/Earns/components/RefetchIndicator' +import { cn } from 'utils/cn' +import { + subscribeNotificationOrderCancelled, + subscribeNotificationOrderExpired, + subscribeNotificationOrderFilled, +} from 'utils/firebase' + +const PAGE_SIZE = 10 + +const LIST_ORDER_TABS = [LimitOrderStatus.ACTIVE, LimitOrderStatus.CLOSED] as const + +const NoResultWrapper = ({ className, ...rest }: HTMLAttributes) => ( +
+) + +const ACTIVE_ORDER_OPTIONS = () => [ + { + label: t`All Active Orders`, + value: LimitOrderStatus.ACTIVE, + }, + { + label: t`Open Orders`, + value: LimitOrderStatus.OPEN, + }, + { + label: t`Partially Filled Orders`, + value: LimitOrderStatus.PARTIALLY_FILLED, + }, +] + +const CLOSE_ORDER_OPTIONS = () => [ + { + label: t`All Closed Orders`, + value: LimitOrderStatus.CLOSED, + }, + { + label: t`Filled Orders`, + value: LimitOrderStatus.FILLED, + }, + { + label: t`Cancelled Orders`, + value: LimitOrderStatus.CANCELLED, + }, + { + label: t`Expired Orders`, + value: LimitOrderStatus.EXPIRED, + }, +] + +const TabSelector = ({ + activeTab, + setActiveTab, +}: { + activeTab: LimitOrderStatus + setActiveTab: (n: LimitOrderStatus) => void +}) => ( +
+ {LIST_ORDER_TABS.map((tab, index) => { + const active = tab === activeTab + const isLast = index === LIST_ORDER_TABS.length - 1 + return ( + + ) + })} +
+) + +const TableHeader = () => ( +
+ + Chain + + + Size + + + Available + Available amount to be filled.} /> + + + Rate + + + Total + + + Status + + +
+) + +const MyOrders = ({ customChainId }: { customChainId?: ChainId }) => { + const { account, chainId: walletChainId, networkInfo } = useActiveWeb3React() + const chainId = customChainId || walletChainId + const { tab, ...qs } = useParsedQueryString<{ tab: LimitOrderStatus }>() + const [searchParams, setSearchParams] = useSearchParams() + const { isEmbeddedSwap } = usePageLocation() + const navigate = useNavigate() + const invalidateTag = useInvalidateTagLimitOrder() + const { isOrderCancelling } = useCancellingOrders() + const { trackingHandler } = useTracking() + + const [curPage, setCurPage] = useState(1) + const [orderType, setOrderType] = useState(LimitOrderStatus.ACTIVE) + const [currentOrder, setCurrentOrder] = useState() + const [isOpenCancel, setIsOpenCancel] = useState(false) + + const keyword = searchParams.get('search') || '' + const isTabActive = isActiveStatus(orderType) + const activeTab = isTabActive ? LimitOrderStatus.ACTIVE : LimitOrderStatus.CLOSED + const orderTypeOptions = isTabActive ? ACTIVE_ORDER_OPTIONS() : CLOSE_ORDER_OPTIONS() + + const { + data: { orders = [], totalOrder = 0 } = {}, + isFetching, + isSuccess: isOrdersLoaded, + } = useGetListOrdersQuery( + { + chainId, + maker: account, + status: orderType, + query: keyword, + page: curPage, + pageSize: PAGE_SIZE, + }, + { skip: !account, pollingInterval: 10_000, refetchOnFocus: true }, + ) + + const { flowState, setFlowState, onCancelOrder } = useRequestCancelOrder({ + orders, + isCancelAll: false, + totalOrder, + }) + + const hasOrders = orders.length > 0 + const showPagination = hasOrders && totalOrder > PAGE_SIZE + const showNoOrders = !hasOrders && (isOrdersLoaded || !account) + + const onReset = useCallback(() => { + setCurPage(1) + }, []) + + const refetchOrders = useCallback(() => { + invalidateTag(RTK_QUERY_TAGS.GET_LIST_ORDERS) + }, [invalidateTag]) + + const refreshListOrder = useCallback(() => { + try { + onReset() + refetchOrders() + } catch (error) {} + }, [onReset, refetchOrders]) + + const setKeyword = useCallback( + (val: string) => { + const nextSearchParams = new URLSearchParams(searchParams) + + if (val) { + nextSearchParams.set('search', val) + } else { + nextSearchParams.delete('search') + } + + setSearchParams(nextSearchParams, { replace: true }) + }, + [searchParams, setSearchParams], + ) + + const onPageChange = (page: number) => { + setCurPage(page) + } + + const onSelectTab = (type: LimitOrderStatus) => { + setOrderType(type) + onReset() + + if (!isEmbeddedSwap) { + navigate({ search: new URLSearchParams(qs).toString() }, { replace: true }) + } + } + + const onSelectOrderType = (type: LimitOrderStatus) => { + setOrderType(type) + onReset() + } + + const onChangeKeyword = (val: string) => { + setKeyword(val) + setCurPage(1) + } + + const trackCancelledOrder = useCallback( + (order: LimitOrder) => { + trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_CANCELLED, { + order_id: order.id, + side: 'sell', + from_token: order.makerAssetSymbol, + to_token: order.takerAssetSymbol, + pair: `${order.makerAssetSymbol}/${order.takerAssetSymbol}`, + limit_price: formatRateLimitOrder(order, false), + amount_in: formatAmountOrder(order.makingAmount, order.makerAssetDecimals), + time_active_minutes: Math.round((Date.now() / 1000 - order.createdAt) / 60), + chain: networkInfo.name, + }) + }, + [networkInfo.name, trackingHandler], + ) + + const trackFilledOrder = useCallback( + (order: LimitOrder) => { + const lastTx = order.transactions?.[order.transactions.length - 1] + + trackingHandler(TRACKING_EVENT_TYPE.LO_ORDER_FILLED, { + order_id: order.id, + side: 'sell', + from_token: order.makerAssetSymbol, + to_token: order.takerAssetSymbol, + pair: `${order.makerAssetSymbol}/${order.takerAssetSymbol}`, + limit_price: formatRateLimitOrder(order, false), + fill_price: formatRateLimitOrder(order, false), + amount_in: formatAmountOrder(order.makingAmount, order.makerAssetDecimals), + amount_out_actual: formatAmountOrder(order.filledTakingAmount, order.takerAssetDecimals), + tx_hash: lastTx?.txHash, + chain: networkInfo.name, + }) + }, + [networkInfo.name, trackingHandler], + ) + + const hideConfirmCancel = useCallback(() => { + setFlowState(TRANSACTION_STATE_DEFAULT) + setIsOpenCancel(false) + setTimeout(() => { + setCurrentOrder(undefined) + }, 300) + }, [setFlowState]) + + const showConfirmCancel = useCallback( + (order: LimitOrder) => { + setCurrentOrder(order) + setFlowState({ ...TRANSACTION_STATE_DEFAULT, showConfirm: true }) + setIsOpenCancel(true) + trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_CANCEL_ORDER, getPayloadTracking(order, networkInfo.name)) + }, + [trackingHandler, setFlowState, networkInfo], + ) + + useEffect(() => { + if (!account) return + + const callback = (data: any) => { + const orders: LimitOrder[] = data?.orders ?? [] + if (orders.length) refreshListOrder() + } + + const unsubscribeCancelled = subscribeNotificationOrderCancelled(account, chainId, data => { + refreshListOrder() + const cancelledOrders: LimitOrder[] = data?.orders ?? [] + cancelledOrders.forEach(trackCancelledOrder) + }) + const unsubscribeExpired = subscribeNotificationOrderExpired(account, chainId, callback) + const unsubscribeFilled = subscribeNotificationOrderFilled(account, chainId, data => { + const filledOrders: LimitOrder[] = data?.orders ?? [] + if (filledOrders.length) refreshListOrder() + filledOrders.forEach(trackFilledOrder) + }) + + return () => { + unsubscribeCancelled?.() + unsubscribeExpired?.() + unsubscribeFilled?.() + } + }, [account, chainId, refreshListOrder, trackCancelledOrder, trackFilledOrder]) + + useEffect(() => { + onReset() + }, [chainId, onReset, orderType]) + + return ( +
+ + +
+ ` + +### 33. View created order +- Example: create order on Ethereum pair `USDT -> ETH`. +- Action: click `View Order` after success. +- Expected result: opens Limit route for the current network/pair. +- Expected URL param: `tab=my_order`. diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts index b4cb952a2a..3b6f57e3ec 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts @@ -1,6 +1,7 @@ import { Currency, Fraction } from '@kyberswap/ks-sdk-core' import { t } from '@lingui/macro' import JSBI from 'jsbi' +import { CreateOrderBody } from 'services/limitOrder' import { CreateOrderParam, LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' import { RESERVE_USD_DECIMALS } from 'constants/index' @@ -134,19 +135,40 @@ export const calcPercentFilledOrder = (value: string, total: string, decimals: n } } -export const getErrorMessage = (error: any) => { +type LimitOrderError = { + code?: string | number + response?: { + data?: { + code?: string | number + } + } +} + +const isLimitOrderError = (error: unknown): error is LimitOrderError => typeof error === 'object' && error !== null + +type CreateOrderSignatureBodyPayload = Omit + +type LimitOrderTrackingPayload = { + from_token: string + to_token: string + from_network: string + trade_qty: string + order_id: number +} & Record + +export const getErrorMessage = (error: unknown) => { console.error('Limit order error: ', error) - const errorCode: string = error?.response?.data?.code || error.code || '' - const mapErrorMessageByErrCode: { [code: string]: string } = { + const errorCode = isLimitOrderError(error) ? error.response?.data?.code || error.code || '' : '' + const mapErrorMessageByErrCode: Record = { 4001: t`User denied message signature`, 4002: t`You don't have sufficient fund for this transaction.`, 4004: t`Invalid signature`, } - const msg = mapErrorMessageByErrCode[errorCode] - return msg?.toString?.() || friendlyError(error) + const msg = mapErrorMessageByErrCode[String(errorCode)] + return msg?.toString?.() || friendlyError(error instanceof Error || typeof error === 'string' ? error : '') } -export const getPayloadCreateOrder = (params: CreateOrderParam) => { +export const getPayloadCreateOrder = (params: CreateOrderParam): CreateOrderSignatureBodyPayload => { const { currencyIn, currencyOut, chainId, account, inputAmount, outputAmount, expiredAt, referral } = params const parseInputAmount = tryParseAmount(inputAmount, currencyIn ?? undefined) return { @@ -162,7 +184,11 @@ export const getPayloadCreateOrder = (params: CreateOrderParam) => { } } -export const getPayloadTracking = (order: LimitOrder, networkName: string, payload = {}) => { +export const getPayloadTracking = ( + order: LimitOrder, + networkName: string, + payload: Record = {}, +): LimitOrderTrackingPayload => { const { makerAssetSymbol, takerAssetSymbol, makingAmount, makerAssetDecimals, id } = order return { ...payload, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx index 98fe0e5113..f600f6dee8 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx @@ -1,4 +1,4 @@ -import { Currency, CurrencyAmount, Token, TokenAmount, WETH } from '@kyberswap/ks-sdk-core' +import { Currency, CurrencyAmount, TokenAmount, WETH } from '@kyberswap/ks-sdk-core' import { t } from '@lingui/macro' import { readContract } from '@wagmi/core' import JSBI from 'jsbi' @@ -14,7 +14,6 @@ import { useWrapEthStatus } from 'components/swapv2/LimitOrder/hooks/useWrapEthS import { LimitOrderCreateContext } from 'components/swapv2/LimitOrder/types' import { ERC20_ABI } from 'constants/abis' import { NativeCurrencies } from 'constants/tokens' -import { useTokenAllowance } from 'data/Allowances' import { useActiveWeb3React } from 'hooks' import { useApproveCallback } from 'hooks/useApproveCallback' import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' @@ -72,37 +71,48 @@ export const useLimitOrderExecution = ({ const { currentData } = useGetLOConfigQuery(chainId) const limitOrderContract = currentData?.contract + const approvalCurrency = useMemo(() => { + if (!currencyIn) return undefined + return currencyIn.isNative ? WETH[chainId] : currencyIn.wrapped + }, [chainId, currencyIn]) + const parsedApprovalAmount = useMemo(() => { + if (!approvalCurrency || !parsedInputAmount) return undefined + return TokenAmount.fromRawAmount(approvalCurrency, parsedInputAmount.quotient) + }, [approvalCurrency, parsedInputAmount]) const parsedActiveOrderMakingAmount = useMemo(() => { try { - if (currencyIn && activeOrderMakingAmount) { - if (currencyIn.isNative) { - return TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(0)) - } - return TokenAmount.fromRawAmount(currencyIn, JSBI.BigInt(activeOrderMakingAmount)) + if (approvalCurrency && activeOrderMakingAmount) { + return TokenAmount.fromRawAmount(approvalCurrency, JSBI.BigInt(activeOrderMakingAmount)) } } catch (error) {} return undefined - }, [currencyIn, activeOrderMakingAmount]) + }, [approvalCurrency, activeOrderMakingAmount]) // Balance and wrap requirements. const balance = useCurrencyBalance(currencyIn, chainId) + const approvalBalance = useCurrencyBalance(approvalCurrency, chainId) const nativeCurrency = NativeCurrencies[chainId] const nativeBalance = useCurrencyBalance(nativeCurrency, chainId) - const isWrappedNativeInput = !!currencyIn?.equals(WETH[chainId]) + const isWrappedNativeApproval = !!approvalCurrency?.equals(WETH[chainId]) const wrapAmountForOrder = useMemo(() => { - if (!currencyIn || !isWrappedNativeInput || !parsedInputAmount || !balance?.currency.equals(currencyIn)) { + if ( + !approvalCurrency || + !isWrappedNativeApproval || + !parsedApprovalAmount || + !approvalBalance?.currency.equals(approvalCurrency) + ) { return undefined } - if (!balance.lessThan(parsedInputAmount)) return undefined - const deficit = JSBI.subtract(parsedInputAmount.quotient, balance.quotient) + if (!approvalBalance.lessThan(parsedApprovalAmount)) return undefined + const deficit = JSBI.subtract(parsedApprovalAmount.quotient, approvalBalance.quotient) return CurrencyAmount.fromRawAmount(nativeCurrency, deficit) - }, [balance, currencyIn, isWrappedNativeInput, nativeCurrency, parsedInputAmount]) + }, [approvalBalance, approvalCurrency, isWrappedNativeApproval, nativeCurrency, parsedApprovalAmount]) - const needsWrap = !!currencyIn?.isNative || !!wrapAmountForOrder - const wrapInputCurrency = currencyIn?.isNative ? currencyIn : wrapAmountForOrder ? nativeCurrency : currencyIn - const wrapTypedValue = wrapAmountForOrder ? wrapAmountForOrder.toExact() : inputAmount + const needsWrap = !!wrapAmountForOrder + const wrapInputCurrency = wrapAmountForOrder ? nativeCurrency : undefined + const wrapTypedValue = wrapAmountForOrder?.toExact() const { isWrappingEth, setTxHashWrapped } = useWrapEthStatus(switchToWeth) const { execute: onWrap } = useWrapCallback(wrapInputCurrency, WETH[chainId], wrapTypedValue, true, chainId) @@ -112,11 +122,19 @@ export const useLimitOrderExecution = ({ }, [balance]) const insufficientBalance = useMemo(() => { - if (!parsedInputAmount || !currencyIn || !balance?.currency.equals(currencyIn)) return false - if (!balance.lessThan(parsedInputAmount)) return false - if (!isWrappedNativeInput || !wrapAmountForOrder || !nativeBalance?.currency.equals(nativeCurrency)) return true + if (!approvalCurrency || !parsedApprovalAmount || !approvalBalance?.currency.equals(approvalCurrency)) return false + if (!approvalBalance.lessThan(parsedApprovalAmount)) return false + if (!isWrappedNativeApproval || !wrapAmountForOrder || !nativeBalance?.currency.equals(nativeCurrency)) return true return nativeBalance.lessThan(wrapAmountForOrder) - }, [balance, currencyIn, isWrappedNativeInput, nativeBalance, nativeCurrency, parsedInputAmount, wrapAmountForOrder]) + }, [ + approvalBalance, + approvalCurrency, + isWrappedNativeApproval, + nativeBalance, + nativeCurrency, + parsedApprovalAmount, + wrapAmountForOrder, + ]) const insufficientBalanceText = insufficientBalance ? t`Insufficient Balance` : undefined @@ -136,74 +154,46 @@ export const useLimitOrderExecution = ({ } catch (error) {} }, [maxAmountInput, onSetInput]) - // Allowance and process-modal steps. - const currentAllowance = useTokenAllowance( - currencyIn as Token, - account ?? undefined, - limitOrderContract, - ) as CurrencyAmount - - const missingAllowance = useMemo(() => { - if (currentAllowance?.equalTo(0)) return true - if (currencyIn?.isNative || !parsedInputAmount) return false - const allowanceSubtracted = parsedActiveOrderMakingAmount - ? currentAllowance?.subtract(parsedActiveOrderMakingAmount) - : undefined - - if ( - !allowanceSubtracted || - allowanceSubtracted.greaterThan(parsedInputAmount) || - allowanceSubtracted.equalTo(parsedInputAmount) - ) - return false - return parsedInputAmount.subtract(allowanceSubtracted) - }, [currencyIn?.isNative, currentAllowance, parsedInputAmount, parsedActiveOrderMakingAmount]) - - const enoughAllowance = !missingAllowance - - const [approval, approveCallback] = useApproveCallback( - parsedInputAmount, - limitOrderContract || undefined, - !enoughAllowance, - ) + // Allowance is checked inside the processing approve step so the modal can show the step even when it passes. + const [approval, approveCallback] = useApproveCallback(parsedApprovalAmount, limitOrderContract || undefined, true) const hasEnoughAllowance = useCallback( - (allowance: CurrencyAmount) => { - if (currencyIn?.isNative || !parsedInputAmount) return true + (allowance: TokenAmount) => { + if (!parsedApprovalAmount) return true try { const availableAllowance = parsedActiveOrderMakingAmount ? allowance.subtract(parsedActiveOrderMakingAmount) : allowance - return availableAllowance.greaterThan(parsedInputAmount) || availableAllowance.equalTo(parsedInputAmount) + return availableAllowance.greaterThan(parsedApprovalAmount) || availableAllowance.equalTo(parsedApprovalAmount) } catch (error) { return false } }, - [currencyIn?.isNative, parsedInputAmount, parsedActiveOrderMakingAmount], + [parsedApprovalAmount, parsedActiveOrderMakingAmount], ) const checkApprovalManually = useCallback(async () => { - if (currencyIn?.isNative) return true - if (!currencyIn || !account || !limitOrderContract || !parsedInputAmount) return false + if (!approvalCurrency || !account || !limitOrderContract || !parsedApprovalAmount) return false const allowance = (await readContract(wagmiConfig, { - address: currencyIn.wrapped.address as Address, + address: approvalCurrency.address as Address, abi: ERC20_ABI, functionName: 'allowance', args: [account, limitOrderContract], chainId: chainId as number, })) as bigint - return hasEnoughAllowance(TokenAmount.fromRawAmount(currencyIn.wrapped, allowance.toString())) - }, [account, chainId, currencyIn, hasEnoughAllowance, limitOrderContract, parsedInputAmount]) + return hasEnoughAllowance(TokenAmount.fromRawAmount(approvalCurrency, allowance.toString())) + }, [account, chainId, approvalCurrency, hasEnoughAllowance, limitOrderContract, parsedApprovalAmount]) const processingSteps = useMemo(() => { const steps: ProcessingOrderStep[] = [] + if (needsWrap) steps.push('wrap') - if (needsWrap || (!currencyIn?.isNative && !enoughAllowance)) steps.push('approve') + steps.push('approve') steps.push('create') return steps - }, [currencyIn?.isNative, enoughAllowance, needsWrap]) + }, [needsWrap]) // Form validation and warning messages. const { inputError, outputError } = useValidateInputError({ diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useTakeLimitOrder.ts b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useTakeLimitOrder.ts index 63adc99e97..90f88b0876 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useTakeLimitOrder.ts +++ b/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useTakeLimitOrder.ts @@ -1,4 +1,4 @@ -import { Currency, CurrencyAmount, TokenAmount } from '@kyberswap/ks-sdk-core' +import { Currency, CurrencyAmount, TokenAmount, WETH } from '@kyberswap/ks-sdk-core' import { t } from '@lingui/macro' import { readContract } from '@wagmi/core' import JSBI from 'jsbi' @@ -13,10 +13,15 @@ import { import { NotificationType } from 'components/Announcement/type' import { wagmiConfig } from 'components/Web3Provider' import { getErrorMessage } from 'components/swapv2/LimitOrder/helpers' +import { useWrapEthStatus } from 'components/swapv2/LimitOrder/hooks/useWrapEthStatus' import { LimitOrderTakeContext } from 'components/swapv2/LimitOrder/types' import { ERC20_ABI } from 'constants/abis' +import { RTK_QUERY_TAGS } from 'constants/index' +import { NativeCurrencies } from 'constants/tokens' import { useActiveWeb3React, useWeb3React } from 'hooks' import { ApprovalState, useApproveCallback } from 'hooks/useApproveCallback' +import { useInvalidateTagLimitOrder } from 'hooks/useInvalidateTags' +import useWrapCallback from 'hooks/useWrapCallback' import { useNotify } from 'state/application/hooks' import { tryParseAmount } from 'state/swap/hooks' import { useTransactionAdder } from 'state/transactions/hooks' @@ -27,7 +32,7 @@ import { ErrorName } from 'utils/transactionError' import useEstimateGasTxs from 'utils/useEstimateGasTxs' import { Address } from 'utils/viem' -export type TakeOrderStep = 'approve' | 'fill' +export type TakeOrderStep = 'wrap' | 'approve' | 'fill' export type TakeOrderStepStatus = 'idle' | 'active' | 'success' | 'error' export type TakeOrderProcessingState = { @@ -102,11 +107,13 @@ export const useTakeLimitOrder = ({ const notify = useNotify() const addTransactionWithType = useTransactionAdder() const estimateGas = useEstimateGasTxs() + const invalidateLimitOrderTags = useInvalidateTagLimitOrder() const [fillAmount, setFillAmount] = useState('') const [processing, setProcessing] = useState(DEFAULT_PROCESSING) const processingRunIdRef = useRef(0) const processingStepStartedRef = useRef() + const wrapTransactionPendingRef = useRef(false) const order = context?.order const payCurrency = context?.payCurrency @@ -125,20 +132,41 @@ export const useTakeLimitOrder = ({ ) const feeBps = useMemo(() => getFeeBps(order?.makerTokenFeePercent), [order?.makerTokenFeePercent]) const receiveAmountAfterFee = useMemo(() => subtractFee(receiveAmount, feeBps), [feeBps, receiveAmount]) - const thresholdAmount = receiveAmountAfterFee?.quotient.toString() || '0' + const thresholdAmount = receiveAmount?.quotient.toString() || '0' const balance = useCurrencyBalance(payCurrency, chainId) + const nativeCurrency = NativeCurrencies[chainId] + const nativeBalance = useCurrencyBalance(nativeCurrency, chainId) + const isWrappedNativePay = !!payCurrency?.equals(WETH[chainId]) + const wrapAmountForOrder = useMemo(() => { + if (!payCurrency || !isWrappedNativePay || !parsedPayAmount || !balance?.currency.equals(payCurrency)) { + return undefined + } + if (!balance.lessThan(parsedPayAmount)) return undefined + return CurrencyAmount.fromRawAmount(nativeCurrency, JSBI.subtract(parsedPayAmount.quotient, balance.quotient)) + }, [balance, isWrappedNativePay, nativeCurrency, parsedPayAmount, payCurrency]) const insufficientBalance = useMemo(() => { if (!parsedPayAmount) return false if (!balance?.currency.equals(parsedPayAmount.currency)) return true - return balance.lessThan(parsedPayAmount) - }, [balance, parsedPayAmount]) + if (!balance.lessThan(parsedPayAmount)) return false + if (!isWrappedNativePay || !wrapAmountForOrder || !nativeBalance?.currency.equals(nativeCurrency)) return true + return nativeBalance.lessThan(wrapAmountForOrder) + }, [balance, isWrappedNativePay, nativeBalance, nativeCurrency, parsedPayAmount, wrapAmountForOrder]) const exceedsAvailableAmount = useMemo(() => { if (!parsedPayAmount || !maxPayAmount) return false return parsedPayAmount.greaterThan(maxPayAmount) }, [maxPayAmount, parsedPayAmount]) + const onWrapped = useCallback(() => undefined, []) + const { isWrappingEth, setTxHashWrapped } = useWrapEthStatus(onWrapped) + const { execute: onWrap } = useWrapCallback( + wrapAmountForOrder ? nativeCurrency : undefined, + WETH[chainId], + wrapAmountForOrder?.toExact(), + true, + chainId, + ) + const [approval, approveCallback] = useApproveCallback(parsedPayAmount, contractAddress || undefined, true) - const needsApprove = approval !== ApprovalState.APPROVED const checkApprovalManually = useCallback(async () => { if (!payCurrency || payCurrency.isNative || !account || !contractAddress || !parsedPayAmount) return true @@ -158,12 +186,14 @@ export const useTakeLimitOrder = ({ const invalidateProcessingRun = useCallback(() => { processingRunIdRef.current += 1 processingStepStartedRef.current = undefined + wrapTransactionPendingRef.current = false }, []) const isCurrentProcessingRun = useCallback((runId: number) => processingRunIdRef.current === runId, []) const markStepSuccess = useCallback((step: TakeOrderStep, txHash?: string) => { processingStepStartedRef.current = undefined + if (step === 'wrap') wrapTransactionPendingRef.current = false setProcessing(state => { if (!state.show || state.currentStep !== step) return state const completedSteps = state.completedSteps.includes(step) @@ -176,6 +206,7 @@ export const useTakeLimitOrder = ({ const markStepError = useCallback((step: TakeOrderStep) => { processingStepStartedRef.current = undefined + if (step === 'wrap') wrapTransactionPendingRef.current = false setProcessing(state => { if (!state.show || state.currentStep !== step) return state return { ...state, errorStep: step } @@ -218,6 +249,28 @@ export const useTakeLimitOrder = ({ return processingRunIdRef.current }, []) + const runWrapStep = useCallback(() => { + if (isWrappingEth) return + const runId = startStepRun('wrap') + if (runId === undefined) return + + void (async () => { + try { + const hash = await onWrap?.() + if (!isCurrentProcessingRun(runId)) return + if (!hash) { + markStepError('wrap') + return + } + setTxHashWrapped(hash) + } catch (error) { + if (!isCurrentProcessingRun(runId)) return + notify({ type: NotificationType.ERROR, title: t`Wrap Error`, summary: getErrorMessage(error) }) + markStepError('wrap') + } + })() + }, [isCurrentProcessingRun, isWrappingEth, markStepError, notify, onWrap, setTxHashWrapped, startStepRun]) + const runApproveStep = useCallback(() => { const runId = startStepRun('approve') if (runId === undefined) return @@ -307,6 +360,11 @@ export const useTakeLimitOrder = ({ }, }, }) + invalidateLimitOrderTags([ + RTK_QUERY_TAGS.GET_LIMIT_ORDER_LIST, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_INSUFFICIENT, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_ACTIVE_MAKING_AMOUNT, + ]) markStepSuccess('fill', response.hash) } catch (error) { if (!isCurrentProcessingRun(runId)) return @@ -321,6 +379,7 @@ export const useTakeLimitOrder = ({ contractAddress, encodeFillOrder, getOperatorSignature, + invalidateLimitOrderTags, isCurrentProcessingRun, isSmartConnector, markStepError, @@ -339,18 +398,32 @@ export const useTakeLimitOrder = ({ const runStep = useCallback( (step: TakeOrderStep) => { + if (step === 'wrap') { + runWrapStep() + return + } + if (step === 'approve') { runApproveStep() return } runFillStep() }, - [runApproveStep, runFillStep], + [runApproveStep, runFillStep, runWrapStep], ) + const buildProcessingSteps = useCallback((): TakeOrderStep[] => { + const steps: TakeOrderStep[] = [] + if (wrapAmountForOrder) steps.push('wrap') + steps.push('approve') + steps.push('fill') + return steps + }, [wrapAmountForOrder]) + const start = useCallback(() => { if (!contractAddress || !parsedPayAmount || insufficientBalance || exceedsAvailableAmount) return - const steps: TakeOrderStep[] = needsApprove ? ['approve', 'fill'] : ['fill'] + + const steps = buildProcessingSteps() invalidateProcessingRun() setProcessing({ show: true, @@ -359,11 +432,11 @@ export const useTakeLimitOrder = ({ completedSteps: [], }) }, [ + buildProcessingSteps, contractAddress, exceedsAvailableAmount, insufficientBalance, invalidateProcessingRun, - needsApprove, parsedPayAmount, ]) @@ -372,6 +445,17 @@ export const useTakeLimitOrder = ({ setFillAmount(getAvailablePayAmount(context).toExact()) }, [context, isOpen]) + useEffect(() => { + if (isWrappingEth) { + wrapTransactionPendingRef.current = true + return + } + + if (wrapTransactionPendingRef.current && processingStepStartedRef.current === 'wrap') { + markStepSuccess('wrap') + } + }, [isWrappingEth, markStepSuccess]) + useEffect(() => { if (!processing.show || !processing.currentStep || processing.errorStep) return runStep(processing.currentStep) diff --git a/apps/kyberswap-interface/src/constants/index.ts b/apps/kyberswap-interface/src/constants/index.ts index 4ef8ee12bd..09e4ca4d03 100644 --- a/apps/kyberswap-interface/src/constants/index.ts +++ b/apps/kyberswap-interface/src/constants/index.ts @@ -212,8 +212,10 @@ export const RTK_QUERY_TAGS = { GET_BRIDGE_HISTORY: 'GET_BRIDGE_HISTORY', // limit order - GET_LIST_ORDERS: 'GET_LIST_ORDERS', - GET_ORDERS_BY_TOKEN_PAIR: 'GET_ORDERS_BY_TOKEN_PAIR', + GET_LIMIT_ORDER_LIST: 'GET_LIMIT_ORDER_LIST', + GET_LIMIT_ORDER_BOOK: 'GET_LIMIT_ORDER_BOOK', + GET_LIMIT_ORDER_INSUFFICIENT: 'GET_LIMIT_ORDER_INSUFFICIENT', + GET_LIMIT_ORDER_ACTIVE_MAKING_AMOUNT: 'GET_LIMIT_ORDER_ACTIVE_MAKING_AMOUNT', // smart exit GET_SMART_EXIT_ORDERS: 'GET_SMART_EXIT_ORDERS', diff --git a/apps/kyberswap-interface/src/services/limitOrder.ts b/apps/kyberswap-interface/src/services/limitOrder.ts index 79a0c9334c..242d5c029f 100644 --- a/apps/kyberswap-interface/src/services/limitOrder.ts +++ b/apps/kyberswap-interface/src/services/limitOrder.ts @@ -119,7 +119,12 @@ const transformResponse = (data: ApiEnvelope) => data.data const limitOrderApi = createApi({ reducerPath: 'limitOrderApi', baseQuery: fetchBaseQuery({ baseUrl: '' }), - tagTypes: [RTK_QUERY_TAGS.GET_LIST_ORDERS, RTK_QUERY_TAGS.GET_ORDERS_BY_TOKEN_PAIR], + tagTypes: [ + RTK_QUERY_TAGS.GET_LIMIT_ORDER_LIST, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_BOOK, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_INSUFFICIENT, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_ACTIVE_MAKING_AMOUNT, + ], endpoints: builder => ({ getLOConfig: builder.query({ query: chainId => ({ @@ -158,7 +163,7 @@ const limitOrderApi = createApi({ }) return { orders: data?.orders || [], totalOrder: data?.pagination?.totalItems || 0 } }, - providesTags: [RTK_QUERY_TAGS.GET_LIST_ORDERS], + providesTags: [RTK_QUERY_TAGS.GET_LIMIT_ORDER_LIST], }), getOrdersByTokenPair: builder.query< { orders: LimitOrderFromTokenPair[] }, @@ -178,7 +183,7 @@ const limitOrderApi = createApi({ }) return { orders: data?.orders || [] } }, - providesTags: [RTK_QUERY_TAGS.GET_ORDERS_BY_TOKEN_PAIR], + providesTags: [RTK_QUERY_TAGS.GET_LIMIT_ORDER_BOOK], }), getNumberOfInsufficientFundOrders: builder.query({ query: params => ({ @@ -186,6 +191,7 @@ const limitOrderApi = createApi({ params, }), transformResponse: ({ data }: ApiEnvelope) => data.total || 0, + providesTags: [RTK_QUERY_TAGS.GET_LIMIT_ORDER_INSUFFICIENT], }), insertCancellingOrder: builder.mutation({ query: body => ({ @@ -193,6 +199,11 @@ const limitOrderApi = createApi({ body, method: 'POST', }), + invalidatesTags: [ + RTK_QUERY_TAGS.GET_LIMIT_ORDER_LIST, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_INSUFFICIENT, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_ACTIVE_MAKING_AMOUNT, + ], }), createOrder: builder.mutation<{ id: number }, CreateOrderBody>({ query: body => ({ @@ -204,7 +215,11 @@ const limitOrderApi = createApi({ }, }), transformResponse, - invalidatesTags: [RTK_QUERY_TAGS.GET_LIST_ORDERS], + invalidatesTags: [ + RTK_QUERY_TAGS.GET_LIMIT_ORDER_LIST, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_INSUFFICIENT, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_ACTIVE_MAKING_AMOUNT, + ], }), createOrderSignature: builder.mutation({ query: body => ({ @@ -244,6 +259,7 @@ const limitOrderApi = createApi({ }, }), transformResponse: ({ data }: ApiEnvelope) => data.activeMakingAmount || '', + providesTags: [RTK_QUERY_TAGS.GET_LIMIT_ORDER_ACTIVE_MAKING_AMOUNT], }), createCancelOrderSignature: builder.mutation< @@ -267,7 +283,11 @@ const limitOrderApi = createApi({ method: 'POST', }), transformResponse, - invalidatesTags: [RTK_QUERY_TAGS.GET_LIST_ORDERS], + invalidatesTags: [ + RTK_QUERY_TAGS.GET_LIMIT_ORDER_LIST, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_INSUFFICIENT, + RTK_QUERY_TAGS.GET_LIMIT_ORDER_ACTIVE_MAKING_AMOUNT, + ], }), getOperatorSignature: builder.query({ query: ({ chainId, orderIds }) => ({ From eeae4424122c8544f1c2ab2813218740d869782e Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Fri, 19 Jun 2026 10:03:39 +0700 Subject: [PATCH 19/52] refactor(limit-order): move module out of swapv2 Relocate LimitOrder under components/LimitOrder and update consumers to use the new import path. --- .../components/Announcement/Popups/index.tsx | 2 +- .../InboxItemLimitOrder.tsx | 2 +- .../NotificationCenter/LimitOrder.tsx | 2 +- .../src/components/Announcement/helpers.ts | 2 +- .../src/components/Announcement/type.ts | 2 +- .../Form/LimitOrderExpirySection.tsx | 0 .../LimitOrder/Form/LimitOrderForm.tsx | 22 +- .../LimitOrder/Form/LimitOrderRateSection.tsx | 4 +- .../Form/LimitOrderTokenSection.tsx | 0 .../LimitOrder/Form/MarketPrice.tsx | 2 +- .../LimitOrder/Modals/CancelButtons.tsx | 6 +- .../LimitOrder/Modals/CancelOrderModal.tsx | 14 +- .../Modals/CancelStatusCountDown.tsx | 4 +- .../LimitOrder/Modals/ConfirmOrderModal.tsx | 6 +- .../Modals/ConfirmTakeOrderModal.tsx | 8 +- .../Modals/ProcessingOrderModal.tsx | 2 +- .../Modals/ProcessingTakeOrderModal.tsx | 2 +- .../LimitOrder/Modals/components.tsx | 6 +- .../LimitOrder/MyOrders/OrderItem.tsx | 4 +- .../LimitOrder/MyOrders/SummaryNotify.tsx | 4 +- .../LimitOrder/MyOrders/index.tsx | 12 +- .../MyOrders/useRequestCancelOrder.tsx | 8 +- .../LimitOrder/OrderBook/OrderItem.tsx | 2 +- .../LimitOrder/OrderBook/TableHeader.tsx | 2 +- .../LimitOrder/OrderBook/index.tsx | 8 +- .../LimitOrder/OrderList/index.tsx | 6 +- .../src/components/LimitOrder/TEST_SCRIPT.md | 221 +++++++++++++ .../{swapv2 => }/LimitOrder/helpers.ts | 2 +- .../LimitOrder/hooks/useCancellingOrders.ts | 4 +- .../LimitOrder/hooks/useCreateLimitOrder.tsx | 8 +- .../hooks/useFetchActiveAllOrders.ts | 2 +- .../hooks/useLimitOrderExecution.tsx | 12 +- .../hooks/useLimitOrderFormState.ts | 4 +- .../hooks/useNotificationLimitOrder.tsx | 4 +- .../LimitOrder/hooks/useProcessingOrder.ts | 0 .../LimitOrder/hooks/useSignOrder.ts | 4 +- .../LimitOrder/hooks/useTakeLimitOrder.ts | 6 +- .../hooks/useValidateInputError.tsx | 0 .../hooks/useWarningCreateOrder.tsx | 2 +- .../LimitOrder/hooks/useWrapEthStatus.ts | 0 .../{swapv2 => }/LimitOrder/types.ts | 0 .../SwapModal/ConfirmSwapModalContent.tsx | 6 +- .../WalletPopup/Transactions/Status.tsx | 2 +- .../Transactions/TransactionItem.tsx | 2 +- .../WalletPopup/Transactions/index.tsx | 2 +- apps/kyberswap-interface/src/locales/en-US.po | 310 +++++++++--------- apps/kyberswap-interface/src/locales/zh-CN.po | 310 +++++++++--------- .../src/pages/PartnerSwap/index.tsx | 4 +- .../src/pages/SwapV3/index.tsx | 4 +- .../src/services/limitOrder.ts | 2 +- .../kyberswap-interface/src/utils/firebase.ts | 2 +- 51 files changed, 633 insertions(+), 412 deletions(-) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Form/LimitOrderExpirySection.tsx (100%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Form/LimitOrderForm.tsx (90%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Form/LimitOrderRateSection.tsx (98%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Form/LimitOrderTokenSection.tsx (100%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Form/MarketPrice.tsx (94%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Modals/CancelButtons.tsx (96%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Modals/CancelOrderModal.tsx (94%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Modals/CancelStatusCountDown.tsx (96%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Modals/ConfirmOrderModal.tsx (97%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Modals/ConfirmTakeOrderModal.tsx (96%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Modals/ProcessingOrderModal.tsx (98%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Modals/ProcessingTakeOrderModal.tsx (98%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/Modals/components.tsx (96%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/MyOrders/OrderItem.tsx (99%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/MyOrders/SummaryNotify.tsx (97%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/MyOrders/index.tsx (96%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/MyOrders/useRequestCancelOrder.tsx (97%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/OrderBook/OrderItem.tsx (98%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/OrderBook/TableHeader.tsx (94%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/OrderBook/index.tsx (97%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/OrderList/index.tsx (95%) create mode 100644 apps/kyberswap-interface/src/components/LimitOrder/TEST_SCRIPT.md rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/helpers.ts (99%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useCancellingOrders.ts (94%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useCreateLimitOrder.tsx (95%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useFetchActiveAllOrders.ts (94%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useLimitOrderExecution.tsx (96%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useLimitOrderFormState.ts (98%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useNotificationLimitOrder.tsx (97%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useProcessingOrder.ts (100%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useSignOrder.ts (94%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useTakeLimitOrder.ts (98%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useValidateInputError.tsx (100%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useWarningCreateOrder.tsx (98%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/hooks/useWrapEthStatus.ts (100%) rename apps/kyberswap-interface/src/components/{swapv2 => }/LimitOrder/types.ts (100%) diff --git a/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx b/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx index 4b30717cf3..422ec995f5 100644 --- a/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx +++ b/apps/kyberswap-interface/src/components/Announcement/Popups/index.tsx @@ -6,7 +6,7 @@ import SnippetPopup from 'components/Announcement/Popups/SnippetPopup' import TopRightPopup from 'components/Announcement/Popups/TopRightPopup' import { PopupType, PrivateAnnouncementType } from 'components/Announcement/type' import { ButtonEmpty } from 'components/Button' -import { useNotificationLimitOrder } from 'components/swapv2/LimitOrder/hooks/useNotificationLimitOrder' +import { useNotificationLimitOrder } from 'components/LimitOrder/hooks/useNotificationLimitOrder' import { TIMES_IN_SECS } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { diff --git a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx index 750e9136b2..4ab20668b0 100644 --- a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx @@ -22,7 +22,7 @@ import { import { AnnouncementTemplateLimitOrder } from 'components/Announcement/type' import { CheckCircle } from 'components/Icons' import { TokenLogoWithShadow } from 'components/Logo' -import { LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +import { LimitOrderStatus } from 'components/LimitOrder/types' import { APP_PATHS } from 'constants/index' import { NETWORKS_INFO } from 'constants/networks' import { useNavigateToUrl } from 'utils/redirect' diff --git a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx index 78df389354..059b47c688 100644 --- a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx @@ -7,7 +7,7 @@ import { PrivateAnnouncementPropCenter } from 'components/Announcement/PrivateAn import { Desc, Time, Title, Wrapper } from 'components/Announcement/PrivateAnnoucement/NotificationCenter/styled' import { AnnouncementTemplateLimitOrder } from 'components/Announcement/type' import Logo from 'components/Logo' -import { LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +import { LimitOrderStatus } from 'components/LimitOrder/types' import { APP_PATHS } from 'constants/index' import { formatTime } from 'utils/time' diff --git a/apps/kyberswap-interface/src/components/Announcement/helpers.ts b/apps/kyberswap-interface/src/components/Announcement/helpers.ts index 6bf9900fea..7b3e3e36fb 100644 --- a/apps/kyberswap-interface/src/components/Announcement/helpers.ts +++ b/apps/kyberswap-interface/src/components/Announcement/helpers.ts @@ -9,7 +9,7 @@ import { SmartExitReason, SmartExitStatus, } from 'components/Announcement/type' -import { LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +import { LimitOrderStatus } from 'components/LimitOrder/types' import { EnvKeys, NOTI_ENV } from 'constants/env' import { Metric, SmartExitCondition } from 'pages/Earns/types' import { formatDisplayNumber } from 'utils/numbers' diff --git a/apps/kyberswap-interface/src/components/Announcement/type.ts b/apps/kyberswap-interface/src/components/Announcement/type.ts index 1ac5e276da..8e6d25462f 100644 --- a/apps/kyberswap-interface/src/components/Announcement/type.ts +++ b/apps/kyberswap-interface/src/components/Announcement/type.ts @@ -1,6 +1,6 @@ import { ReactNode } from 'react' -import { LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +import { LimitOrderStatus } from 'components/LimitOrder/types' import { SmartExitDexType } from 'pages/Earns/components/SmartExit/constants' import { SmartExitCondition } from 'pages/Earns/types' import { HistoricalPriceAlert } from 'pages/NotificationCenter/const' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderExpirySection.tsx similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderExpirySection.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderExpirySection.tsx diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx similarity index 90% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx index c676369386..6188d62841 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderForm.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx @@ -7,19 +7,19 @@ import { ButtonLight, ButtonPrimary, ButtonWarning } from 'components/Button' import DateTimePicker from 'components/DateTimePicker' import { NetworkSelector } from 'components/NetworkSelector' import { HStack, Stack } from 'components/Stack' -import LimitOrderExpirySection from 'components/swapv2/LimitOrder/Form/LimitOrderExpirySection' +import LimitOrderExpirySection from 'components/LimitOrder/Form/LimitOrderExpirySection' import LimitOrderRateSection, { useGetDeltaRateLimitOrder, -} from 'components/swapv2/LimitOrder/Form/LimitOrderRateSection' -import LimitOrderTokenSection from 'components/swapv2/LimitOrder/Form/LimitOrderTokenSection' -import MarketPrice from 'components/swapv2/LimitOrder/Form/MarketPrice' -import ConfirmOrderModal from 'components/swapv2/LimitOrder/Modals/ConfirmOrderModal' -import ProcessingOrderModal from 'components/swapv2/LimitOrder/Modals/ProcessingOrderModal' -import { useCreateLimitOrder } from 'components/swapv2/LimitOrder/hooks/useCreateLimitOrder' -import { useLimitOrderExecution } from 'components/swapv2/LimitOrder/hooks/useLimitOrderExecution' -import { useLimitOrderFormState } from 'components/swapv2/LimitOrder/hooks/useLimitOrderFormState' -import { useProcessingOrder } from 'components/swapv2/LimitOrder/hooks/useProcessingOrder' -import { LimitOrderTab } from 'components/swapv2/LimitOrder/types' +} from 'components/LimitOrder/Form/LimitOrderRateSection' +import LimitOrderTokenSection from 'components/LimitOrder/Form/LimitOrderTokenSection' +import MarketPrice from 'components/LimitOrder/Form/MarketPrice' +import ConfirmOrderModal from 'components/LimitOrder/Modals/ConfirmOrderModal' +import ProcessingOrderModal from 'components/LimitOrder/Modals/ProcessingOrderModal' +import { useCreateLimitOrder } from 'components/LimitOrder/hooks/useCreateLimitOrder' +import { useLimitOrderExecution } from 'components/LimitOrder/hooks/useLimitOrderExecution' +import { useLimitOrderFormState } from 'components/LimitOrder/hooks/useLimitOrderFormState' +import { useProcessingOrder } from 'components/LimitOrder/hooks/useProcessingOrder' +import { LimitOrderTab } from 'components/LimitOrder/types' import { APP_PATHS } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { NETWORKS_INFO } from 'hooks/useChainsConfig' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderRateSection.tsx similarity index 98% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderRateSection.tsx index 3f0a21cb9d..57330ad5b0 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderRateSection.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderRateSection.tsx @@ -5,8 +5,8 @@ import { useEffect, useMemo, useState } from 'react' import InfoHelper from 'components/InfoHelper' import NumericalInput from 'components/NumericalInput' import { Stack } from 'components/Stack' -import { removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' -import { DeltaRateLimitOrder, RateInfo } from 'components/swapv2/LimitOrder/types' +import { removeTrailingZero } from 'components/LimitOrder/helpers' +import { DeltaRateLimitOrder, RateInfo } from 'components/LimitOrder/types' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import useTheme from 'hooks/useTheme' import { cn } from 'utils/cn' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderTokenSection.tsx similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/LimitOrderTokenSection.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderTokenSection.tsx diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/MarketPrice.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Form/MarketPrice.tsx similarity index 94% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/MarketPrice.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Form/MarketPrice.tsx index 86061facc5..9f6b6ee253 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Form/MarketPrice.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Form/MarketPrice.tsx @@ -3,7 +3,7 @@ import { Repeat } from 'react-feather' import Skeleton from 'components/Skeleton' import { HStack } from 'components/Stack' -import { removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' +import { removeTrailingZero } from 'components/LimitOrder/helpers' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' type MarketPriceProps = { diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelButtons.tsx similarity index 96% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelButtons.tsx index 51451363a2..e2e67318eb 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelButtons.tsx @@ -7,9 +7,9 @@ import { ButtonLight, ButtonOutlined, ButtonPrimary } from 'components/Button' import Column from 'components/Column' import { GasStation } from 'components/Icons' import { MouseoverTooltip } from 'components/Tooltip' -import { CancelStatus } from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' -import { DOCS_LINKS, getPayloadTracking } from 'components/swapv2/LimitOrder/helpers' -import { CancelOrderType, LimitOrder } from 'components/swapv2/LimitOrder/types' +import { CancelStatus } from 'components/LimitOrder/Modals/CancelOrderModal' +import { DOCS_LINKS, getPayloadTracking } from 'components/LimitOrder/helpers' +import { CancelOrderType, LimitOrder } from 'components/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import useTheme from 'hooks/useTheme' import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelOrderModal.tsx similarity index 94% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelOrderModal.tsx index 73ab8cc08f..5e096f8620 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelOrderModal.tsx @@ -4,16 +4,16 @@ import { useEffect, useMemo, useState } from 'react' import Logo from 'components/Logo' import Modal from 'components/Modal' -import CancelButtons from 'components/swapv2/LimitOrder/Modals/CancelButtons' -import CancelStatusCountDown from 'components/swapv2/LimitOrder/Modals/CancelStatusCountDown' -import { Container, Header, Label, ListInfo, Note, Rate, Value } from 'components/swapv2/LimitOrder/Modals/components' -import { useEstimateFee, useProcessCancelOrder } from 'components/swapv2/LimitOrder/MyOrders/useRequestCancelOrder' -import { calcPercentFilledOrder, formatAmountOrder } from 'components/swapv2/LimitOrder/helpers' +import CancelButtons from 'components/LimitOrder/Modals/CancelButtons' +import CancelStatusCountDown from 'components/LimitOrder/Modals/CancelStatusCountDown' +import { Container, Header, Label, ListInfo, Note, Rate, Value } from 'components/LimitOrder/Modals/components' +import { useEstimateFee, useProcessCancelOrder } from 'components/LimitOrder/MyOrders/useRequestCancelOrder' +import { calcPercentFilledOrder, formatAmountOrder } from 'components/LimitOrder/helpers' import { useAllActiveOrders, useIsSupportSoftCancelOrder, -} from 'components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders' -import { CancelOrderFunction, CancelOrderType, LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +} from 'components/LimitOrder/hooks/useFetchActiveAllOrders' +import { CancelOrderFunction, CancelOrderType, LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' import { NativeCurrencies } from 'constants/tokens' import { useCurrencyV2 } from 'hooks/Tokens' import { useBaseTradeInfoLimitOrder } from 'hooks/useBaseTradeInfo' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelStatusCountDown.tsx similarity index 96% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelStatusCountDown.tsx index 060ff693ec..d3fbdc3abc 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelStatusCountDown.tsx @@ -7,8 +7,8 @@ import Column from 'components/Column' import { Clock } from 'components/Icons' import WarningIcon from 'components/Icons/WarningIcon' import Loader from 'components/Loader' -import { CancelStatus } from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' -import { DOCS_LINKS } from 'components/swapv2/LimitOrder/helpers' +import { CancelStatus } from 'components/LimitOrder/Modals/CancelOrderModal' +import { DOCS_LINKS } from 'components/LimitOrder/helpers' import useInterval from 'hooks/useInterval' import { ExternalLink } from 'theme' import { TransactionFlowState } from 'types/TransactionFlowState' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmOrderModal.tsx similarity index 97% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmOrderModal.tsx index d06fb47abb..0153646178 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmOrderModal.tsx @@ -8,9 +8,9 @@ import { ButtonPrimary, ButtonWarning } from 'components/Button' import CurrencyLogo from 'components/CurrencyLogo' import Modal from 'components/Modal' import { HStack, Stack } from 'components/Stack' -import { formatAmountOrder, removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' -import { WORSE_PRICE_DIFF_THRESHOLD } from 'components/swapv2/LimitOrder/hooks/useWarningCreateOrder' -import { LimitOrderCreateContext, RateInfo } from 'components/swapv2/LimitOrder/types' +import { formatAmountOrder, removeTrailingZero } from 'components/LimitOrder/helpers' +import { WORSE_PRICE_DIFF_THRESHOLD } from 'components/LimitOrder/hooks/useWarningCreateOrder' +import { LimitOrderCreateContext, RateInfo } from 'components/LimitOrder/types' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import { CloseIcon } from 'theme/components' import { cn } from 'utils/cn' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmTakeOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmTakeOrderModal.tsx similarity index 96% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmTakeOrderModal.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmTakeOrderModal.tsx index e09bc21aa7..4635a7eea6 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ConfirmTakeOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmTakeOrderModal.tsx @@ -8,10 +8,10 @@ import CurrencyLogo from 'components/CurrencyLogo' import Modal from 'components/Modal' import NumericalInput from 'components/NumericalInput' import { HStack, Stack } from 'components/Stack' -import ProcessingTakeOrderModal from 'components/swapv2/LimitOrder/Modals/ProcessingTakeOrderModal' -import { removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' -import { useTakeLimitOrder } from 'components/swapv2/LimitOrder/hooks/useTakeLimitOrder' -import { LimitOrderTakeContext } from 'components/swapv2/LimitOrder/types' +import ProcessingTakeOrderModal from 'components/LimitOrder/Modals/ProcessingTakeOrderModal' +import { removeTrailingZero } from 'components/LimitOrder/helpers' +import { useTakeLimitOrder } from 'components/LimitOrder/hooks/useTakeLimitOrder' +import { LimitOrderTakeContext } from 'components/LimitOrder/types' import { CloseIcon } from 'theme/components' import { cn } from 'utils/cn' import { formatDisplayNumber } from 'utils/numbers' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingOrderModal.tsx similarity index 98% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingOrderModal.tsx index 7dac31a5e3..f72bd231f8 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingOrderModal.tsx @@ -12,7 +12,7 @@ import type { ProcessingOrderState, ProcessingOrderStep, ProcessingOrderStepStatus, -} from 'components/swapv2/LimitOrder/hooks/useProcessingOrder' +} from 'components/LimitOrder/hooks/useProcessingOrder' import { NativeCurrencies } from 'constants/tokens' import { CloseIcon } from 'theme/components' import { cn } from 'utils/cn' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingTakeOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingTakeOrderModal.tsx similarity index 98% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingTakeOrderModal.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingTakeOrderModal.tsx index 68594def82..63b52ac779 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/ProcessingTakeOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingTakeOrderModal.tsx @@ -11,7 +11,7 @@ import { TakeOrderProcessingState, TakeOrderStep, TakeOrderStepStatus, -} from 'components/swapv2/LimitOrder/hooks/useTakeLimitOrder' +} from 'components/LimitOrder/hooks/useTakeLimitOrder' import { NativeCurrencies } from 'constants/tokens' import { CloseIcon } from 'theme/components' import { cn } from 'utils/cn' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/components.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/components.tsx similarity index 96% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/components.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Modals/components.tsx index 83ce9a8973..cb2bb90035 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/Modals/components.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/components.tsx @@ -5,9 +5,9 @@ import { X } from 'react-feather' import Column from 'components/Column' import { Swap as SwapIcon } from 'components/Icons' -import MarketPrice from 'components/swapv2/LimitOrder/Form/MarketPrice' -import { formatAmountOrder, formatRateLimitOrder } from 'components/swapv2/LimitOrder/helpers' -import { LimitOrder, RateInfo } from 'components/swapv2/LimitOrder/types' +import MarketPrice from 'components/LimitOrder/Form/MarketPrice' +import { formatAmountOrder, formatRateLimitOrder } from 'components/LimitOrder/helpers' +import { LimitOrder, RateInfo } from 'components/LimitOrder/types' import { NativeCurrencies } from 'constants/tokens' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import { cn } from 'utils/cn' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/OrderItem.tsx b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/OrderItem.tsx similarity index 99% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/OrderItem.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/MyOrders/OrderItem.tsx index db9baddfb9..f5ef7de8ad 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/OrderItem.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/OrderItem.tsx @@ -4,8 +4,8 @@ import { useMemo } from 'react' import { Trash } from 'react-feather' import { useNavigate } from 'react-router-dom' -import { calcPercentFilledOrder, isActiveStatus } from 'components/swapv2/LimitOrder/helpers' -import { LimitOrder, LimitOrderStatus, LimitOrderTab } from 'components/swapv2/LimitOrder/types' +import { calcPercentFilledOrder, isActiveStatus } from 'components/LimitOrder/helpers' +import { LimitOrder, LimitOrderStatus, LimitOrderTab } from 'components/LimitOrder/types' import { APP_PATHS } from 'constants/index' import { NETWORKS_INFO } from 'constants/networks' import { NativeCurrencies } from 'constants/tokens' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/SummaryNotify.tsx b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/SummaryNotify.tsx similarity index 97% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/SummaryNotify.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/MyOrders/SummaryNotify.tsx index 494739ec56..35a78383dd 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/SummaryNotify.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/SummaryNotify.tsx @@ -7,8 +7,8 @@ import { calcRate, formatAmountOrder, formatRateLimitOrder, -} from 'components/swapv2/LimitOrder/helpers' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +} from 'components/LimitOrder/helpers' +import { LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' const SummaryNotify = ({ type, diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/index.tsx b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx similarity index 96% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/index.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx index 329f3f6341..e24bba982a 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/index.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx @@ -9,17 +9,17 @@ import InfoHelper from 'components/InfoHelper' import Pagination from 'components/Pagination' import SearchInput from 'components/SearchInput' import Select from 'components/Select' -import CancelOrderModal from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' -import OrderItem from 'components/swapv2/LimitOrder/MyOrders/OrderItem' -import { useRequestCancelOrder } from 'components/swapv2/LimitOrder/MyOrders/useRequestCancelOrder' +import CancelOrderModal from 'components/LimitOrder/Modals/CancelOrderModal' +import OrderItem from 'components/LimitOrder/MyOrders/OrderItem' +import { useRequestCancelOrder } from 'components/LimitOrder/MyOrders/useRequestCancelOrder' import { formatAmountOrder, formatRateLimitOrder, getPayloadTracking, isActiveStatus, -} from 'components/swapv2/LimitOrder/helpers' -import { useCancellingOrders } from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +} from 'components/LimitOrder/helpers' +import { useCancellingOrders } from 'components/LimitOrder/hooks/useCancellingOrders' +import { LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' import { RTK_QUERY_TAGS, TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { useInvalidateTagLimitOrder } from 'hooks/useInvalidateTags' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/useRequestCancelOrder.tsx b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/useRequestCancelOrder.tsx similarity index 97% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/useRequestCancelOrder.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/MyOrders/useRequestCancelOrder.tsx index e21d53b493..ffc1ca85e0 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/MyOrders/useRequestCancelOrder.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/useRequestCancelOrder.tsx @@ -9,10 +9,10 @@ import { } from 'services/limitOrder' import { wagmiConfig } from 'components/Web3Provider' -import { CancelStatus } from 'components/swapv2/LimitOrder/Modals/CancelOrderModal' -import { formatAmountOrder, getErrorMessage, getPayloadTracking } from 'components/swapv2/LimitOrder/helpers' -import { useCancellingOrders } from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' -import { CancelOrderFunction, CancelOrderType, LimitOrder } from 'components/swapv2/LimitOrder/types' +import { CancelStatus } from 'components/LimitOrder/Modals/CancelOrderModal' +import { formatAmountOrder, getErrorMessage, getPayloadTracking } from 'components/LimitOrder/helpers' +import { useCancellingOrders } from 'components/LimitOrder/hooks/useCancellingOrders' +import { CancelOrderFunction, CancelOrderType, LimitOrder } from 'components/LimitOrder/types' import { LIMIT_ORDER_ABI } from 'constants/abis' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React, useWeb3React } from 'hooks' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx b/apps/kyberswap-interface/src/components/LimitOrder/OrderBook/OrderItem.tsx similarity index 98% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/OrderBook/OrderItem.tsx index 65e600c522..14fd8ccfe0 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/OrderItem.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/OrderBook/OrderItem.tsx @@ -4,7 +4,7 @@ import { useMemo } from 'react' import { useMedia } from 'react-use' import CopyHelper from 'components/Copy' -import { LimitOrderFromTokenPairFormatted } from 'components/swapv2/LimitOrder/types' +import { LimitOrderFromTokenPairFormatted } from 'components/LimitOrder/types' import { NETWORKS_INFO } from 'hooks/useChainsConfig' import { useLimitState } from 'state/limit/hooks' import { MEDIA_WIDTHS } from 'theme' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx b/apps/kyberswap-interface/src/components/LimitOrder/OrderBook/TableHeader.tsx similarity index 94% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/OrderBook/TableHeader.tsx index ee4ab694cf..00e321920d 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/OrderBook/TableHeader.tsx @@ -2,7 +2,7 @@ import { Trans } from '@lingui/macro' import { useMedia } from 'react-use' import InfoHelper from 'components/InfoHelper' -import { ItemWrapper } from 'components/swapv2/LimitOrder/OrderBook/OrderItem' +import { ItemWrapper } from 'components/LimitOrder/OrderBook/OrderItem' import { MEDIA_WIDTHS } from 'theme' const TableHeader = () => { diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx b/apps/kyberswap-interface/src/components/LimitOrder/OrderBook/index.tsx similarity index 97% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/OrderBook/index.tsx index 0b741450df..9716296cb0 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderBook/index.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/OrderBook/index.tsx @@ -5,14 +5,14 @@ import { useGetOrdersByTokenPairQuery } from 'services/limitOrder' import { ReactComponent as NoDataIcon } from 'assets/svg/no_data.svg' import RefreshLoading from 'components/RefreshLoading' -import ConfirmTakeOrderModal from 'components/swapv2/LimitOrder/Modals/ConfirmTakeOrderModal' -import OrderItem, { ItemWrapper } from 'components/swapv2/LimitOrder/OrderBook/OrderItem' -import TableHeader from 'components/swapv2/LimitOrder/OrderBook/TableHeader' +import ConfirmTakeOrderModal from 'components/LimitOrder/Modals/ConfirmTakeOrderModal' +import OrderItem, { ItemWrapper } from 'components/LimitOrder/OrderBook/OrderItem' +import TableHeader from 'components/LimitOrder/OrderBook/TableHeader' import { LimitOrderFromTokenPair, LimitOrderFromTokenPairFormatted, LimitOrderTakeContext, -} from 'components/swapv2/LimitOrder/types' +} from 'components/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import { useBaseTradeInfoLimitOrder } from 'hooks/useBaseTradeInfo' import RefetchIndicator from 'pages/Earns/components/RefetchIndicator' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderList/index.tsx b/apps/kyberswap-interface/src/components/LimitOrder/OrderList/index.tsx similarity index 95% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderList/index.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/OrderList/index.tsx index 9226494e61..ee2fe124a5 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/OrderList/index.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/OrderList/index.tsx @@ -4,9 +4,9 @@ import { useGetNumberOfInsufficientFundOrdersQuery } from 'services/limitOrder' import { HStack, Stack } from 'components/Stack' import { MouseoverTooltip } from 'components/Tooltip' -import MyOrders from 'components/swapv2/LimitOrder/MyOrders' -import OrderBook from 'components/swapv2/LimitOrder/OrderBook' -import { LimitOrderTab } from 'components/swapv2/LimitOrder/types' +import MyOrders from 'components/LimitOrder/MyOrders' +import OrderBook from 'components/LimitOrder/OrderBook' +import { LimitOrderTab } from 'components/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import useTab from 'hooks/useTab' import TokenPriceChart from 'pages/SwapV3/Components/TokenPriceChart' diff --git a/apps/kyberswap-interface/src/components/LimitOrder/TEST_SCRIPT.md b/apps/kyberswap-interface/src/components/LimitOrder/TEST_SCRIPT.md new file mode 100644 index 0000000000..e14cf042b5 --- /dev/null +++ b/apps/kyberswap-interface/src/components/LimitOrder/TEST_SCRIPT.md @@ -0,0 +1,221 @@ +# Limit Order QA Test Script + +Use the examples below as concrete scenarios. Token names are examples; any pair with the same balance/allowance setup is fine. + +Expected processing pattern: +- Create order: `Wrap native? -> Approve token -> Sign order` +- Take/fill order: `Wrap native? -> Approve token -> Fill order` +- `Wrap native` appears only when the required wrapped token balance is missing and native balance can cover the deficit. +- `Approve token` always appears. If allowance is already enough, it should auto-pass without wallet popup. + +## Create Order - ERC20 Input + +### 1. ERC20 balance enough, allowance already enough +- Example: create order `100 USDT -> 0.04 ETH`. +- Wallet balance: `500 USDT`. +- Existing allowance: `200 USDT`. +- Reserved active making amount: `0 USDT`. +- Expected processing steps: `Approve USDT`, `Sign order`. +- Expected tx/signature: approve step auto-passes; no approve tx; order signing/API create runs. + +### 2. ERC20 balance enough, allowance missing +- Example: create order `100 USDT -> 0.04 ETH`. +- Wallet balance: `500 USDT`. +- Existing allowance: `20 USDT`. +- Reserved active making amount: `0 USDT`. +- Expected processing steps: `Approve USDT`, `Sign order`. +- Expected tx/signature: approve USDT tx is requested; order signing starts after approval is detected. + +### 3. ERC20 allowance enough for input but not reserved active amount +- Example: create order `100 USDT -> 0.04 ETH`. +- Wallet balance: `500 USDT`. +- Existing allowance: `120 USDT`. +- Reserved active making amount: `50 USDT`. +- Required allowance check: `100 + 50 = 150 USDT`. +- Expected processing steps: `Approve USDT`, `Sign order`. +- Expected tx/signature: approve tx is requested because available allowance after reserved amount is only `70 USDT`. + +### 4. ERC20 invalid or zero amount +- Example: input amount is `0`, empty, or unparsable. +- Expected result: bottom button shows `Please enter a valid input amount`. +- Expected result: token input tooltip error is not shown separately. +- Expected result: review modal cannot open. + +## Create Order - Native / WETH Input + +### 5. Native ETH input, WETH balance and allowance already enough +- Example: create order `1 ETH -> 3,500 USDT`. +- Wallet balance: `2 ETH`, `1 WETH`. +- Existing WETH allowance: `2 WETH`. +- Reserved active making amount: `0 WETH`. +- Expected processing steps: `Approve WETH`, `Sign order`. +- Expected tx/signature: no wrap tx; approve step auto-passes; order signing/API create runs. + +### 6. Native ETH input, WETH balance enough but allowance missing +- Example: create order `1 ETH -> 3,500 USDT`. +- Wallet balance: `2 ETH`, `1 WETH`. +- Existing WETH allowance: `0 WETH`. +- Expected processing steps: `Approve WETH`, `Sign order`. +- Expected tx/signature: no wrap tx; approve WETH tx is requested; order signing starts after approval is detected. + +### 7. Native ETH input, WETH balance missing but ETH enough +- Example: create order `1 ETH -> 3,500 USDT`. +- Wallet balance: `2 ETH`, `0 WETH`. +- Existing WETH allowance: `0 WETH`. +- Expected wrap amount: `1 ETH`. +- Expected processing steps: `Wrap ETH`, `Approve WETH`, `Sign order`. +- Expected tx/signature: wrap `1 ETH`; approve WETH tx is requested; order signing starts after approval is detected. + +### 8. WETH input, WETH balance enough but allowance missing +- Example: create order `1 WETH -> 3,500 USDT`. +- Wallet balance: `1.5 WETH`, `0 ETH`. +- Existing WETH allowance: `0 WETH`. +- Expected processing steps: `Approve WETH`, `Sign order`. +- Expected tx/signature: no wrap tx; approve WETH tx is requested; order signing starts after approval is detected. + +### 9. WETH input, WETH balance partially missing but ETH enough +- Example: create order `1 WETH -> 3,500 USDT`. +- Wallet balance: `0.4 WETH`, `2 ETH`. +- Existing WETH allowance: `5 WETH`. +- Expected wrap amount: `0.6 ETH`. +- Expected processing steps: `Wrap ETH`, `Approve WETH`, `Sign order`. +- Expected tx/signature: wrap `0.6 ETH`; approve step auto-passes; order signing/API create runs. + +### 10. WETH input, WETH plus ETH insufficient +- Example: create order `1 WETH -> 3,500 USDT`. +- Wallet balance: `0.4 WETH`, `0.3 ETH`. +- Existing WETH allowance: any value. +- Required available amount: `0.4 + 0.3 = 0.7 WETH equivalent`. +- Expected result: bottom button shows `Insufficient Balance`. +- Expected result: review/processing cannot start. + +## Take / Fill Order - ERC20 Pay Token + +### 11. ERC20 pay token, allowance already enough +- Example: fill order requiring taker to pay `100 USDT` and receive `0.04 ETH`. +- Wallet balance: `500 USDT`. +- Existing USDT allowance: `200 USDT`. +- Expected processing steps: `Approve token`, `Fill order`. +- Expected tx: approve step auto-passes; no approve tx; fill tx is submitted. + +### 12. ERC20 pay token, allowance missing +- Example: fill order requiring taker to pay `100 USDT`. +- Wallet balance: `500 USDT`. +- Existing USDT allowance: `20 USDT`. +- Expected processing steps: `Approve token`, `Fill order`. +- Expected tx: approve USDT tx is requested; fill tx starts after approval is detected. + +### 13. Fill amount exceeds available amount +- Example: order has available amount `60 HYPE`. +- User enters fill amount `100 HYPE`. +- Expected result: submit button shows `Exceeds available amount`. +- Expected result: processing modal cannot start. + +## Take / Fill Order - WETH Pay Token + +### 14. WETH pay token, WETH balance and allowance already enough +- Example: fill order requiring taker to pay `1 WETH`. +- Wallet balance: `2 WETH`, `0 ETH`. +- Existing WETH allowance: `2 WETH`. +- Expected processing steps: `Approve token`, `Fill order`. +- Expected tx: no wrap tx; approve step auto-passes; fill tx is submitted. + +### 15. WETH pay token, WETH balance enough but allowance missing +- Example: fill order requiring taker to pay `1 WETH`. +- Wallet balance: `1.5 WETH`, `0 ETH`. +- Existing WETH allowance: `0 WETH`. +- Expected processing steps: `Approve token`, `Fill order`. +- Expected tx: no wrap tx; approve WETH tx is requested; fill tx starts after approval is detected. + +### 16. WETH pay token, WETH balance missing but ETH enough +- Example: fill order requiring taker to pay `1 WETH`. +- Wallet balance: `0.4 WETH`, `2 ETH`. +- Existing WETH allowance: `5 WETH`. +- Expected wrap amount: `0.6 ETH`. +- Expected processing steps: `Wrap ETH`, `Approve token`, `Fill order`. +- Expected tx: wrap `0.6 ETH`; approve step auto-passes; fill tx is submitted. + +### 17. WETH pay token, WETH balance missing and allowance missing +- Example: fill order requiring taker to pay `1 WETH`. +- Wallet balance: `0.4 WETH`, `2 ETH`. +- Existing WETH allowance: `0 WETH`. +- Expected wrap amount: `0.6 ETH`. +- Expected processing steps: `Wrap ETH`, `Approve token`, `Fill order`. +- Expected tx: wrap `0.6 ETH`; approve WETH tx is requested; fill tx starts after approval is detected. + +### 18. WETH pay token, WETH plus ETH insufficient +- Example: fill order requiring taker to pay `1 WETH`. +- Wallet balance: `0.4 WETH`, `0.3 ETH`. +- Existing WETH allowance: any value. +- Required available amount: `0.7 WETH equivalent`, below `1 WETH`. +- Expected result: submit button shows `Insufficient Balance`. +- Expected result: processing modal cannot start. + +## Take / Fill Order - Fee and Encode Payload + +### 19. Fill threshold and taker fee display +- Example: fill order requiring taker to pay `100 HYPE`, order rate `1 HYPE = 35 USDT`, taker fee `0.4%`. +- Gross receive amount: `3,500 USDT`. +- UI `You Receive`: `3,486 USDT`. +- Expected encode payload: `thresholdAmount` equals raw amount for `3,500 USDT`, not `3,486 USDT`. + +## Processing Modal Behavior + +### 20. Approve step auto-pass +- Example: allowance is already enough before opening processing modal. +- Expected result: `Approve token` row is visible, then quickly changes to success without wallet popup. +- Applies to: create order and take order. + +### 21. Processing cannot be dismissed mid-step +- Example: start `Wrap ETH`, `Approve token`, `Sign order`, or `Fill order`. +- Expected result: clicking outside does not close modal. +- Expected result: close icon is disabled while the active step is running. +- Expected result: close works after success or error. + +### 22. Retry failed step +- Example: reject approve in wallet. +- Expected result: approve row becomes error. +- Expected result: `Retry` appears on the same row without layout jump. +- Expected result: retry reruns only approve step, not previous successful wrap step. + +### 23. Create success actions +- Example: create order finishes successfully. +- Expected result: modal shows `Close` and `View Order`. +- Expected result: `View Order` opens Limit page with `tab=my_order`. + +### 24. Take success actions +- Example: fill order tx is submitted successfully. +- Expected result: modal shows `Close`. +- Expected result: closing modal also closes the fill modal flow. + +## Cancel Order + +### 25. Gasless cancel refresh +- Example: cancel order `#123` with gasless cancel. +- Expected result: cancel request succeeds. +- Expected result: My Orders list refreshes. +- Expected result: insufficient-orders badge refreshes. + +### 26. Hard cancel refresh +- Example: cancel order `#123` with hard cancel. +- Expected result: cancel tx is submitted. +- Expected result: cancelling-order insert API completes. +- Expected result: My Orders list refreshes after insert. +- Expected result: insufficient-orders badge refreshes. + +## URL / Tab Behavior + +### 27. Reserved order notice link +- Example: notice says `Some of your USDT is already reserved... here`. +- Action: click `here`. +- Expected result: confirm modal closes if it was open. +- Expected URL params: + - `tab=my_order` + - `orderTab=active` + - `search=` + +### 28. View created order +- Example: create order on Ethereum pair `USDT -> ETH`. +- Action: click `View Order` after success. +- Expected result: opens Limit route for the current network/pair. +- Expected URL param: `tab=my_order`. diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts b/apps/kyberswap-interface/src/components/LimitOrder/helpers.ts similarity index 99% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts rename to apps/kyberswap-interface/src/components/LimitOrder/helpers.ts index 3b6f57e3ec..436be07eb3 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/helpers.ts +++ b/apps/kyberswap-interface/src/components/LimitOrder/helpers.ts @@ -3,7 +3,7 @@ import { t } from '@lingui/macro' import JSBI from 'jsbi' import { CreateOrderBody } from 'services/limitOrder' -import { CreateOrderParam, LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +import { CreateOrderParam, LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' import { RESERVE_USD_DECIMALS } from 'constants/index' import { tryParseAmount } from 'state/swap/hooks' import { friendlyError } from 'utils/errorMessage' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCancellingOrders.ts similarity index 94% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useCancellingOrders.ts index b8cf447752..40ee945d98 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCancellingOrders.ts +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCancellingOrders.ts @@ -1,8 +1,8 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { useGetLOConfigQuery } from 'services/limitOrder' -import { isActiveStatus } from 'components/swapv2/LimitOrder/helpers' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +import { isActiveStatus } from 'components/LimitOrder/helpers' +import { LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import { OrderNonces, subscribeCancellingOrders } from 'utils/firebase' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCreateLimitOrder.tsx similarity index 95% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useCreateLimitOrder.tsx index 7e3e8735fa..6be837b332 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useCreateLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCreateLimitOrder.tsx @@ -5,10 +5,10 @@ import { useCreateOrderMutation } from 'services/limitOrder' import { NotificationType } from 'components/Announcement/type' import { getTipLinkAttribution } from 'components/TipLinkGeneratorModal/shared' -import { SummaryNotifyOrderPlaced } from 'components/swapv2/LimitOrder/MyOrders/SummaryNotify' -import { calcUsdPrices, getPayloadCreateOrder, removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' -import { useSignOrder } from 'components/swapv2/LimitOrder/hooks/useSignOrder' -import { CreateOrderParam, LimitOrderCreateContext } from 'components/swapv2/LimitOrder/types' +import { SummaryNotifyOrderPlaced } from 'components/LimitOrder/MyOrders/SummaryNotify' +import { calcUsdPrices, getPayloadCreateOrder, removeTrailingZero } from 'components/LimitOrder/helpers' +import { useSignOrder } from 'components/LimitOrder/hooks/useSignOrder' +import { CreateOrderParam, LimitOrderCreateContext } from 'components/LimitOrder/types' import { useActiveWeb3React } from 'hooks' import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' import { useNotify } from 'state/application/hooks' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useFetchActiveAllOrders.ts similarity index 94% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useFetchActiveAllOrders.ts index 3be0e40bfe..146e38f62f 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useFetchActiveAllOrders.ts +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useFetchActiveAllOrders.ts @@ -2,7 +2,7 @@ import { ChainId } from '@kyberswap/ks-sdk-core' import { useCallback, useMemo } from 'react' import { useGetLOConfigQuery, useGetListOrdersQuery } from 'services/limitOrder' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +import { LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' import { useActiveWeb3React } from 'hooks' export const useIsSupportSoftCancelOrder = () => { diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderExecution.tsx similarity index 96% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderExecution.tsx index f600f6dee8..424421a235 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderExecution.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderExecution.tsx @@ -6,12 +6,12 @@ import { useCallback, useEffect, useMemo } from 'react' import { useGetLOConfigQuery, useGetTotalActiveMakingAmountQuery } from 'services/limitOrder' import { wagmiConfig } from 'components/Web3Provider' -import { calcUsdPrices, getErrorMessage, removeTrailingZero } from 'components/swapv2/LimitOrder/helpers' -import { ProcessingOrderStep } from 'components/swapv2/LimitOrder/hooks/useProcessingOrder' -import { useValidateInputError } from 'components/swapv2/LimitOrder/hooks/useValidateInputError' -import { useWarningCreateOrder } from 'components/swapv2/LimitOrder/hooks/useWarningCreateOrder' -import { useWrapEthStatus } from 'components/swapv2/LimitOrder/hooks/useWrapEthStatus' -import { LimitOrderCreateContext } from 'components/swapv2/LimitOrder/types' +import { calcUsdPrices, getErrorMessage, removeTrailingZero } from 'components/LimitOrder/helpers' +import { ProcessingOrderStep } from 'components/LimitOrder/hooks/useProcessingOrder' +import { useValidateInputError } from 'components/LimitOrder/hooks/useValidateInputError' +import { useWarningCreateOrder } from 'components/LimitOrder/hooks/useWarningCreateOrder' +import { useWrapEthStatus } from 'components/LimitOrder/hooks/useWrapEthStatus' +import { LimitOrderCreateContext } from 'components/LimitOrder/types' import { ERC20_ABI } from 'constants/abis' import { NativeCurrencies } from 'constants/tokens' import { useActiveWeb3React } from 'hooks' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderFormState.ts similarity index 98% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderFormState.ts index 49eaba2cf0..7c6178d062 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useLimitOrderFormState.ts +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderFormState.ts @@ -9,8 +9,8 @@ import { calcRate, parseFraction, removeTrailingZero, -} from 'components/swapv2/LimitOrder/helpers' -import { RateInfo } from 'components/swapv2/LimitOrder/types' +} from 'components/LimitOrder/helpers' +import { RateInfo } from 'components/LimitOrder/types' import { TIMES_IN_SECS } from 'constants/index' import { SUPPORTED_NETWORKS } from 'constants/networks' import { useActiveWeb3React } from 'hooks' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useNotificationLimitOrder.tsx similarity index 97% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useNotificationLimitOrder.tsx index 3f56673eb3..5c1ea03d96 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useNotificationLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useNotificationLimitOrder.tsx @@ -3,8 +3,8 @@ import { useCallback, useEffect, useRef } from 'react' import { useAckNotificationOrderMutation } from 'services/limitOrder' import { NotificationType } from 'components/Announcement/type' -import SummaryNotify from 'components/swapv2/LimitOrder/MyOrders/SummaryNotify' -import { LimitOrder, LimitOrderStatus } from 'components/swapv2/LimitOrder/types' +import SummaryNotify from 'components/LimitOrder/MyOrders/SummaryNotify' +import { LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' import { APP_PATHS } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { useNotify } from 'state/application/hooks' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useProcessingOrder.ts b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useProcessingOrder.ts similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useProcessingOrder.ts rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useProcessingOrder.ts diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useSignOrder.ts similarity index 94% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useSignOrder.ts index 38831b68ec..b390c84b04 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useSignOrder.ts +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useSignOrder.ts @@ -1,8 +1,8 @@ import { useCallback } from 'react' import { useCreateOrderSignatureMutation } from 'services/limitOrder' -import { formatAmountOrder, getPayloadCreateOrder } from 'components/swapv2/LimitOrder/helpers' -import { CreateOrderParam } from 'components/swapv2/LimitOrder/types' +import { formatAmountOrder, getPayloadCreateOrder } from 'components/LimitOrder/helpers' +import { CreateOrderParam } from 'components/LimitOrder/types' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { TransactionFlowState } from 'types/TransactionFlowState' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useTakeLimitOrder.ts b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useTakeLimitOrder.ts similarity index 98% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useTakeLimitOrder.ts rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useTakeLimitOrder.ts index 90f88b0876..edb06a0634 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useTakeLimitOrder.ts +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useTakeLimitOrder.ts @@ -12,9 +12,9 @@ import { import { NotificationType } from 'components/Announcement/type' import { wagmiConfig } from 'components/Web3Provider' -import { getErrorMessage } from 'components/swapv2/LimitOrder/helpers' -import { useWrapEthStatus } from 'components/swapv2/LimitOrder/hooks/useWrapEthStatus' -import { LimitOrderTakeContext } from 'components/swapv2/LimitOrder/types' +import { getErrorMessage } from 'components/LimitOrder/helpers' +import { useWrapEthStatus } from 'components/LimitOrder/hooks/useWrapEthStatus' +import { LimitOrderTakeContext } from 'components/LimitOrder/types' import { ERC20_ABI } from 'constants/abis' import { RTK_QUERY_TAGS } from 'constants/index' import { NativeCurrencies } from 'constants/tokens' diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useValidateInputError.tsx similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useValidateInputError.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useValidateInputError.tsx diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useWarningCreateOrder.tsx similarity index 98% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useWarningCreateOrder.tsx index 9cf7c710b2..3a3cca1258 100644 --- a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWarningCreateOrder.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useWarningCreateOrder.tsx @@ -3,7 +3,7 @@ import { Trans } from '@lingui/macro' import { PropsWithChildren, useMemo } from 'react' import { Link } from 'react-router-dom' -import { DeltaRateLimitOrder, LimitOrderStatus, LimitOrderTab } from 'components/swapv2/LimitOrder/types' +import { DeltaRateLimitOrder, LimitOrderStatus, LimitOrderTab } from 'components/LimitOrder/types' const AprHighlight = ({ children }: PropsWithChildren) => {children} diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWrapEthStatus.ts b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useWrapEthStatus.ts similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/hooks/useWrapEthStatus.ts rename to apps/kyberswap-interface/src/components/LimitOrder/hooks/useWrapEthStatus.ts diff --git a/apps/kyberswap-interface/src/components/swapv2/LimitOrder/types.ts b/apps/kyberswap-interface/src/components/LimitOrder/types.ts similarity index 100% rename from apps/kyberswap-interface/src/components/swapv2/LimitOrder/types.ts rename to apps/kyberswap-interface/src/components/LimitOrder/types.ts diff --git a/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx b/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx index 5073557578..88b579bd31 100644 --- a/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx +++ b/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx @@ -23,9 +23,9 @@ import { BuildRouteResult } from 'components/SwapForm/hooks/useBuildRoute' import { MouseoverTooltip } from 'components/Tooltip' import { TransactionErrorContent } from 'components/TransactionConfirmationModal' import WarningNote from 'components/WarningNote' -import { calcPercentFilledOrder } from 'components/swapv2/LimitOrder/helpers' -import { ReservedOrderNotice } from 'components/swapv2/LimitOrder/hooks/useWarningCreateOrder' -import { LimitOrderStatus, LimitOrderTab } from 'components/swapv2/LimitOrder/types' +import { calcPercentFilledOrder } from 'components/LimitOrder/helpers' +import { ReservedOrderNotice } from 'components/LimitOrder/hooks/useWarningCreateOrder' +import { LimitOrderStatus, LimitOrderTab } from 'components/LimitOrder/types' import { StyledBalanceMaxMini } from 'components/swapv2/styleds' import { TOKEN_API_URL } from 'constants/env' import { APP_PATHS, PAIR_CATEGORY } from 'constants/index' diff --git a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/Status.tsx b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/Status.tsx index bc247709a8..053df5195c 100644 --- a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/Status.tsx +++ b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/Status.tsx @@ -10,7 +10,7 @@ import WarningIcon from 'components/Icons/WarningIcon' import Loader from 'components/Loader' import { PrimaryText } from 'components/WalletPopup/Transactions/TransactionItem' import { isTxsPendingTooLong as isShowPendingWarning } from 'components/WalletPopup/Transactions/helper' -import { CancellingOrderInfo } from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' +import { CancellingOrderInfo } from 'components/LimitOrder/hooks/useCancellingOrders' import { AppDispatch } from 'state' import { modifyTransaction } from 'state/transactions/actions' import { TRANSACTION_TYPE, TransactionDetails } from 'state/transactions/type' diff --git a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/TransactionItem.tsx b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/TransactionItem.tsx index c4c642642c..91be564c94 100644 --- a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/TransactionItem.tsx +++ b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/TransactionItem.tsx @@ -15,7 +15,7 @@ import PendingWarning from 'components/WalletPopup/Transactions/PendingWarning' import PoolFarmLink from 'components/WalletPopup/Transactions/PoolFarmLink' import Status from 'components/WalletPopup/Transactions/Status' import { isTxsPendingTooLong } from 'components/WalletPopup/Transactions/helper' -import { CancellingOrderInfo } from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' +import { CancellingOrderInfo } from 'components/LimitOrder/hooks/useCancellingOrders' import { APP_PATHS, ETHER_ADDRESS } from 'constants/index' import { TRANSACTION_TYPE, diff --git a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx index 906662b630..7db587a3b4 100644 --- a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx +++ b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx @@ -11,7 +11,7 @@ import Row, { RowBetween } from 'components/Row' import Tab from 'components/WalletPopup/Transactions/Tab' import TransactionItem from 'components/WalletPopup/Transactions/TransactionItem' import { NUMBERS } from 'components/WalletPopup/Transactions/helper' -import { CancellingOrderInfo, useCancellingOrders } from 'components/swapv2/LimitOrder/hooks/useCancellingOrders' +import { CancellingOrderInfo, useCancellingOrders } from 'components/LimitOrder/hooks/useCancellingOrders' import { useActiveWeb3React } from 'hooks' import { fetchListTokenByAddresses, findCacheToken, useIsLoadedTokenDefault } from 'hooks/Tokens' import { isSupportKyberDao } from 'hooks/kyberdao' diff --git a/apps/kyberswap-interface/src/locales/en-US.po b/apps/kyberswap-interface/src/locales/en-US.po index ef55fa5ef3..07dd558eca 100644 --- a/apps/kyberswap-interface/src/locales/en-US.po +++ b/apps/kyberswap-interface/src/locales/en-US.po @@ -34,7 +34,7 @@ msgstr "Staked liquidity" msgid "Please type the word <0>Confirm below to enable Degen Mode" msgstr "Please type the word <0>Confirm below to enable Degen Mode" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "You need to first allow KyberSwap smart contracts to use your {inSymbol}. This has to be done only once for each token." msgstr "You need to first allow KyberSwap smart contracts to use your {inSymbol}. This has to be done only once for each token." @@ -70,7 +70,7 @@ msgstr "Updated" msgid "Position Status" msgstr "Position Status" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "Open Orders" msgstr "Open Orders" @@ -116,8 +116,8 @@ msgstr "Any Other Pairs" msgid "Exported profiles will not be associated with your wallet. Your export code is unique. Learn more about profile <0>here." msgstr "Exported profiles will not be associated with your wallet. Your export code is unique. Learn more about profile <0>here." -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx -#: src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/OrderBook/TableHeader.tsx msgid "RATE" msgstr "RATE" @@ -228,8 +228,8 @@ msgstr "Unable to switch network. Please try it on your wallet." msgid "Which activities earn points?" msgstr "Which activities earn points?" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "Placing order" msgstr "Placing order" @@ -369,7 +369,7 @@ msgstr "Ex: ARB <> USDC; ETH <> ARB; PENDLE <> ARB" msgid "No hidden fees - Your optional tips support {clientName}!" msgstr "No hidden fees - Your optional tips support {clientName}!" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Hard Cancel" msgstr "Hard Cancel" @@ -436,7 +436,7 @@ msgid "An error occurred. Invalid Permit Signature." msgstr "An error occurred. Invalid Permit Signature." #: src/components/SwapForm/SwapActionButton/index.tsx -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "Switch to {0}" msgstr "Switch to {0}" @@ -512,7 +512,7 @@ msgstr "Stable Pairs:" msgid "USD stablecoins equivalent to 60% of the Reference Value of Lost Affected Assets contributed from such Affected Address, vested continuously on a linear basis over 3 months." msgstr "USD stablecoins equivalent to 60% of the Reference Value of Lost Affected Assets contributed from such Affected Address, vested continuously on a linear basis over 3 months." -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "<0>{0} {makerAssetSymbol} and receive <1>{1} {takerAssetSymbol} <2>at {takerAssetSymbol} price of {rate} {makerAssetSymbol}" msgstr "<0>{0} {makerAssetSymbol} and receive <1>{1} {takerAssetSymbol} <2>at {takerAssetSymbol} price of {rate} {makerAssetSymbol}" @@ -578,7 +578,7 @@ msgstr "Unknown error" #~ msgid "Switch Profile" #~ msgstr "Switch Profile" -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "Canceling order" msgstr "Canceling order" @@ -631,7 +631,7 @@ msgstr "Winner" msgid "TOTAL AMOUNT (USD)" msgstr "TOTAL AMOUNT (USD)" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "Review your order" msgstr "Review your order" @@ -724,7 +724,7 @@ msgstr "The current rewards are based on your current rank. See Information for msgid "Error occur, please try again" msgstr "Error occur, please try again" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Bulk Cancellation" msgstr "Bulk Cancellation" @@ -828,8 +828,8 @@ msgstr "Choose to reinvest your earnings back into this position or send them to msgid "Get notified via Telegram when this position moves out of range or back in range" msgstr "Get notified via Telegram when this position moves out of range or back in range" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "and receive" msgstr "and receive" @@ -933,7 +933,7 @@ msgstr "Cross-Chain Routing Sources" msgid "If you miss the claiming deadline, your eligibility will expire and the reward will no longer be available." msgstr "If you miss the claiming deadline, your eligibility will expire and the reward will no longer be available." -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Are you sure you want to cancel {0} limit orders?" msgstr "Are you sure you want to cancel {0} limit orders?" @@ -1035,7 +1035,7 @@ msgstr "Transactions" msgid "Notification" msgstr "Notification" -#: src/components/swapv2/LimitOrder/DeltaRate.tsx +#: src/components/LimitOrder/DeltaRate.tsx msgid "Your selected price is {styledPercent} better than the current market price." msgstr "Your selected price is {styledPercent} better than the current market price." @@ -1108,7 +1108,7 @@ msgstr "You had successfully import this profile. You are now signed in with thi msgid "Automatically remove liquidity from this position when your pre-set rice, time, or fee yield condition(s)." msgstr "Automatically remove liquidity from this position when your pre-set rice, time, or fee yield condition(s)." -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Cancel order to pay {mainMsg} failed" msgstr "Cancel order to pay {mainMsg} failed" @@ -1167,7 +1167,7 @@ msgstr "Invalid amount" msgid "Overview" msgstr "Overview" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Insufficient {0} balance for order execution." msgstr "Insufficient {0} balance for order execution." @@ -1188,7 +1188,7 @@ msgstr "Import Pool" msgid "Due to a <0><1>potential issue with our legacy Elastic protocol, we recommend that all liquidity providers withdraw their liquidity from Elastic Pools (Legacy). We have fixed all the issues and deployed the new and audited <2>{0} where you can add liquidity normally instead." msgstr "Due to a <0><1>potential issue with our legacy Elastic protocol, we recommend that all liquidity providers withdraw their liquidity from Elastic Pools (Legacy). We have fixed all the issues and deployed the new and audited <2>{0} where you can add liquidity normally instead." -#: src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx +#: src/components/LimitOrder/ListLimitOrder/TabSelector.tsx msgid "My Order(s)" msgstr "My Order(s)" @@ -1226,7 +1226,7 @@ msgstr "Navigating My Pools Tutorial" msgid "The actual gas cost will be deducted from your outputs when the order executes." msgstr "The actual gas cost will be deducted from your outputs when the order executes." -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your orders below have successfully cancelled:<0/>{listOrderName}" msgstr "Your orders below have successfully cancelled:<0/>{listOrderName}" @@ -1254,7 +1254,7 @@ msgstr "Collect fees is not supported on this dex" msgid "Choose Pool Pair" msgstr "Choose Pool Pair" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Hour" msgstr "Hour" @@ -1497,7 +1497,7 @@ msgstr "When will gas refunds be available to claim?" msgid "These Terms and Conditions <0>(\"Terms\") should be read in conjunction with the KyberSwap Terms of Use, which lay out the terms and conditions that apply to all KyberSwap promotional activities (\"Campaign\")." msgstr "These Terms and Conditions <0>(\"Terms\") should be read in conjunction with the KyberSwap Terms of Use, which lay out the terms and conditions that apply to all KyberSwap promotional activities (\"Campaign\")." -#: src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx +#: src/components/LimitOrder/useWarningCreateOrder.tsx msgid "Your current allowance is insufficient. Approve an additional {0} {1} to proceed." msgstr "Your current allowance is insufficient. Approve an additional {0} {1} to proceed." @@ -1578,7 +1578,7 @@ msgstr "Claiming {rewardAmounts} KNC" msgid "Routed via" msgstr "Routed via" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "Partially Filled Orders" msgstr "Partially Filled Orders" @@ -1596,7 +1596,7 @@ msgstr "Estimated change in price due to the size of your transaction." msgid "Vote on current epoch proposals to get your full reward." msgstr "Vote on current epoch proposals to get your full reward." -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx msgid "CREATED | EXPIRY" msgstr "CREATED | EXPIRY" @@ -1615,7 +1615,7 @@ msgstr "Voting ends in:" msgid "KNC Staked" msgstr "KNC Staked" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Hard Cancel All Orders" msgstr "Hard Cancel All Orders" @@ -1624,7 +1624,7 @@ msgid "🏆 Prize: {0} KNC" msgstr "🏆 Prize: {0} KNC" #: src/components/SwapForm/hooks/useGetInputError.tsx -#: src/components/swapv2/LimitOrder/useValidateInputError.tsx +#: src/components/LimitOrder/useValidateInputError.tsx msgid "Insufficient {symbol} balance" msgstr "Insufficient {symbol} balance" @@ -1654,7 +1654,7 @@ msgstr "Claim your rewards" msgid "Merkl Bonus" msgstr "Merkl Bonus" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "You have successfully cancelled an order to pay {mainMsg}{filledComponent}" msgstr "You have successfully cancelled an order to pay {mainMsg}{filledComponent}" @@ -1671,7 +1671,7 @@ msgstr "KyberSwap Guide" msgid "Total Amount (USDC)" msgstr "Total Amount (USDC)" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Once you add {0}, the order will be executed at <0>{1}% below the market price." msgstr "Once you add {0}, the order will be executed at <0>{1}% below the market price." @@ -1705,7 +1705,7 @@ msgstr "You need to first give a temporary 24H approval to KyberSwap's smart con msgid "To learn more about how to increase liquidity to KyberSwap Elastic, view <0> here" msgstr "To learn more about how to increase liquidity to KyberSwap Elastic, view <0> here" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "This chain is not supported gasless cancel. It's coming soon." msgstr "This chain is not supported gasless cancel. It's coming soon." @@ -1729,7 +1729,7 @@ msgstr "Connect wallet to view notification" #~ msgid "{0}Skip" #~ msgstr "{0}Skip" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Note: Your currently existing order is {percent}% filled" msgstr "Note: Your currently existing order is {percent}% filled" @@ -1740,11 +1740,11 @@ msgstr "Note: Your currently existing order is {percent}% filled" msgid "In-Progress" msgstr "In-Progress" -#: src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx +#: src/components/LimitOrder/ListLimitOrder/TabSelector.tsx msgid "Open Limit Orders" msgstr "Open Limit Orders" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "Search by token symbol or token address" msgstr "Search by token symbol or token address" @@ -1822,7 +1822,7 @@ msgstr "Generate Referral" msgid "(ii) holds a licence issued by MAS for the provision of, or is authorised by MAS to provide, any service relating to tokens (whether digital payment tokens under the Payment Services Act of Singapore or digital tokens under the Financial Markets Services Act of Singapore)." msgstr "(ii) holds a licence issued by MAS for the provision of, or is authorised by MAS to provide, any service relating to tokens (whether digital payment tokens under the Payment Services Act of Singapore or digital tokens under the Financial Markets Services Act of Singapore)." -#: src/components/swapv2/LimitOrder/DeltaRate.tsx +#: src/components/LimitOrder/DeltaRate.tsx msgid "Sell {symbol} at rate" msgstr "Sell {symbol} at rate" @@ -1862,7 +1862,7 @@ msgstr "KNC rewards will be available to claim on the “My Dashboard” page st msgid "Total Balance" msgstr "Total Balance" -#: src/components/swapv2/LimitOrder/useValidateInputError.tsx +#: src/components/LimitOrder/useValidateInputError.tsx msgid "Your output amount is invalid." msgstr "Your output amount is invalid." @@ -1936,7 +1936,7 @@ msgstr "Go to My Pool" #~ msgid "Max:" #~ msgstr "Max:" -#: src/components/swapv2/LimitOrder/TradePrice.tsx +#: src/components/LimitOrder/TradePrice.tsx msgid "Unable to get the market price" msgstr "Unable to get the market price" @@ -2055,7 +2055,7 @@ msgstr "Limited on-chain activity in the past 24h - price may not reflect tradab msgid "Yes. We only count the first 50 eligible hashes per wallet." msgstr "Yes. We only count the first 50 eligible hashes per wallet." -#: src/components/swapv2/LimitOrder/Modals/styled.tsx +#: src/components/LimitOrder/Modals/styled.tsx msgid "Est. Market Price" msgstr "Est. Market Price" @@ -2064,7 +2064,7 @@ msgstr "Est. Market Price" msgid "<0>Slippage<1>is high. Your transaction may be front-run" msgstr "<0>Slippage<1>is high. Your transaction may be front-run" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "Cancelled Orders" msgstr "Cancelled Orders" @@ -2169,7 +2169,7 @@ msgid "What are the different categories and how does it work?" msgstr "What are the different categories and how does it work?" #: src/components/SwapForm/SwapActionButton/SwapButtonWithPriceImpact.tsx -#: src/components/swapv2/LimitOrder/TradePrice.tsx +#: src/components/LimitOrder/TradePrice.tsx #: src/components/swapv2/TradePrice.tsx msgid "Calculating" msgstr "Calculating" @@ -2178,7 +2178,7 @@ msgstr "Calculating" msgid "Removing a Smart Exit" msgstr "Removing a Smart Exit" -#: src/components/swapv2/LimitOrder/DeltaRate.tsx +#: src/components/LimitOrder/DeltaRate.tsx msgid "Your selected price is {styledPercent} worse than the current market price." msgstr "Your selected price is {styledPercent} worse than the current market price." @@ -2269,7 +2269,7 @@ msgstr "Rethink" msgid "Multichain team ceased operations, and we discourage user interaction with the deployed Wrapped KNC token contracts on various chains. See more <0>here" msgstr "Multichain team ceased operations, and we discourage user interaction with the deployed Wrapped KNC token contracts on various chains. See more <0>here" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "No orders found." msgstr "No orders found." @@ -2277,7 +2277,7 @@ msgstr "No orders found." #~ msgid "Expert" #~ msgstr "Expert" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "Hard Cancel Instead" msgstr "Hard Cancel Instead" @@ -2305,7 +2305,7 @@ msgstr "We will use our Aggregator to regularly monitor price changes based on y msgid "Claim threshold" msgstr "Claim threshold" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "Est. Market Price:" msgstr "Est. Market Price:" @@ -2457,7 +2457,7 @@ msgstr "Visit the claim portal, connect your eligible wallet address, and comple msgid "Failed to switch network" msgstr "Failed to switch network" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "You don't have any open orders yet." msgstr "You don't have any open orders yet." @@ -2506,7 +2506,7 @@ msgstr "Top 100 pools that have the high total earned fee in the last 7 days" msgid "TVL" msgstr "TVL" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "Cancel without paying gas." msgstr "Cancel without paying gas." @@ -2564,7 +2564,7 @@ msgstr "Est. liquidity & <0/> earned fee" msgid "Smart Exit executed" msgstr "Smart Exit executed" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Gasless Cancel All Orders" msgstr "Gasless Cancel All Orders" @@ -2711,7 +2711,7 @@ msgstr "Price Alert" msgid "My Positions" msgstr "My Positions" -#: src/components/swapv2/LimitOrder/helpers.ts +#: src/components/LimitOrder/helpers.ts msgid "User denied message signature" msgstr "User denied message signature" @@ -2719,7 +2719,7 @@ msgstr "User denied message signature" msgid "→ Hash 1 is chosen for promotional rewards." msgstr "→ Hash 1 is chosen for promotional rewards." -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "You have successfully cancelled all orders." msgstr "You have successfully cancelled all orders." @@ -2773,7 +2773,7 @@ msgstr "Trading" msgid "No price alerts created yet" msgstr "No price alerts created yet" -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "Your request has timed out." msgstr "Your request has timed out." @@ -2867,8 +2867,8 @@ msgstr "There is no minimum nor maximum value requirement for a trade." msgid "Past Actions" msgstr "Past Actions" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "Confirm Price" msgstr "Confirm Price" @@ -3070,7 +3070,7 @@ msgstr "Show more details" msgid "Mark all read" msgstr "Mark all read" -#: src/components/swapv2/LimitOrder/OrderBook/index.tsx +#: src/components/LimitOrder/OrderBook/index.tsx msgid "Orders refresh in" msgstr "Orders refresh in" @@ -3189,11 +3189,11 @@ msgstr "Max Execution Gas" msgid "Checking data" msgstr "Checking data" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "You Sell" msgstr "You Sell" -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx msgid "FILLED % | STATUS" msgstr "FILLED % | STATUS" @@ -3250,7 +3250,7 @@ msgstr "Staked LP Tokens" msgid "Claiming" msgstr "Claiming" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "<0/> Cancellation may not be instant. <1>Learn more ↗︎" msgstr "<0/> Cancellation may not be instant. <1>Learn more ↗︎" @@ -3264,7 +3264,7 @@ msgstr "Explore Liquidity Pools to get started" #: src/components/Header/index.tsx #: src/components/Menu/index.tsx -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "Market" msgstr "Market" @@ -3395,7 +3395,7 @@ msgstr "ESTIMATED REWARDS" msgid "Review the Cross-chain Swap" msgstr "Review the Cross-chain Swap" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "insufficient funds" msgstr "insufficient funds" @@ -3403,7 +3403,7 @@ msgstr "insufficient funds" msgid "Expired" msgstr "Expired" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Default Options" msgstr "Default Options" @@ -3539,8 +3539,8 @@ msgstr "Volume is measured based on the value of tokens received on the <0>desti msgid "All Time High" msgstr "All Time High" -#: src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx -#: src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx +#: src/components/LimitOrder/OrderBook/TableHeader.tsx +#: src/components/LimitOrder/OrderBook/TableHeader.tsx #: src/pages/CrossChainSwap/components/TransactionHistory.tsx msgid "AMOUNT" msgstr "AMOUNT" @@ -3670,7 +3670,7 @@ msgstr "After" msgid "Token is not available" msgstr "Token is not available" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Set" msgstr "Set" @@ -3691,7 +3691,7 @@ msgstr "Others" msgid "Claim Asset" msgstr "Claim Asset" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Customize the Expiry Time" msgstr "Customize the Expiry Time" @@ -3826,7 +3826,7 @@ msgstr "Approve <0>{0} requires to be more than <1>{1} {2}, find out mor #~ msgid "Withdraw your liquidity positions (i.e. your NFT tokens) from the farming contract." #~ msgstr "Withdraw your liquidity positions (i.e. your NFT tokens) from the farming contract." -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Cancel Order" msgstr "Cancel Order" @@ -3906,7 +3906,7 @@ msgstr "You will receive {amount} {tokenSymbol} soon!" msgid "Total Available Rewards" msgstr "Total Available Rewards" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "Filled Orders" msgstr "Filled Orders" @@ -4036,7 +4036,7 @@ msgstr "Are swaps on all chains eligible for gas refunds?" msgid "As a referrer, when someone you referred earns ARB on a trade made on KyberSwap.com, you get 10% of their rewards allocation." msgstr "As a referrer, when someone you referred earns ARB on a trade made on KyberSwap.com, you get 10% of their rewards allocation." -#: src/components/swapv2/LimitOrder/useValidateInputError.tsx +#: src/components/LimitOrder/useValidateInputError.tsx #: src/components/WalletPopup/SendToken/index.tsx msgid "Your input amount is invalid." msgstr "Your input amount is invalid." @@ -4132,7 +4132,7 @@ msgstr "Approve Error" #~ msgid "empty" #~ msgstr "empty" -#: src/components/swapv2/LimitOrder/DeltaRate.tsx +#: src/components/LimitOrder/DeltaRate.tsx msgid "Buy {symbol} at rate" msgstr "Buy {symbol} at rate" @@ -4247,7 +4247,7 @@ msgstr "KyberSwap reserves the right to disqualify any address found to engage i msgid "<0>Week 5 Aug 05 - Aug 11" msgstr "<0>Week 5 Aug 05 - Aug 11" -#: src/components/swapv2/LimitOrder/helpers.ts +#: src/components/LimitOrder/helpers.ts msgid "Invalid signature" msgstr "Invalid signature" @@ -4286,7 +4286,7 @@ msgstr "Rewards to claim after the end of the countdown period." msgid "Stablecoins to Stablecoins trading will give 0.5 Points per USD swapped." msgstr "Stablecoins to Stablecoins trading will give 0.5 Points per USD swapped." -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "Edit immediately by paying {gasAmountDisplay} gas fees." msgstr "Edit immediately by paying {gasAmountDisplay} gas fees." @@ -4307,7 +4307,7 @@ msgstr "starting in" msgid "KyberSwap reserves the right to shorten, extend, suspend, or terminate the Campaign at any time, at its sole discretion." msgstr "KyberSwap reserves the right to shorten, extend, suspend, or terminate the Campaign at any time, at its sole discretion." -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Partially Filled" msgstr "Partially Filled" @@ -4363,7 +4363,7 @@ msgstr "If you want both conditions to be required, switch to AND." msgid "Use any 2 different products: +20 points" msgstr "Use any 2 different products: +20 points" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Order will Expire on" msgstr "Order will Expire on" @@ -4799,7 +4799,7 @@ msgstr "Pending" msgid "Affected Assets taken from Affected Pools by subsequent activity (“Category 2 MBA”) of two mimicking bots mimicking the Primary Exploit, which Affected Assets have yet to be recovered" msgstr "Affected Assets taken from Affected Pools by subsequent activity (“Category 2 MBA”) of two mimicking bots mimicking the Primary Exploit, which Affected Assets have yet to be recovered" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your order was {filledPercent}% filled" msgstr "Your order was {filledPercent}% filled" @@ -4831,7 +4831,7 @@ msgstr "Claim only" msgid "WALLET" msgstr "WALLET" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "You Buy" msgstr "You Buy" @@ -4872,8 +4872,8 @@ msgstr "Exit when fee yield" #: src/components/Header/groups/SwapNavGroup.tsx #: src/components/Menu/index.tsx #: src/components/SwapForm/PriceImpactNote.tsx -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx #: src/pages/Campaign/MyDashboard.tsx #: src/pages/SwapV3/Tabs/LimitTab.tsx msgid "Limit Order" @@ -4913,8 +4913,8 @@ msgstr "Verify your email address." msgid "Connect wallet" msgstr "Connect wallet" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "at" msgstr "at" @@ -4940,7 +4940,7 @@ msgstr "No element of chance, randomness or gambling is involved." msgid "Coming Soon" msgstr "Coming Soon" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "before the order expires on" msgstr "before the order expires on" @@ -4994,7 +4994,7 @@ msgstr "An error occurred" msgid "To be eligible, you must make a swap on <0>KyberSwap.com using trading pairs composed of eligible tokens from the list, excluding WETH-ETH, WETH-USDC, and ETH-USDC." msgstr "To be eligible, you must make a swap on <0>KyberSwap.com using trading pairs composed of eligible tokens from the list, excluding WETH-ETH, WETH-USDC, and ETH-USDC." -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your order to pay {mainMsg} is {filledPercent}% filled" msgstr "Your order to pay {mainMsg} is {filledPercent}% filled" @@ -5113,7 +5113,7 @@ msgstr "Max is {format}" msgid "You can <0>choose Grant Option once, please read and decide carefully" msgstr "You can <0>choose Grant Option once, please read and decide carefully" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Gasless Cancel {0}/{1} Orders" msgstr "Gasless Cancel {0}/{1} Orders" @@ -5169,7 +5169,7 @@ msgstr "Saving ..." msgid "Invalid email address" msgstr "Invalid email address" -#: src/components/swapv2/LimitOrder/useValidateInputError.tsx +#: src/components/LimitOrder/useValidateInputError.tsx msgid "Insufficient {0} balance.<0/><1>{1}{formatNum} {2} remaining after deducting Active and Open orders." msgstr "Insufficient {0} balance.<0/><1>{1}{formatNum} {2} remaining after deducting Active and Open orders." @@ -5189,7 +5189,7 @@ msgstr "- powered by Blink to protect your transactions from front-running attac msgid "Claiming rewards" msgstr "Claiming rewards" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Are you sure you want to cancel this limit order?" msgstr "Are you sure you want to cancel this limit order?" @@ -5202,7 +5202,7 @@ msgstr "Verification code is wrong or expired. Please try again." msgid "Vesting" msgstr "Vesting" -#: src/components/swapv2/LimitOrder/Modals/styled.tsx +#: src/components/LimitOrder/Modals/styled.tsx msgid "{0} price of {rateStr} {1}" msgstr "{0} price of {rateStr} {1}" @@ -5257,7 +5257,7 @@ msgstr "Saving..." #~ msgid "Suitable for stablecoin or stable correlated pairs. Anticipating price to fluctuate within ~0.6%. You can earn fees even if the price goes up by 0.3% or goes down by 0.3%." #~ msgstr "Suitable for stablecoin or stable correlated pairs. Anticipating price to fluctuate within ~0.6%. You can earn fees even if the price goes up by 0.3% or goes down by 0.3%." -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Cancel Orders Failed" msgstr "Cancel Orders Failed" @@ -5353,7 +5353,7 @@ msgstr "Approving..." msgid "For every $100 volume, participants earn points based on the following distribution:" msgstr "For every $100 volume, participants earn points based on the following distribution:" -#: src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx +#: src/components/LimitOrder/OrderBook/TableHeader.tsx msgid "ORDER STATUS" msgstr "ORDER STATUS" @@ -5402,7 +5402,7 @@ msgstr "Spread" msgid "See All" msgstr "See All" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "You have successfully placed an order to pay <0>{0} {1} and receive <1>{2} {3} <2>at {4} price of {5} {6}." msgstr "You have successfully placed an order to pay <0>{0} {1} and receive <1>{2} {3} <2>at {4} price of {5} {6}." @@ -5460,7 +5460,7 @@ msgstr "No notifications found" msgid "<0>Your <1>Slippage<2> {msg}" msgstr "<0>Your <1>Slippage<2> {msg}" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Cancel Orders" msgstr "Cancel Orders" @@ -5645,7 +5645,7 @@ msgstr "<0>Week 1 May 19 - May 25" msgid "Protection safeguards you from front-running attacks on {chainName}. We recommend using" msgstr "Protection safeguards you from front-running attacks on {chainName}. We recommend using" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Expiry" msgstr "Expiry" @@ -5661,7 +5661,7 @@ msgstr "Est. liquidity & earned fee" msgid "Migrating {value} KNCL to KNC" msgstr "Migrating {value} KNCL to KNC" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "Cancel immediately by paying {gasAmountDisplay} gas fees." msgstr "Cancel immediately by paying {gasAmountDisplay} gas fees." @@ -5669,7 +5669,7 @@ msgstr "Cancel immediately by paying {gasAmountDisplay} gas fees." msgid "Add Condition 2" msgstr "Add Condition 2" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your orders below cancel failed:<0/>{listOrderName}" msgstr "Your orders below cancel failed:<0/>{listOrderName}" @@ -5861,7 +5861,7 @@ msgstr "Total Fees Amount<0/>(USD)" #~ msgid "Get Started" #~ msgstr "Get Started" -#: src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx +#: src/components/LimitOrder/ListOrder/useRequestCancelOrder.tsx msgid "Canceling your orders" msgstr "Canceling your orders" @@ -5878,12 +5878,12 @@ msgstr "There is no minimum nor maximum value requirement for a trade to earn po msgid "Search for a liquidity source" msgstr "Search for a liquidity source" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Order will trigger on" msgstr "Order will trigger on" -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx msgid "LIMIT ORDER(S)" msgstr "LIMIT ORDER(S)" @@ -5958,7 +5958,7 @@ msgstr "<0>Week 9 Sep 02 - Sep 08" msgid "Step" msgstr "Step" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Cancel an order" msgstr "Cancel an order" @@ -5991,7 +5991,7 @@ msgstr "Your transactions" msgid "If I swap $1 volume from EVM to Near L1, is the volume counted for my EVM wallet or my Near wallet?" msgstr "If I swap $1 volume from EVM to Near L1, is the volume counted for my EVM wallet or my Near wallet?" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Created" msgstr "Created" @@ -6035,8 +6035,8 @@ msgstr "Required:" msgid "Acknowledge" msgstr "Acknowledge" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx -#: src/components/swapv2/LimitOrder/ListOrder/ActionButtons.tsx +#: src/components/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ListOrder/ActionButtons.tsx #: src/components/WalletPopup/Transactions/index.tsx #: src/components/ZapCreatePool/CreatePoolModal.tsx #: src/hooks/useLogin.tsx @@ -6062,7 +6062,7 @@ msgid "Time to sign-in is Expired, please go back and try again." msgstr "Time to sign-in is Expired, please go back and try again." #: src/components/Announcement/PrivateAnnoucement/InboxItemPriceAlert.tsx -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx #: src/components/WalletPopup/Transactions/ContractAddress.tsx #: src/components/WalletPopup/Transactions/TransactionItem.tsx #: src/pages/NotificationCenter/CreateAlert/ConfirmModal.tsx @@ -6133,9 +6133,9 @@ msgstr "How often is the data updated?" msgid "Current Cycle" msgstr "Current Cycle" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx #: src/pages/Campaign/constants.tsx msgid "Place Order" msgstr "Place Order" @@ -6192,7 +6192,7 @@ msgstr "Total Value" msgid "Classic Pools" msgstr "Classic Pools" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "Your currently existing order is {filledPercent}% filled." msgstr "Your currently existing order is {filledPercent}% filled." @@ -6239,7 +6239,7 @@ msgstr "Pool Address:" msgid "External Call" msgstr "External Call" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Min" msgstr "Min" @@ -6271,7 +6271,7 @@ msgstr "Your position’s % earned fees so far, based on the amount of fee token msgid "No staked liquidity found. Check out our <0>Farms." msgstr "No staked liquidity found. Check out our <0>Farms." -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "Wrapping {amount} {inSymbol} to {amount} {wethSymbol}" msgstr "Wrapping {amount} {inSymbol} to {amount} {wethSymbol}" @@ -6279,7 +6279,7 @@ msgstr "Wrapping {amount} {inSymbol} to {amount} {wethSymbol}" msgid "Reposition" msgstr "Reposition" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "Edit Type" msgstr "Edit Type" @@ -6587,9 +6587,9 @@ msgstr "To learn more about how to add liquidity to KyberSwap Classic, view <0> msgid "Approve failed" msgstr "Approve failed" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "Learn more ↗︎" msgstr "Learn more ↗︎" @@ -6767,7 +6767,7 @@ msgid "Email Address" msgstr "Email Address" #: src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Order Expired" msgstr "Order Expired" @@ -6776,7 +6776,7 @@ msgstr "Order Expired" msgid "DIFFERENCE" msgstr "DIFFERENCE" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "You don't have any order history." msgstr "You don't have any order history." @@ -6810,7 +6810,7 @@ msgstr "Attention Item(s)" msgid "These Terms and Conditions should be read in conjunction with the KyberSwap <0>Terms of Use, which lay out the terms and conditions that apply to all KyberSwap activities." msgstr "These Terms and Conditions should be read in conjunction with the KyberSwap <0>Terms of Use, which lay out the terms and conditions that apply to all KyberSwap activities." -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx #: src/pages/Earns/components/SmartExit/Confirmation/MoreInfo.tsx msgid "Expires in" msgstr "Expires in" @@ -6869,7 +6869,7 @@ msgstr "Enter an amount" #: src/components/Header/web3/SelectWallet.tsx #: src/components/Menu/FaucetModal.tsx #: src/components/SwapForm/SwapActionButton/index.tsx -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx #: src/components/YieldPools/ElasticFarmGroup/buttons.tsx #: src/pages/Campaign/components/CampaignStats/NearIntentCampaignStats.tsx #: src/pages/Campaign/components/MyDashboard/NearIntentDashboard.tsx @@ -6924,11 +6924,11 @@ msgstr "You have successfully turned on MEV Protection Mode. All transactions on msgid "Current Market Price is {currentPrice} {token0Symbol} per {token1Symbol}" msgstr "Current Market Price is {currentPrice} {token0Symbol} per {token1Symbol}" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "Note: Your existing order will be automatically cancelled and a new order will be created." msgstr "Note: Your existing order will be automatically cancelled and a new order will be created." -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your order to pay {mainMsg} was successfully filled" msgstr "Your order to pay {mainMsg} was successfully filled" @@ -6998,7 +6998,7 @@ msgstr "Add MEV Protection to safeguard you from front-running attacks." msgid "Blacklisted Function" msgstr "Blacklisted Function" -#: src/components/swapv2/LimitOrder/ListOrder/TabSelector.tsx +#: src/components/LimitOrder/ListOrder/TabSelector.tsx msgid "Active Orders" msgstr "Active Orders" @@ -7115,8 +7115,8 @@ msgstr "FairFlow EG Rewards" msgid "EVM ↔ Solana L1" msgstr "EVM ↔ Solana L1" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "Review Order" msgstr "Review Order" @@ -7153,7 +7153,7 @@ msgstr "Signed out all accounts successfully" msgid "See here" msgstr "See here" -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "Order will be automatically cancelled in" msgstr "Order will be automatically cancelled in" @@ -7165,7 +7165,7 @@ msgstr "Step 2:" #~ msgid "Pool Fees" #~ msgstr "Pool Fees" -#: src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx +#: src/components/LimitOrder/useWarningCreateOrder.tsx msgid "We suggest you increase the value of your limit order to at least <0>${threshold}. This will increase the odds of your order being filled." msgstr "We suggest you increase the value of your limit order to at least <0>${threshold}. This will increase the odds of your order being filled." @@ -7228,7 +7228,7 @@ msgstr "Total Gas Refund" msgid "Reposition to new range" msgstr "Reposition to new range" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your order to pay {mainMsg} has expired{filledComponent}" msgstr "Your order to pay {mainMsg} has expired{filledComponent}" @@ -7236,7 +7236,7 @@ msgstr "Your order to pay {mainMsg} has expired{filledComponent}" #~ msgid "You can place limit orders, bridge tokens, or buy crypto with multiple payment options!" #~ msgstr "You can place limit orders, bridge tokens, or buy crypto with multiple payment options!" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Gasless Cancel" msgstr "Gasless Cancel" @@ -7297,7 +7297,7 @@ msgid "Clear Pending Transactions" msgstr "Clear Pending Transactions" #: src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Order Partially Filled" msgstr "Order Partially Filled" @@ -7350,7 +7350,7 @@ msgstr "Pools" msgid "Minimum Received" msgstr "Minimum Received" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "Cancel All" msgstr "Cancel All" @@ -7360,8 +7360,8 @@ msgstr "Cancel All" msgid "You can find the full list of eligible tokens <0>here" msgstr "You can find the full list of eligible tokens <0>here" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "I pay" msgstr "I pay" @@ -7381,7 +7381,7 @@ msgstr "<0><1>Price Impact is very high. You will lose funds!" msgid "Weekly reset: Product usage and bonus progress reset after the weekly event ends." msgstr "Weekly reset: Product usage and bonus progress reset after the weekly event ends." -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Order Cancel Failed" msgstr "Order Cancel Failed" @@ -7390,7 +7390,7 @@ msgstr "Order Cancel Failed" msgid "Degen mode is on. Be cautious!" msgstr "Degen mode is on. Be cautious!" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "Checking Allowance..." msgstr "Checking Allowance..." @@ -7505,7 +7505,7 @@ msgstr "Our simulation detects that {0} has {1}% fee on transfer, please check f msgid "Trade more to earn more points to climb the leaderboard - the higher your rank, the greater your rewards." msgstr "Trade more to earn more points to climb the leaderboard - the higher your rank, the greater your rewards." -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "You will need to wrap your {inSymbol} to {wrapSymbol} before you can place a limit order. Your tokens will be exchanged 1 to 1." msgstr "You will need to wrap your {inSymbol} to {wrapSymbol} before you can place a limit order. Your tokens will be exchanged 1 to 1." @@ -7616,7 +7616,7 @@ msgstr "Select a Chain" msgid "Go to <0>KyberSwap Cross-Chain feature." msgstr "Go to <0>KyberSwap Cross-Chain feature." -#: src/components/swapv2/LimitOrder/OrderBook/index.tsx +#: src/components/LimitOrder/OrderBook/index.tsx msgid "No orders." msgstr "No orders." @@ -7805,7 +7805,7 @@ msgstr "There is no maximum allocation for each eligible wallet." msgid "Campaigns" msgstr "Campaigns" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "Wrap {inSymbol}" msgstr "Wrap {inSymbol}" @@ -7817,7 +7817,7 @@ msgstr "Total LP Tokens" msgid "🏆 Rewards" msgstr "🏆 Rewards" -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "*There is a possibility that the order might be filled before cancellation." msgstr "*There is a possibility that the order might be filled before cancellation." @@ -7918,7 +7918,7 @@ msgstr "Sell Price" msgid "Cancel all orders" msgstr "Cancel all orders" -#: src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx +#: src/components/LimitOrder/useWarningCreateOrder.tsx msgid "Your limit order price is <0>{percentWithoutMinus} lower than the market. You will be selling your {0} exceedingly cheap." msgstr "Your limit order price is <0>{percentWithoutMinus} lower than the market. You will be selling your {0} exceedingly cheap." @@ -7930,7 +7930,7 @@ msgstr "Total Reward" #~ msgid "A cryptocurrency wallet gives you access to your digital tokens and acts as a gateway to many blockchain applications like KyberSwap. You can buy, store, send and swap tokens using this wallet.<0/><1/>On KyberSwap we support a list of wallets including: MetaMask, Coin98, Wallet Connect, Coinbase Wallet, Ledger and others." #~ msgstr "A cryptocurrency wallet gives you access to your digital tokens and acts as a gateway to many blockchain applications like KyberSwap. You can buy, store, send and swap tokens using this wallet.<0/><1/>On KyberSwap we support a list of wallets including: MetaMask, Coin98, Wallet Connect, Coinbase Wallet, Ledger and others." -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Cancel all orders failed. Please try again." msgstr "Cancel all orders failed. Please try again." @@ -7960,7 +7960,7 @@ msgstr "<0>Week 10 Sep 09 - Sep 15" msgid "Total Amount (USD)" msgstr "Total Amount (USD)" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "Wrapping" msgstr "Wrapping" @@ -8010,7 +8010,7 @@ msgstr "My Staked {0}" msgid "Attention" msgstr "Attention" -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx msgid "ACTION" msgstr "ACTION" @@ -8071,7 +8071,7 @@ msgstr "None of the liquidity position(s) held by your wallet ({0}) were affecte msgid "Switch Chain" msgstr "Switch Chain" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "Try Again" msgstr "Try Again" @@ -8256,7 +8256,7 @@ msgstr "KyberSwap provides tools for tracking & adding liquidity to third-party msgid "Price:" msgstr "Price:" -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "Order has been successfully cancelled." msgstr "Order has been successfully cancelled." @@ -8317,7 +8317,7 @@ msgstr "Note: {warningToken} is now <10% of the pool. Pool might become inactive msgid "Invalid wallet address" msgstr "Invalid wallet address" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "Expired Orders" msgstr "Expired Orders" @@ -8330,7 +8330,7 @@ msgstr "Value is updating" msgid "NFT Permit Error" msgstr "NFT Permit Error" -#: src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx +#: src/components/LimitOrder/useWarningCreateOrder.tsx msgid "Limit order price is >={BETTER_PRICE_DIFF_THRESHOLD}% higher than the market. We just want to make sure this is correct" msgstr "Limit order price is >={BETTER_PRICE_DIFF_THRESHOLD}% higher than the market. We just want to make sure this is correct" @@ -8350,7 +8350,7 @@ msgstr "Trade $50,000 from Arbitrum to Near L1 and Stable Pairs earns 125,000 po msgid "What is the First-Come, First-Served (FCFS) round?" msgstr "What is the First-Come, First-Served (FCFS) round?" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "I want to cancel my order where" msgstr "I want to cancel my order where" @@ -8452,7 +8452,7 @@ msgstr "In order to be eligible, you need to make a swap from KyberSwap Aggregat #~ msgid "Here's a quick tutorial guide about KyberSwap's main features. Do you wish to have a look?" #~ msgstr "Here's a quick tutorial guide about KyberSwap's main features. Do you wish to have a look?" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your orders below has expired:<0/>{listOrderName}" msgstr "Your orders below has expired:<0/>{listOrderName}" @@ -8549,7 +8549,7 @@ msgstr "Leaderboard" msgid "{conditionTime} is already met." msgstr "{conditionTime} is already met." -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your orders below was successfully filled:<0/>{listOrderName}" msgstr "Your orders below was successfully filled:<0/>{listOrderName}" @@ -8713,7 +8713,7 @@ msgstr "Verify" msgid "Output is estimated. If the price changes by more than {displaySlp}% your transaction will revert." msgstr "Output is estimated. If the price changes by more than {displaySlp}% your transaction will revert." -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx #: src/pages/Earns/components/SmartExit/Confirmation/MoreInfo.tsx #: src/pages/Earns/components/SmartExit/ExpireSetting.tsx msgid "Once an order expires, it will be cancelled automatically. No gas fees will be charged." @@ -8965,7 +8965,7 @@ msgstr "Swap via" msgid "Only successful (\"success\" status on explorer) transaction hash is counted." msgstr "Only successful (\"success\" status on explorer) transaction hash is counted." -#: src/components/swapv2/LimitOrder/helpers.ts +#: src/components/LimitOrder/helpers.ts msgid "You don't have sufficient fund for this transaction." msgstr "You don't have sufficient fund for this transaction." @@ -8989,7 +8989,7 @@ msgstr "Trade $50,000 between EVM Chains and Stable Pairs earns 50,000 points." msgid "🕑️ Timeline and Reward" msgstr "🕑️ Timeline and Reward" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "Order Placed" msgstr "Order Placed" @@ -8997,7 +8997,7 @@ msgstr "Order Placed" msgid "Click <0>Join Now on the kyberswap.com to participate." msgstr "Click <0>Join Now on the kyberswap.com to participate." -#: src/components/swapv2/LimitOrder/useValidateInputError.tsx +#: src/components/LimitOrder/useValidateInputError.tsx msgid "Invalid input amount" msgstr "Invalid input amount" @@ -9058,7 +9058,7 @@ msgstr "No Smart Exit orders yet" msgid "User Points: Points earned within the $100,000 volume cap" msgstr "User Points: Points earned within the $100,000 volume cap" -#: src/components/swapv2/LimitOrder/ListOrder/ActionButtons.tsx +#: src/components/LimitOrder/ListOrder/ActionButtons.tsx msgid "Copy Txn Hash" msgstr "Copy Txn Hash" @@ -9097,7 +9097,7 @@ msgstr "Click <0>Join Now to participate." msgid "LM Reward:" msgstr "LM Reward:" -#: src/components/swapv2/LimitOrder/ListOrder/TabSelector.tsx +#: src/components/LimitOrder/ListOrder/TabSelector.tsx msgid "Order History" msgstr "Order History" @@ -9151,7 +9151,7 @@ msgstr "Sell" msgid "Your KIP Voting Power" msgstr "Your KIP Voting Power" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "All Closed Orders" msgstr "All Closed Orders" @@ -9171,7 +9171,7 @@ msgstr "Claim Ended" msgid "Smart Exit created" msgstr "Smart Exit created" -#: src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx +#: src/components/LimitOrder/ListLimitOrder/TabSelector.tsx msgid "You have {numberOfInsufficientFundOrders} active orders that don't have sufficient funds." msgstr "You have {numberOfInsufficientFundOrders} active orders that don't have sufficient funds." @@ -9203,7 +9203,7 @@ msgstr "Calculate the absolute numerical difference." msgid "Points are earned each time a user swap eligible tokens on KyberSwap Aggregator API. Eligible tokens are indexed in 4 different categories, giving different amount of points per USD swapped. Eligible tokens can be found on <0>this list" msgstr "Points are earned each time a user swap eligible tokens on KyberSwap Aggregator API. Eligible tokens are indexed in 4 different categories, giving different amount of points per USD swapped. Eligible tokens can be found on <0>this list" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "All Active Orders" msgstr "All Active Orders" @@ -9322,7 +9322,7 @@ msgstr "Each address can participate across multiple weeks, but can only claim a #~ msgid "Add a new position" #~ msgstr "Add a new position" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "This order is not supported gasless cancel. Because it was created by our old contract" msgstr "This order is not supported gasless cancel. Because it was created by our old contract" @@ -9330,8 +9330,8 @@ msgstr "This order is not supported gasless cancel. Because it was created by ou #: src/components/Announcement/Popups/CtaButton.tsx #: src/components/Announcement/Popups/DetailAnnouncementPopup.tsx #: src/components/ElasticHackedModal.tsx -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx #: src/components/TransactionConfirmationModal/index.tsx #: src/pages/Campaign/components/RaffleRewardModal.tsx #: src/pages/Earns/UserPositions/PositionBanner.tsx @@ -9396,7 +9396,7 @@ msgstr "Total Points: Combined points from all participants" msgid "Claim Rewards" msgstr "Claim Rewards" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Filled" msgstr "Filled" @@ -9449,7 +9449,7 @@ msgid "Contract Security" msgstr "Contract Security" #: src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Order Filled" msgstr "Order Filled" diff --git a/apps/kyberswap-interface/src/locales/zh-CN.po b/apps/kyberswap-interface/src/locales/zh-CN.po index e69716e9e1..7727b91180 100644 --- a/apps/kyberswap-interface/src/locales/zh-CN.po +++ b/apps/kyberswap-interface/src/locales/zh-CN.po @@ -34,7 +34,7 @@ msgstr "质押流动性" msgid "Please type the word <0>Confirm below to enable Degen Mode" msgstr "请在下方输入“Confirm”以启用 \"高风险\" 模式" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "You need to first allow KyberSwap smart contracts to use your {inSymbol}. This has to be done only once for each token." msgstr "您需要先允许 KyberSwap 的智能合约使用您的 {inSymbol}。每种代币只需进行一次授权。" @@ -70,7 +70,7 @@ msgstr "已更新" msgid "Position Status" msgstr "收益仓位" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "Open Orders" msgstr "未成交订单" @@ -116,8 +116,8 @@ msgstr "其他任意交易对" msgid "Exported profiles will not be associated with your wallet. Your export code is unique. Learn more about profile <0>here." msgstr "导出的配置文件不会与您的钱包关联。您的导出码是唯一的。<0>点击此处了解更多" -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx -#: src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/OrderBook/TableHeader.tsx msgid "RATE" msgstr "汇率" @@ -228,8 +228,8 @@ msgstr "无法切换网络,请在您的钱包中尝试切换。" msgid "Which activities earn points?" msgstr "" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "Placing order" msgstr "正在下单" @@ -369,7 +369,7 @@ msgstr "示例:ARB <> USDC;ETH <> ARB;PENDLE <> ARB" msgid "No hidden fees - Your optional tips support {clientName}!" msgstr "无隐藏费用——您的自愿打赏将支持 {clientName}!" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Hard Cancel" msgstr "强制取消" @@ -436,7 +436,7 @@ msgid "An error occurred. Invalid Permit Signature." msgstr "发生错误:许可签名无效" #: src/components/SwapForm/SwapActionButton/index.tsx -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "Switch to {0}" msgstr "切换至 {0}" @@ -512,7 +512,7 @@ msgstr "稳定交易对:" msgid "USD stablecoins equivalent to 60% of the Reference Value of Lost Affected Assets contributed from such Affected Address, vested continuously on a linear basis over 3 months." msgstr "向该受影响地址发放相当于受影响资产参考价值 60% 的美元稳定币,并在 3 个月内按线性方式持续归属。" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "<0>{0} {makerAssetSymbol} and receive <1>{1} {takerAssetSymbol} <2>at {takerAssetSymbol} price of {rate} {makerAssetSymbol}" msgstr "<0>{0} {makerAssetSymbol} 并接收 <1>{1} {takerAssetSymbol} <2>按 {rate} {makerAssetSymbol} 的 {takerAssetSymbol} 价格" @@ -578,7 +578,7 @@ msgstr "未知错误" #~ msgid "Switch Profile" #~ msgstr "切换配置文件" -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "Canceling order" msgstr "取消订单中" @@ -631,7 +631,7 @@ msgstr "" msgid "TOTAL AMOUNT (USD)" msgstr "总金额(美元)" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "Review your order" msgstr "检查您的订单" @@ -724,7 +724,7 @@ msgstr "当前奖励基于您的当前排名。详情请查看“信息”页签 msgid "Error occur, please try again" msgstr "发生错误,请重试" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Bulk Cancellation" msgstr "批量取消" @@ -828,8 +828,8 @@ msgstr "选择将收益复投到该仓位或发送至钱包" msgid "Get notified via Telegram when this position moves out of range or back in range" msgstr "当仓位进出价格区间时通过 Telegram 通知我" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "and receive" msgstr "并接收" @@ -933,7 +933,7 @@ msgstr "跨链路由来源" msgid "If you miss the claiming deadline, your eligibility will expire and the reward will no longer be available." msgstr "" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Are you sure you want to cancel {0} limit orders?" msgstr "确认要取消 {0} 个限价单吗?" @@ -1035,7 +1035,7 @@ msgstr "交易记录" msgid "Notification" msgstr "通知" -#: src/components/swapv2/LimitOrder/DeltaRate.tsx +#: src/components/LimitOrder/DeltaRate.tsx msgid "Your selected price is {styledPercent} better than the current market price." msgstr "您选择的价格比当前市场价好 {styledPercent}" @@ -1108,7 +1108,7 @@ msgstr "您已成功导入该配置文件,并以访客账号登录" msgid "Automatically remove liquidity from this position when your pre-set rice, time, or fee yield condition(s)." msgstr "" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Cancel order to pay {mainMsg} failed" msgstr "取消订单并支付 {mainMsg} 失败" @@ -1167,7 +1167,7 @@ msgstr "数量无效" msgid "Overview" msgstr "概览" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Insufficient {0} balance for order execution." msgstr "{0} 余额不足,无法执行订单" @@ -1188,7 +1188,7 @@ msgstr "导入资金池" msgid "Due to a <0><1>potential issue with our legacy Elastic protocol, we recommend that all liquidity providers withdraw their liquidity from Elastic Pools (Legacy). We have fixed all the issues and deployed the new and audited <2>{0} where you can add liquidity normally instead." msgstr "由于旧版 Elastic 协议存在潜在问题,建议从旧池中移除流动性,并使用全新审计的 <2>{0}" -#: src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx +#: src/components/LimitOrder/ListLimitOrder/TabSelector.tsx msgid "My Order(s)" msgstr "我的订单" @@ -1226,7 +1226,7 @@ msgstr "我的资金池导航教程" msgid "The actual gas cost will be deducted from your outputs when the order executes." msgstr "" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your orders below have successfully cancelled:<0/>{listOrderName}" msgstr "以下订单已成功取消:<0/>{listOrderName}" @@ -1254,7 +1254,7 @@ msgstr "" msgid "Choose Pool Pair" msgstr "选择池交易对" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Hour" msgstr "小时" @@ -1497,7 +1497,7 @@ msgstr "Gas 退款何时可领取?" msgid "These Terms and Conditions <0>(\"Terms\") should be read in conjunction with the KyberSwap Terms of Use, which lay out the terms and conditions that apply to all KyberSwap promotional activities (\"Campaign\")." msgstr "这些条款与细则 <0>(“条款”) 应与 KyberSwap 使用条款一并阅读,后者规定了适用于所有 KyberSwap 推广活动(“活动”)的条款与条件。" -#: src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx +#: src/components/LimitOrder/useWarningCreateOrder.tsx msgid "Your current allowance is insufficient. Approve an additional {0} {1} to proceed." msgstr "当前授权额度不足,请额外授权 {0} {1}" @@ -1578,7 +1578,7 @@ msgstr "正在领取 {rewardAmounts} KNC" msgid "Routed via" msgstr "" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "Partially Filled Orders" msgstr "部分成交订单" @@ -1596,7 +1596,7 @@ msgstr "预计因交易规模导致的价格变化" msgid "Vote on current epoch proposals to get your full reward." msgstr "对当前 Epoch 提案投票以获得完整奖励" -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx msgid "CREATED | EXPIRY" msgstr "创建 | 到期" @@ -1615,7 +1615,7 @@ msgstr "投票结束于:" msgid "KNC Staked" msgstr "已质押 KNC" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Hard Cancel All Orders" msgstr "强制取消所有订单" @@ -1624,7 +1624,7 @@ msgid "🏆 Prize: {0} KNC" msgstr "🏆 奖励:{0} KNC" #: src/components/SwapForm/hooks/useGetInputError.tsx -#: src/components/swapv2/LimitOrder/useValidateInputError.tsx +#: src/components/LimitOrder/useValidateInputError.tsx msgid "Insufficient {symbol} balance" msgstr "{symbol} 余额不足" @@ -1654,7 +1654,7 @@ msgstr "领取奖励" msgid "Merkl Bonus" msgstr "" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "You have successfully cancelled an order to pay {mainMsg}{filledComponent}" msgstr "您已成功取消支付 {mainMsg}{filledComponent} 的订单" @@ -1671,7 +1671,7 @@ msgstr "KyberSwap 指南" msgid "Total Amount (USDC)" msgstr "总金额(USDC)" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Once you add {0}, the order will be executed at <0>{1}% below the market price." msgstr "添加 {0} 后,订单将以低于市价 <0>{1}% 执行" @@ -1705,7 +1705,7 @@ msgstr "需先给予 KyberSwap 合约 24 小时临时授权以使用您的 {0} msgid "To learn more about how to increase liquidity to KyberSwap Elastic, view <0> here" msgstr "了解如何增加 KyberSwap Elastic 流动性 <0>点击这里" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "This chain is not supported gasless cancel. It's coming soon." msgstr "该链暂不支持免 Gas 取消,敬请期待" @@ -1729,7 +1729,7 @@ msgstr "连接钱包以查看通知" #~ msgid "{0}Skip" #~ msgstr "{0} 跳过" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Note: Your currently existing order is {percent}% filled" msgstr "注意:当前订单已成交 {percent}%" @@ -1740,11 +1740,11 @@ msgstr "注意:当前订单已成交 {percent}%" msgid "In-Progress" msgstr "进行中" -#: src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx +#: src/components/LimitOrder/ListLimitOrder/TabSelector.tsx msgid "Open Limit Orders" msgstr "开放的限价单" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "Search by token symbol or token address" msgstr "按代币符号或地址搜索" @@ -1822,7 +1822,7 @@ msgstr "生成推荐链接" msgid "(ii) holds a licence issued by MAS for the provision of, or is authorised by MAS to provide, any service relating to tokens (whether digital payment tokens under the Payment Services Act of Singapore or digital tokens under the Financial Markets Services Act of Singapore)." msgstr "(ii)持有或获 MAS 授权提供代币相关服务" -#: src/components/swapv2/LimitOrder/DeltaRate.tsx +#: src/components/LimitOrder/DeltaRate.tsx msgid "Sell {symbol} at rate" msgstr "按汇率卖出 {symbol}" @@ -1862,7 +1862,7 @@ msgstr "自 6 月 9 日 00:00 UTC 起,您可以在“我的仪表板”页面 msgid "Total Balance" msgstr "总余额" -#: src/components/swapv2/LimitOrder/useValidateInputError.tsx +#: src/components/LimitOrder/useValidateInputError.tsx msgid "Your output amount is invalid." msgstr "输出金额无效" @@ -1936,7 +1936,7 @@ msgstr "前往我的资金池" #~ msgid "Max:" #~ msgstr "最大值:" -#: src/components/swapv2/LimitOrder/TradePrice.tsx +#: src/components/LimitOrder/TradePrice.tsx msgid "Unable to get the market price" msgstr "无法获取市场价格" @@ -2055,7 +2055,7 @@ msgstr "" msgid "Yes. We only count the first 50 eligible hashes per wallet." msgstr "是的。每个钱包只计算前 50 个合格哈希。" -#: src/components/swapv2/LimitOrder/Modals/styled.tsx +#: src/components/LimitOrder/Modals/styled.tsx msgid "Est. Market Price" msgstr "预估市场价" @@ -2064,7 +2064,7 @@ msgstr "预估市场价" msgid "<0>Slippage<1>is high. Your transaction may be front-run" msgstr "<0>滑点<1>过高,交易可能被抢跑" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "Cancelled Orders" msgstr "已取消订单" @@ -2169,7 +2169,7 @@ msgid "What are the different categories and how does it work?" msgstr "有哪些不同的类别?它们如何运作?" #: src/components/SwapForm/SwapActionButton/SwapButtonWithPriceImpact.tsx -#: src/components/swapv2/LimitOrder/TradePrice.tsx +#: src/components/LimitOrder/TradePrice.tsx #: src/components/swapv2/TradePrice.tsx msgid "Calculating" msgstr "计算中" @@ -2178,7 +2178,7 @@ msgstr "计算中" msgid "Removing a Smart Exit" msgstr "" -#: src/components/swapv2/LimitOrder/DeltaRate.tsx +#: src/components/LimitOrder/DeltaRate.tsx msgid "Your selected price is {styledPercent} worse than the current market price." msgstr "您选择的价格比当前市场价差 {styledPercent}" @@ -2269,7 +2269,7 @@ msgstr "重新考虑" msgid "Multichain team ceased operations, and we discourage user interaction with the deployed Wrapped KNC token contracts on various chains. See more <0>here" msgstr "Multichain 团队已停止运营,请避免与 Wrapped KNC 合约交互 <0>了解更多" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "No orders found." msgstr "未找到订单" @@ -2277,7 +2277,7 @@ msgstr "未找到订单" #~ msgid "Expert" #~ msgstr "专家模式" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "Hard Cancel Instead" msgstr "改为强制取消" @@ -2305,7 +2305,7 @@ msgstr "我们将基于以下条件监控价格并发送提醒" msgid "Claim threshold" msgstr "领取阈值" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "Est. Market Price:" msgstr "预估市场价:" @@ -2457,7 +2457,7 @@ msgstr "" msgid "Failed to switch network" msgstr "切换网络失败" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "You don't have any open orders yet." msgstr "您尚无任何未完成订单" @@ -2506,7 +2506,7 @@ msgstr "过去 7 天手续费最高的前 100 个资金池" msgid "TVL" msgstr "TVL总锁仓价值" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "Cancel without paying gas." msgstr "无需 Gas 取消" @@ -2564,7 +2564,7 @@ msgstr "" msgid "Smart Exit executed" msgstr "" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Gasless Cancel All Orders" msgstr "免 Gas 取消全部订单" @@ -2711,7 +2711,7 @@ msgstr "价格提醒" msgid "My Positions" msgstr "我的仓位" -#: src/components/swapv2/LimitOrder/helpers.ts +#: src/components/LimitOrder/helpers.ts msgid "User denied message signature" msgstr "用户拒绝签名" @@ -2719,7 +2719,7 @@ msgstr "用户拒绝签名" msgid "→ Hash 1 is chosen for promotional rewards." msgstr "→ 选择哈希 1 作为推广奖励。" -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "You have successfully cancelled all orders." msgstr "您已成功取消所有订单" @@ -2773,7 +2773,7 @@ msgstr "交易" msgid "No price alerts created yet" msgstr "尚未创建任何价格提醒" -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "Your request has timed out." msgstr "请求超时" @@ -2867,8 +2867,8 @@ msgstr "交易没有最低或最高金额要求。" msgid "Past Actions" msgstr "" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "Confirm Price" msgstr "确认价格" @@ -3070,7 +3070,7 @@ msgstr "显示更多详情" msgid "Mark all read" msgstr "全部标记为已读" -#: src/components/swapv2/LimitOrder/OrderBook/index.tsx +#: src/components/LimitOrder/OrderBook/index.tsx msgid "Orders refresh in" msgstr "订单刷新于" @@ -3189,11 +3189,11 @@ msgstr "" msgid "Checking data" msgstr "检查数据中" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "You Sell" msgstr "您卖出" -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx msgid "FILLED % | STATUS" msgstr "成交率 | 状态" @@ -3250,7 +3250,7 @@ msgstr "已质押 LP 代币" msgid "Claiming" msgstr "领取中" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "<0/> Cancellation may not be instant. <1>Learn more ↗︎" msgstr "<0/> 取消可能不会立即生效 <1>了解更多 ↗︎" @@ -3264,7 +3264,7 @@ msgstr "浏览流动性池以开始" #: src/components/Header/index.tsx #: src/components/Menu/index.tsx -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "Market" msgstr "市场" @@ -3395,7 +3395,7 @@ msgstr "预计奖励" msgid "Review the Cross-chain Swap" msgstr "审查跨链兑换" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "insufficient funds" msgstr "资金不足" @@ -3403,7 +3403,7 @@ msgstr "资金不足" msgid "Expired" msgstr "已过期" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Default Options" msgstr "默认选项" @@ -3539,8 +3539,8 @@ msgstr "成交量按照在 <0>目标链 上收到的代币价值计算,并 msgid "All Time High" msgstr "历史最高价" -#: src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx -#: src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx +#: src/components/LimitOrder/OrderBook/TableHeader.tsx +#: src/components/LimitOrder/OrderBook/TableHeader.tsx #: src/pages/CrossChainSwap/components/TransactionHistory.tsx msgid "AMOUNT" msgstr "金额" @@ -3670,7 +3670,7 @@ msgstr "" msgid "Token is not available" msgstr "代币不可用" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Set" msgstr "设置" @@ -3691,7 +3691,7 @@ msgstr "其他" msgid "Claim Asset" msgstr "领取资产" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Customize the Expiry Time" msgstr "自定义过期时间" @@ -3826,7 +3826,7 @@ msgstr "授权 <0>{0} 需大于 <1>{1} {2},了解更多 <2>这里" #~ msgid "Withdraw your liquidity positions (i.e. your NFT tokens) from the farming contract." #~ msgstr "从 Farming 合约中提取您的流动性仓位(NFT)" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Cancel Order" msgstr "取消订单" @@ -3906,7 +3906,7 @@ msgstr "您将很快收到 {amount} {tokenSymbol}!" msgid "Total Available Rewards" msgstr "可领取总奖励" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "Filled Orders" msgstr "已成交订单" @@ -4036,7 +4036,7 @@ msgstr "所有链上的 Swap 是否都支持 Gas 返还?" msgid "As a referrer, when someone you referred earns ARB on a trade made on KyberSwap.com, you get 10% of their rewards allocation." msgstr "作为推荐人,当您推荐的用户在 KyberSwap.com 上交易并获得 ARB 奖励时,您将得到其奖励分配的 10%。" -#: src/components/swapv2/LimitOrder/useValidateInputError.tsx +#: src/components/LimitOrder/useValidateInputError.tsx #: src/components/WalletPopup/SendToken/index.tsx msgid "Your input amount is invalid." msgstr "输入金额无效" @@ -4132,7 +4132,7 @@ msgstr "授权错误" #~ msgid "empty" #~ msgstr "空" -#: src/components/swapv2/LimitOrder/DeltaRate.tsx +#: src/components/LimitOrder/DeltaRate.tsx msgid "Buy {symbol} at rate" msgstr "以该价格买入 {symbol}" @@ -4247,7 +4247,7 @@ msgstr "KyberSwap 保留取消任何被发现存在刷量、女巫攻击、闪 msgid "<0>Week 5 Aug 05 - Aug 11" msgstr "<0>第 5 周 8 月 5 日 - 8 月 11 日" -#: src/components/swapv2/LimitOrder/helpers.ts +#: src/components/LimitOrder/helpers.ts msgid "Invalid signature" msgstr "签名无效" @@ -4286,7 +4286,7 @@ msgstr "倒计时结束后可领取的奖励" msgid "Stablecoins to Stablecoins trading will give 0.5 Points per USD swapped." msgstr "稳定币之间的交易每兑换 1 美元可获得 0.5 积分。" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "Edit immediately by paying {gasAmountDisplay} gas fees." msgstr "立即编辑并支付 {gasAmountDisplay} Gas 费" @@ -4307,7 +4307,7 @@ msgstr "距离开始还有" msgid "KyberSwap reserves the right to shorten, extend, suspend, or terminate the Campaign at any time, at its sole discretion." msgstr "KyberSwap 有权自行决定随时缩短、延长、暂停或终止本活动。" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Partially Filled" msgstr "部分成交" @@ -4363,7 +4363,7 @@ msgstr "" msgid "Use any 2 different products: +20 points" msgstr "" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Order will Expire on" msgstr "订单将于以下时间到期" @@ -4799,7 +4799,7 @@ msgstr "处理中" msgid "Affected Assets taken from Affected Pools by subsequent activity (“Category 2 MBA”) of two mimicking bots mimicking the Primary Exploit, which Affected Assets have yet to be recovered" msgstr "两名模仿主攻击的机器人后续活动(“类别 2 MBA”)从受影响池中取走的受影响资产尚未追回。" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your order was {filledPercent}% filled" msgstr "您的订单已成交 {filledPercent}%" @@ -4831,7 +4831,7 @@ msgstr "仅领取" msgid "WALLET" msgstr "钱包" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "You Buy" msgstr "您买入" @@ -4872,8 +4872,8 @@ msgstr "" #: src/components/Header/groups/SwapNavGroup.tsx #: src/components/Menu/index.tsx #: src/components/SwapForm/PriceImpactNote.tsx -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx #: src/pages/Campaign/MyDashboard.tsx #: src/pages/SwapV3/Tabs/LimitTab.tsx msgid "Limit Order" @@ -4913,8 +4913,8 @@ msgstr "验证您的邮箱地址" msgid "Connect wallet" msgstr "连接钱包" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "at" msgstr "在" @@ -4940,7 +4940,7 @@ msgstr "不涉及任何机会、随机性或赌博成分。" msgid "Coming Soon" msgstr "即将上线" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "before the order expires on" msgstr "在订单到期前" @@ -4994,7 +4994,7 @@ msgstr "发生错误" msgid "To be eligible, you must make a swap on <0>KyberSwap.com using trading pairs composed of eligible tokens from the list, excluding WETH-ETH, WETH-USDC, and ETH-USDC." msgstr "要符合资格,您必须在 <0>KyberSwap.com 上使用列表中的合资格代币交易对进行兑换,但不包括 WETH-ETH、WETH-USDC 和 ETH-USDC。" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your order to pay {mainMsg} is {filledPercent}% filled" msgstr "您用于支付 {mainMsg} 的订单已成交 {filledPercent}%" @@ -5113,7 +5113,7 @@ msgstr "最大为 {format}" msgid "You can <0>choose Grant Option once, please read and decide carefully" msgstr "您<0>只能选择一次资助选项,请仔细阅读并谨慎决定" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Gasless Cancel {0}/{1} Orders" msgstr "免 Gas 取消 {0}/{1} 个订单" @@ -5169,7 +5169,7 @@ msgstr "保存中……" msgid "Invalid email address" msgstr "无效的邮箱地址" -#: src/components/swapv2/LimitOrder/useValidateInputError.tsx +#: src/components/LimitOrder/useValidateInputError.tsx msgid "Insufficient {0} balance.<0/><1>{1}{formatNum} {2} remaining after deducting Active and Open orders." msgstr "{0} 余额不足。扣除进行中和未完成订单后剩余 <1>{1}{formatNum} {2}" @@ -5189,7 +5189,7 @@ msgstr "— 由 Blink 提供支持,防止抢跑攻击并提升交易体验" msgid "Claiming rewards" msgstr "领取奖励中" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Are you sure you want to cancel this limit order?" msgstr "确定要取消该限价单吗?" @@ -5202,7 +5202,7 @@ msgstr "验证码错误或已过期,请重试" msgid "Vesting" msgstr "归属中" -#: src/components/swapv2/LimitOrder/Modals/styled.tsx +#: src/components/LimitOrder/Modals/styled.tsx msgid "{0} price of {rateStr} {1}" msgstr "{1} 的 {0} 价格为 {rateStr}" @@ -5257,7 +5257,7 @@ msgstr "保存中……" #~ msgid "Suitable for stablecoin or stable correlated pairs. Anticipating price to fluctuate within ~0.6%. You can earn fees even if the price goes up by 0.3% or goes down by 0.3%." #~ msgstr "适用于稳定币或强相关交易对,预期价格波动约 ±0.6%。即使上涨 0.3% 或下跌 0.3% 仍可赚取手续费" -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Cancel Orders Failed" msgstr "取消订单失败" @@ -5353,7 +5353,7 @@ msgstr "正在授权…" msgid "For every $100 volume, participants earn points based on the following distribution:" msgstr "" -#: src/components/swapv2/LimitOrder/OrderBook/TableHeader.tsx +#: src/components/LimitOrder/OrderBook/TableHeader.tsx msgid "ORDER STATUS" msgstr "订单状态" @@ -5402,7 +5402,7 @@ msgstr "价差" msgid "See All" msgstr "查看全部" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "You have successfully placed an order to pay <0>{0} {1} and receive <1>{2} {3} <2>at {4} price of {5} {6}." msgstr "您已成功下单,支付 <0>{0} {1} 并接收 <1>{2} {3}<2>,成交价为 {4},价格为 {5} {6}" @@ -5460,7 +5460,7 @@ msgstr "未找到通知" msgid "<0>Your <1>Slippage<2> {msg}" msgstr "<0>您的 <1>滑点<2> {msg}" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Cancel Orders" msgstr "取消订单" @@ -5645,7 +5645,7 @@ msgstr "<0>第 1 周 5 月 19 日 - 5 月 25 日" msgid "Protection safeguards you from front-running attacks on {chainName}. We recommend using" msgstr "该保护机制可在 {chainName} 上防止抢跑攻击,建议使用" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Expiry" msgstr "到期时间" @@ -5661,7 +5661,7 @@ msgstr "" msgid "Migrating {value} KNCL to KNC" msgstr "迁移 {value} KNCL 至 KNC" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "Cancel immediately by paying {gasAmountDisplay} gas fees." msgstr "支付 {gasAmountDisplay} Gas 费用可立即取消" @@ -5669,7 +5669,7 @@ msgstr "支付 {gasAmountDisplay} Gas 费用可立即取消" msgid "Add Condition 2" msgstr "" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your orders below cancel failed:<0/>{listOrderName}" msgstr "以下订单取消失败:<0/>{listOrderName}" @@ -5861,7 +5861,7 @@ msgstr "费用总额<0/>(美元)" #~ msgid "Get Started" #~ msgstr "开始" -#: src/components/swapv2/LimitOrder/ListOrder/useRequestCancelOrder.tsx +#: src/components/LimitOrder/ListOrder/useRequestCancelOrder.tsx msgid "Canceling your orders" msgstr "取消您的订单中" @@ -5878,12 +5878,12 @@ msgstr "交易获得积分没有最低或最高金额限制。" msgid "Search for a liquidity source" msgstr "搜索流动性来源" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Order will trigger on" msgstr "" -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx msgid "LIMIT ORDER(S)" msgstr "限价单" @@ -5958,7 +5958,7 @@ msgstr "<0>第 9 周 9 月 2 日 - 9 月 8 日" msgid "Step" msgstr "步骤" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Cancel an order" msgstr "取消订单" @@ -5991,7 +5991,7 @@ msgstr "您的交易" msgid "If I swap $1 volume from EVM to Near L1, is the volume counted for my EVM wallet or my Near wallet?" msgstr "如果我从 EVM 向 Near L1 兑换 1 美元,交易量算在 EVM 钱包还是 Near 钱包?" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Created" msgstr "已创建" @@ -6035,8 +6035,8 @@ msgstr "必需:" msgid "Acknowledge" msgstr "确认" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx -#: src/components/swapv2/LimitOrder/ListOrder/ActionButtons.tsx +#: src/components/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ListOrder/ActionButtons.tsx #: src/components/WalletPopup/Transactions/index.tsx #: src/components/ZapCreatePool/CreatePoolModal.tsx #: src/hooks/useLogin.tsx @@ -6062,7 +6062,7 @@ msgid "Time to sign-in is Expired, please go back and try again." msgstr "登录时间已过期,请返回重试" #: src/components/Announcement/PrivateAnnoucement/InboxItemPriceAlert.tsx -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx #: src/components/WalletPopup/Transactions/ContractAddress.tsx #: src/components/WalletPopup/Transactions/TransactionItem.tsx #: src/pages/NotificationCenter/CreateAlert/ConfirmModal.tsx @@ -6133,9 +6133,9 @@ msgstr "这些数据多久更新一次?" msgid "Current Cycle" msgstr "当前周期" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx #: src/pages/Campaign/constants.tsx msgid "Place Order" msgstr "下单" @@ -6192,7 +6192,7 @@ msgstr "总价值" msgid "Classic Pools" msgstr "经典池" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "Your currently existing order is {filledPercent}% filled." msgstr "您当前的订单已成交 {filledPercent}%" @@ -6239,7 +6239,7 @@ msgstr "" msgid "External Call" msgstr "外部调用" -#: src/components/swapv2/LimitOrder/ExpirePicker.tsx +#: src/components/LimitOrder/ExpirePicker.tsx msgid "Min" msgstr "最小" @@ -6271,7 +6271,7 @@ msgstr "" msgid "No staked liquidity found. Check out our <0>Farms." msgstr "未发现已质押流动性,查看 <0>农场" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "Wrapping {amount} {inSymbol} to {amount} {wethSymbol}" msgstr "将 {amount} {inSymbol} 包装为 {amount} {wethSymbol}" @@ -6279,7 +6279,7 @@ msgstr "将 {amount} {inSymbol} 包装为 {amount} {wethSymbol}" msgid "Reposition" msgstr "重新定位仓位" -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "Edit Type" msgstr "编辑类型" @@ -6587,9 +6587,9 @@ msgstr "了解如何向 KyberSwap Classic 添加流动性,请查看 <0>这里< msgid "Approve failed" msgstr "授权失败" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "Learn more ↗︎" msgstr "了解更多 ↗︎" @@ -6767,7 +6767,7 @@ msgid "Email Address" msgstr "邮箱地址" #: src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Order Expired" msgstr "订单已过期" @@ -6776,7 +6776,7 @@ msgstr "订单已过期" msgid "DIFFERENCE" msgstr "差值" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "You don't have any order history." msgstr "您暂无订单历史" @@ -6810,7 +6810,7 @@ msgstr "注意事项" msgid "These Terms and Conditions should be read in conjunction with the KyberSwap <0>Terms of Use, which lay out the terms and conditions that apply to all KyberSwap activities." msgstr "本条款需结合 KyberSwap <0>使用条款 一并阅读,后者规定了适用于所有 KyberSwap 活动的条款与条件。" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx #: src/pages/Earns/components/SmartExit/Confirmation/MoreInfo.tsx msgid "Expires in" msgstr "剩余有效期" @@ -6869,7 +6869,7 @@ msgstr "请输入金额" #: src/components/Header/web3/SelectWallet.tsx #: src/components/Menu/FaucetModal.tsx #: src/components/SwapForm/SwapActionButton/index.tsx -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx #: src/components/YieldPools/ElasticFarmGroup/buttons.tsx #: src/pages/Campaign/components/CampaignStats/NearIntentCampaignStats.tsx #: src/pages/Campaign/components/MyDashboard/NearIntentDashboard.tsx @@ -6924,11 +6924,11 @@ msgstr "您已成功开启 MEV 保护模式,{chainName} 上的所有交易将 msgid "Current Market Price is {currentPrice} {token0Symbol} per {token1Symbol}" msgstr "当前市场价为 {currentPrice} {token0Symbol}/{token1Symbol}" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "Note: Your existing order will be automatically cancelled and a new order will be created." msgstr "注意:您现有的订单将被自动取消并创建新订单" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your order to pay {mainMsg} was successfully filled" msgstr "您用于支付 {mainMsg} 的订单已成功成交" @@ -6998,7 +6998,7 @@ msgstr "开启 MEV 保护以防止抢跑攻击" msgid "Blacklisted Function" msgstr "黑名单功能" -#: src/components/swapv2/LimitOrder/ListOrder/TabSelector.tsx +#: src/components/LimitOrder/ListOrder/TabSelector.tsx msgid "Active Orders" msgstr "活跃订单" @@ -7115,8 +7115,8 @@ msgstr "" msgid "EVM ↔ Solana L1" msgstr "EVM ↔ Solana L1" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "Review Order" msgstr "审核订单" @@ -7153,7 +7153,7 @@ msgstr "已成功登出所有账户" msgid "See here" msgstr "查看这里" -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "Order will be automatically cancelled in" msgstr "订单将自动取消于" @@ -7165,7 +7165,7 @@ msgstr "步骤 2:" #~ msgid "Pool Fees" #~ msgstr "池手续费" -#: src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx +#: src/components/LimitOrder/useWarningCreateOrder.tsx msgid "We suggest you increase the value of your limit order to at least <0>${threshold}. This will increase the odds of your order being filled." msgstr "建议将限价单金额提高至至少 <0>${threshold} 以提高成交概率" @@ -7228,7 +7228,7 @@ msgstr "Gas 返还总额" msgid "Reposition to new range" msgstr "重新定位至新区间" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your order to pay {mainMsg} has expired{filledComponent}" msgstr "您用于支付 {mainMsg} 的订单已过期{filledComponent}" @@ -7236,7 +7236,7 @@ msgstr "您用于支付 {mainMsg} 的订单已过期{filledComponent}" #~ msgid "You can place limit orders, bridge tokens, or buy crypto with multiple payment options!" #~ msgstr "您可以提交限价单、跨链或使用多种支付方式购买加密资产" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "Gasless Cancel" msgstr "免 Gas 取消" @@ -7297,7 +7297,7 @@ msgid "Clear Pending Transactions" msgstr "清除待处理交易" #: src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Order Partially Filled" msgstr "订单部分成交" @@ -7350,7 +7350,7 @@ msgstr "流动性池" msgid "Minimum Received" msgstr "最少接收" -#: src/components/swapv2/LimitOrder/ListOrder/index.tsx +#: src/components/LimitOrder/ListOrder/index.tsx msgid "Cancel All" msgstr "全部取消" @@ -7360,8 +7360,8 @@ msgstr "全部取消" msgid "You can find the full list of eligible tokens <0>here" msgstr "可在<0>此处查看合资格代币的完整列表" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx -#: src/components/swapv2/LimitOrder/Modals/ConfirmOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/ConfirmOrderModal.tsx msgid "I pay" msgstr "我支付" @@ -7381,7 +7381,7 @@ msgstr "<0><1>价格影响 极高,您将损失资金" msgid "Weekly reset: Product usage and bonus progress reset after the weekly event ends." msgstr "" -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Order Cancel Failed" msgstr "取消订单失败" @@ -7390,7 +7390,7 @@ msgstr "取消订单失败" msgid "Degen mode is on. Be cautious!" msgstr "Degen 模式已开启,请谨慎" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "Checking Allowance..." msgstr "检查授权中…" @@ -7505,7 +7505,7 @@ msgstr "模拟检测到 {0} 存在 {1}% 转账手续费,请谨慎交易" msgid "Trade more to earn more points to climb the leaderboard - the higher your rank, the greater your rewards." msgstr "交易越多,积分越多,排名越高,奖励越丰厚。" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "You will need to wrap your {inSymbol} to {wrapSymbol} before you can place a limit order. Your tokens will be exchanged 1 to 1." msgstr "在下限价单前需将 {inSymbol} 包装为 {wrapSymbol},代币将按 1:1 兑换" @@ -7616,7 +7616,7 @@ msgstr "选择链" msgid "Go to <0>KyberSwap Cross-Chain feature." msgstr "前往 <0>KyberSwap 跨链 功能。" -#: src/components/swapv2/LimitOrder/OrderBook/index.tsx +#: src/components/LimitOrder/OrderBook/index.tsx msgid "No orders." msgstr "暂无订单" @@ -7805,7 +7805,7 @@ msgstr "每个合资格钱包没有最高分配额度。" msgid "Campaigns" msgstr "活动" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "Wrap {inSymbol}" msgstr "包装 {inSymbol}" @@ -7817,7 +7817,7 @@ msgstr "LP 代币总量" msgid "🏆 Rewards" msgstr "🏆 奖励" -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "*There is a possibility that the order might be filled before cancellation." msgstr "*订单可能在取消前被成交" @@ -7918,7 +7918,7 @@ msgstr "卖出价格" msgid "Cancel all orders" msgstr "取消所有订单" -#: src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx +#: src/components/LimitOrder/useWarningCreateOrder.tsx msgid "Your limit order price is <0>{percentWithoutMinus} lower than the market. You will be selling your {0} exceedingly cheap." msgstr "您的限价单价格比市价低 <0>{percentWithoutMinus},将以极低价格卖出 {0}" @@ -7930,7 +7930,7 @@ msgstr "" #~ msgid "A cryptocurrency wallet gives you access to your digital tokens and acts as a gateway to many blockchain applications like KyberSwap. You can buy, store, send and swap tokens using this wallet.<0/><1/>On KyberSwap we support a list of wallets including: MetaMask, Coin98, Wallet Connect, Coinbase Wallet, Ledger and others." #~ msgstr "加密钱包让您掌控数字代币,并成为进入 KyberSwap 等区块链应用的入口。通过钱包,您可以购买、存储、发送和兑换代币。<0/><1/>KyberSwap 支持的部分钱包包括:MetaMask、Coin98、WalletConnect、Coinbase Wallet、Ledger 等。" -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Cancel all orders failed. Please try again." msgstr "取消所有订单失败,请重试" @@ -7960,7 +7960,7 @@ msgstr "<0>第 10 周 9 月 9 日 - 9 月 15 日" msgid "Total Amount (USD)" msgstr "总金额(美元)" -#: src/components/swapv2/LimitOrder/ActionButtonLimitOrder.tsx +#: src/components/LimitOrder/ActionButtonLimitOrder.tsx msgid "Wrapping" msgstr "包装中" @@ -8010,7 +8010,7 @@ msgstr "我已质押 {0}" msgid "Attention" msgstr "注意" -#: src/components/swapv2/LimitOrder/ListOrder/TableHeader.tsx +#: src/components/LimitOrder/ListOrder/TableHeader.tsx msgid "ACTION" msgstr "操作" @@ -8071,7 +8071,7 @@ msgstr "您的钱包({0})持有的流动性仓位均未受到此次攻击影 msgid "Switch Chain" msgstr "" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "Try Again" msgstr "重试" @@ -8256,7 +8256,7 @@ msgstr "KyberSwap 提供用于跟踪并向第三方协议添加流动性工具 msgid "Price:" msgstr "价格:" -#: src/components/swapv2/LimitOrder/Modals/CancelStatusCountDown.tsx +#: src/components/LimitOrder/Modals/CancelStatusCountDown.tsx msgid "Order has been successfully cancelled." msgstr "订单已成功取消" @@ -8317,7 +8317,7 @@ msgstr "注意:{warningToken} 已低于池中 10%,若降至 0% 池子可能 msgid "Invalid wallet address" msgstr "无效的钱包地址" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "Expired Orders" msgstr "已过期订单" @@ -8330,7 +8330,7 @@ msgstr "数值更新中" msgid "NFT Permit Error" msgstr "" -#: src/components/swapv2/LimitOrder/useWarningCreateOrder.tsx +#: src/components/LimitOrder/useWarningCreateOrder.tsx msgid "Limit order price is >={BETTER_PRICE_DIFF_THRESHOLD}% higher than the market. We just want to make sure this is correct" msgstr "限价单价格高于市价 ≥{BETTER_PRICE_DIFF_THRESHOLD}%,请确认是否正确" @@ -8350,7 +8350,7 @@ msgstr "从 Arbitrum 向 Near L1 的稳定交易对兑换 50,000 美元可获得 msgid "What is the First-Come, First-Served (FCFS) round?" msgstr "" -#: src/components/swapv2/LimitOrder/Modals/CancelOrderModal.tsx +#: src/components/LimitOrder/Modals/CancelOrderModal.tsx msgid "I want to cancel my order where" msgstr "我想取消我的订单,其中" @@ -8452,7 +8452,7 @@ msgstr "要符合资格,您需要通过 KyberSwap Aggregator API 进行兑换 #~ msgid "Here's a quick tutorial guide about KyberSwap's main features. Do you wish to have a look?" #~ msgstr "这是 KyberSwap 主要功能的快速指南,是否查看?" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your orders below has expired:<0/>{listOrderName}" msgstr "以下订单已过期:<0/>{listOrderName}" @@ -8549,7 +8549,7 @@ msgstr "排行榜" msgid "{conditionTime} is already met." msgstr "" -#: src/components/swapv2/LimitOrder/ListOrder/SummaryNotify.tsx +#: src/components/LimitOrder/ListOrder/SummaryNotify.tsx msgid "Your orders below was successfully filled:<0/>{listOrderName}" msgstr "以下订单已成功成交:<0/>{listOrderName}" @@ -8713,7 +8713,7 @@ msgstr "验证" msgid "Output is estimated. If the price changes by more than {displaySlp}% your transaction will revert." msgstr "输出为预估值,若价格变动超过 {displaySlp}% 交易将回滚" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx #: src/pages/Earns/components/SmartExit/Confirmation/MoreInfo.tsx #: src/pages/Earns/components/SmartExit/ExpireSetting.tsx msgid "Once an order expires, it will be cancelled automatically. No gas fees will be charged." @@ -8965,7 +8965,7 @@ msgstr "" msgid "Only successful (\"success\" status on explorer) transaction hash is counted." msgstr "仅计入成功(区块浏览器显示为“success”状态)的交易哈希。" -#: src/components/swapv2/LimitOrder/helpers.ts +#: src/components/LimitOrder/helpers.ts msgid "You don't have sufficient fund for this transaction." msgstr "余额不足,无法完成交易" @@ -8989,7 +8989,7 @@ msgstr "在 EVM 链之间的稳定交易对兑换 50,000 美元可获得 50,000 msgid "🕑️ Timeline and Reward" msgstr "🕑️ 时间线与奖励" -#: src/components/swapv2/LimitOrder/LimitOrderForm.tsx +#: src/components/LimitOrder/LimitOrderForm.tsx msgid "Order Placed" msgstr "订单已提交" @@ -8997,7 +8997,7 @@ msgstr "订单已提交" msgid "Click <0>Join Now on the kyberswap.com to participate." msgstr "在 kyberswap.com 点击 <0>Join Now 参与。" -#: src/components/swapv2/LimitOrder/useValidateInputError.tsx +#: src/components/LimitOrder/useValidateInputError.tsx msgid "Invalid input amount" msgstr "无效的输入金额" @@ -9058,7 +9058,7 @@ msgstr "" msgid "User Points: Points earned within the $100,000 volume cap" msgstr "用户积分:在 10 万美元交易量上限内获得的积分" -#: src/components/swapv2/LimitOrder/ListOrder/ActionButtons.tsx +#: src/components/LimitOrder/ListOrder/ActionButtons.tsx msgid "Copy Txn Hash" msgstr "复制交易哈希" @@ -9097,7 +9097,7 @@ msgstr "" msgid "LM Reward:" msgstr "LM 奖励:" -#: src/components/swapv2/LimitOrder/ListOrder/TabSelector.tsx +#: src/components/LimitOrder/ListOrder/TabSelector.tsx msgid "Order History" msgstr "订单历史" @@ -9151,7 +9151,7 @@ msgstr "卖出" msgid "Your KIP Voting Power" msgstr "您的 KIP 投票权" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "All Closed Orders" msgstr "所有已关闭订单" @@ -9171,7 +9171,7 @@ msgstr "" msgid "Smart Exit created" msgstr "" -#: src/components/swapv2/LimitOrder/ListLimitOrder/TabSelector.tsx +#: src/components/LimitOrder/ListLimitOrder/TabSelector.tsx msgid "You have {numberOfInsufficientFundOrders} active orders that don't have sufficient funds." msgstr "您有 {numberOfInsufficientFundOrders} 个资金不足的活跃订单" @@ -9203,7 +9203,7 @@ msgstr "计算绝对数值差。" msgid "Points are earned each time a user swap eligible tokens on KyberSwap Aggregator API. Eligible tokens are indexed in 4 different categories, giving different amount of points per USD swapped. Eligible tokens can be found on <0>this list" msgstr "每当用户通过 KyberSwap Aggregator API 兑换合资格代币时都会获得积分。合资格代币分为 4 个类别,每兑换 1 美元可获得不同积分。可在 <0>该列表 中查看合资格代币。" -#: src/components/swapv2/LimitOrder/const.ts +#: src/components/LimitOrder/const.ts msgid "All Active Orders" msgstr "所有活跃订单" @@ -9322,7 +9322,7 @@ msgstr "" #~ msgid "Add a new position" #~ msgstr "添加新仓位" -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx msgid "This order is not supported gasless cancel. Because it was created by our old contract" msgstr "该订单不支持免 Gas 取消(由旧合约创建)" @@ -9330,8 +9330,8 @@ msgstr "该订单不支持免 Gas 取消(由旧合约创建)" #: src/components/Announcement/Popups/CtaButton.tsx #: src/components/Announcement/Popups/DetailAnnouncementPopup.tsx #: src/components/ElasticHackedModal.tsx -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx -#: src/components/swapv2/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx +#: src/components/LimitOrder/Modals/CancelButtons.tsx #: src/components/TransactionConfirmationModal/index.tsx #: src/pages/Campaign/components/RaffleRewardModal.tsx #: src/pages/Earns/UserPositions/PositionBanner.tsx @@ -9396,7 +9396,7 @@ msgstr "总代积分:所有参与者的积分总和" msgid "Claim Rewards" msgstr "领取奖励" -#: src/components/swapv2/LimitOrder/ListOrder/OrderItem.tsx +#: src/components/LimitOrder/ListOrder/OrderItem.tsx msgid "Filled" msgstr "已成交" @@ -9449,7 +9449,7 @@ msgid "Contract Security" msgstr "合约安全" #: src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx -#: src/components/swapv2/LimitOrder/useNotificationLimitOrder.tsx +#: src/components/LimitOrder/useNotificationLimitOrder.tsx msgid "Order Filled" msgstr "订单已成交" diff --git a/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx b/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx index 79fb1b7f95..281df10671 100644 --- a/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx +++ b/apps/kyberswap-interface/src/pages/PartnerSwap/index.tsx @@ -8,8 +8,8 @@ import Banner from 'components/Banner' import SwapForm, { SwapFormProps } from 'components/SwapForm' import { SwitchLocaleLink } from 'components/SwitchLocaleLink' import { DEFAULT_TIP, TIP_LINK_CLIENT_ID, isCreatorNameValid } from 'components/TipLinkGeneratorModal/shared' -import LimitOrderForm from 'components/swapv2/LimitOrder/Form/LimitOrderForm' -import OrderList from 'components/swapv2/LimitOrder/OrderList' +import LimitOrderForm from 'components/LimitOrder/Form/LimitOrderForm' +import OrderList from 'components/LimitOrder/OrderList' import LiquiditySourcesPanel from 'components/swapv2/LiquiditySourcesPanel' import SettingsPanel from 'components/swapv2/SwapSettingsPanel' import useRequiredDegenMode from 'components/swapv2/SwapSettingsPanel/useRequiredDegenMode' diff --git a/apps/kyberswap-interface/src/pages/SwapV3/index.tsx b/apps/kyberswap-interface/src/pages/SwapV3/index.tsx index 241a8a718e..e91ba1e6eb 100644 --- a/apps/kyberswap-interface/src/pages/SwapV3/index.tsx +++ b/apps/kyberswap-interface/src/pages/SwapV3/index.tsx @@ -6,8 +6,8 @@ import { FarmingPoolBanner, TrendingPoolBanner } from 'components/EarnBanner' import { HStack, Stack } from 'components/Stack' import { SwitchLocaleLink } from 'components/SwitchLocaleLink' import { TutorialIds } from 'components/Tutorial/TutorialSwap/constant' -import LimitOrderForm from 'components/swapv2/LimitOrder/Form/LimitOrderForm' -import OrderList from 'components/swapv2/LimitOrder/OrderList' +import LimitOrderForm from 'components/LimitOrder/Form/LimitOrderForm' +import OrderList from 'components/LimitOrder/OrderList' import LiquiditySourcesPanel from 'components/swapv2/LiquiditySourcesPanel' import SettingsPanel from 'components/swapv2/SwapSettingsPanel' import useRequiredDegenMode from 'components/swapv2/SwapSettingsPanel/useRequiredDegenMode' diff --git a/apps/kyberswap-interface/src/services/limitOrder.ts b/apps/kyberswap-interface/src/services/limitOrder.ts index 242d5c029f..29e0e3df80 100644 --- a/apps/kyberswap-interface/src/services/limitOrder.ts +++ b/apps/kyberswap-interface/src/services/limitOrder.ts @@ -6,7 +6,7 @@ import { LimitOrder, LimitOrderFromTokenPair, LimitOrderStatus, -} from 'components/swapv2/LimitOrder/types' +} from 'components/LimitOrder/types' import { LIMIT_ORDER_API } from 'constants/env' import { RTK_QUERY_TAGS } from 'constants/index' diff --git a/apps/kyberswap-interface/src/utils/firebase.ts b/apps/kyberswap-interface/src/utils/firebase.ts index aab1b3122a..8cd9234936 100644 --- a/apps/kyberswap-interface/src/utils/firebase.ts +++ b/apps/kyberswap-interface/src/utils/firebase.ts @@ -3,7 +3,7 @@ import firebase from 'firebase/compat/app' import { Firestore, collection, doc, getFirestore, onSnapshot, query } from 'firebase/firestore' import { PopupContentAnnouncement } from 'components/Announcement/type' -import { LimitOrder } from 'components/swapv2/LimitOrder/types' +import { LimitOrder } from 'components/LimitOrder/types' import { ENV_KEY, ENV_LEVEL, FIREBASE } from 'constants/env' import { ENV_TYPE } from 'constants/type' From 717592bbe9e093eb8e47a02f05b2c5adfb3a5794 Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Fri, 19 Jun 2026 12:27:14 +0700 Subject: [PATCH 20/52] refactor(limit-order): consolidate processing modal --- .../InboxItemLimitOrder.tsx | 2 +- .../NotificationCenter/LimitOrder.tsx | 2 +- .../LimitOrder/Form/LimitOrderForm.tsx | 12 +- .../LimitOrder/Form/LimitOrderRateSection.tsx | 4 +- .../LimitOrder/Form/MarketPrice.tsx | 2 +- .../LimitOrder/Modals/CancelButtons.tsx | 4 +- .../LimitOrder/Modals/CancelOrderModal.tsx | 15 +- .../Modals/CancelStatusCountDown.tsx | 2 +- .../LimitOrder/Modals/ConfirmOrderModal.tsx | 16 +- .../Modals/ConfirmTakeOrderModal.tsx | 34 +++- .../Modals/ProcessingOrderModal.tsx | 171 +++++++++++------- .../Modals/ProcessingTakeOrderModal.tsx | 161 ----------------- .../LimitOrder/Modals/components.tsx | 2 +- .../components/LimitOrder/MyOrders/index.tsx | 6 +- .../MyOrders/useRequestCancelOrder.tsx | 6 +- .../LimitOrder/OrderBook/OrderItem.tsx | 4 +- .../components/LimitOrder/OrderBook/index.tsx | 2 +- .../components/LimitOrder/OrderList/index.tsx | 4 +- .../LimitOrder/hooks/useCreateLimitOrder.tsx | 10 +- .../hooks/useLimitOrderExecution.tsx | 20 +- .../hooks/useLimitOrderFormState.ts | 8 +- .../LimitOrder/hooks/useProcessingOrder.ts | 12 +- .../LimitOrder/hooks/useTakeLimitOrder.ts | 5 +- .../LimitOrder/hooks/useWrapEthStatus.ts | 4 +- .../SwapModal/ConfirmSwapModalContent.tsx | 6 +- .../WalletPopup/Transactions/Status.tsx | 2 +- .../Transactions/TransactionItem.tsx | 2 +- .../WalletPopup/Transactions/index.tsx | 2 +- .../src/pages/PartnerSwap/index.tsx | 4 +- .../src/pages/SwapV3/index.tsx | 4 +- .../src/services/limitOrder.ts | 7 +- 31 files changed, 204 insertions(+), 331 deletions(-) delete mode 100644 apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingTakeOrderModal.tsx diff --git a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx index 4ab20668b0..b06d1501a4 100644 --- a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/InboxItemLimitOrder.tsx @@ -21,8 +21,8 @@ import { } from 'components/Announcement/PrivateAnnoucement/styled' import { AnnouncementTemplateLimitOrder } from 'components/Announcement/type' import { CheckCircle } from 'components/Icons' -import { TokenLogoWithShadow } from 'components/Logo' import { LimitOrderStatus } from 'components/LimitOrder/types' +import { TokenLogoWithShadow } from 'components/Logo' import { APP_PATHS } from 'constants/index' import { NETWORKS_INFO } from 'constants/networks' import { useNavigateToUrl } from 'utils/redirect' diff --git a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx index 059b47c688..49b41bba1c 100644 --- a/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/Announcement/PrivateAnnoucement/NotificationCenter/LimitOrder.tsx @@ -6,8 +6,8 @@ import InboxIcon from 'components/Announcement/PrivateAnnoucement/Icon' import { PrivateAnnouncementPropCenter } from 'components/Announcement/PrivateAnnoucement/NotificationCenter' import { Desc, Time, Title, Wrapper } from 'components/Announcement/PrivateAnnoucement/NotificationCenter/styled' import { AnnouncementTemplateLimitOrder } from 'components/Announcement/type' -import Logo from 'components/Logo' import { LimitOrderStatus } from 'components/LimitOrder/types' +import Logo from 'components/Logo' import { APP_PATHS } from 'constants/index' import { formatTime } from 'utils/time' diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx index 6188d62841..bd2d153127 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx @@ -5,12 +5,8 @@ import { useNavigate } from 'react-router-dom' import { ButtonLight, ButtonPrimary, ButtonWarning } from 'components/Button' import DateTimePicker from 'components/DateTimePicker' -import { NetworkSelector } from 'components/NetworkSelector' -import { HStack, Stack } from 'components/Stack' import LimitOrderExpirySection from 'components/LimitOrder/Form/LimitOrderExpirySection' -import LimitOrderRateSection, { - useGetDeltaRateLimitOrder, -} from 'components/LimitOrder/Form/LimitOrderRateSection' +import LimitOrderRateSection, { useGetDeltaRateLimitOrder } from 'components/LimitOrder/Form/LimitOrderRateSection' import LimitOrderTokenSection from 'components/LimitOrder/Form/LimitOrderTokenSection' import MarketPrice from 'components/LimitOrder/Form/MarketPrice' import ConfirmOrderModal from 'components/LimitOrder/Modals/ConfirmOrderModal' @@ -20,6 +16,8 @@ import { useLimitOrderExecution } from 'components/LimitOrder/hooks/useLimitOrde import { useLimitOrderFormState } from 'components/LimitOrder/hooks/useLimitOrderFormState' import { useProcessingOrder } from 'components/LimitOrder/hooks/useProcessingOrder' import { LimitOrderTab } from 'components/LimitOrder/types' +import { NetworkSelector } from 'components/NetworkSelector' +import { HStack, Stack } from 'components/Stack' import { APP_PATHS } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { NETWORKS_INFO } from 'hooks/useChainsConfig' @@ -127,7 +125,6 @@ const LimitOrderForm = ({ currencyIn: currencyInProp, currencyOut: currencyOutPr onError: execution.handleError, onStart: review.closeReview, }) - const { dismiss: dismissProcessingOrder } = processing const viewCreatedOrder = useCallback(() => { const currencyPair = @@ -136,9 +133,8 @@ const LimitOrderForm = ({ currencyIn: currencyInProp, currencyOut: currencyOutPr : '' const search = new URLSearchParams({ tab: LimitOrderTab.MY_ORDER }).toString() - dismissProcessingOrder() navigate(`${APP_PATHS.LIMIT}/${form.networkInfo.route}${currencyPair}?${search}`) - }, [currencyIn, currencyOut, dismissProcessingOrder, form.chainId, form.networkInfo.route, navigate]) + }, [currencyIn, currencyOut, form.chainId, form.networkInfo.route, navigate]) const validationError = validation.inputError || validation.outputError const disableReviewButton = validation.isNotFillAllInput || !!validationError || balance.insufficientBalance diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderRateSection.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderRateSection.tsx index 57330ad5b0..2c697fda31 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderRateSection.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderRateSection.tsx @@ -3,10 +3,10 @@ import { Trans, t } from '@lingui/macro' import { useEffect, useMemo, useState } from 'react' import InfoHelper from 'components/InfoHelper' -import NumericalInput from 'components/NumericalInput' -import { Stack } from 'components/Stack' import { removeTrailingZero } from 'components/LimitOrder/helpers' import { DeltaRateLimitOrder, RateInfo } from 'components/LimitOrder/types' +import NumericalInput from 'components/NumericalInput' +import { Stack } from 'components/Stack' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import useTheme from 'hooks/useTheme' import { cn } from 'utils/cn' diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Form/MarketPrice.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Form/MarketPrice.tsx index 9f6b6ee253..dda41a51c8 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Form/MarketPrice.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Form/MarketPrice.tsx @@ -1,9 +1,9 @@ import { useState } from 'react' import { Repeat } from 'react-feather' +import { removeTrailingZero } from 'components/LimitOrder/helpers' import Skeleton from 'components/Skeleton' import { HStack } from 'components/Stack' -import { removeTrailingZero } from 'components/LimitOrder/helpers' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' type MarketPriceProps = { diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelButtons.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelButtons.tsx index e2e67318eb..3ce372a398 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelButtons.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelButtons.tsx @@ -6,10 +6,10 @@ import { ReactComponent as GasLessIcon } from 'assets/svg/gas_less_icon.svg' import { ButtonLight, ButtonOutlined, ButtonPrimary } from 'components/Button' import Column from 'components/Column' import { GasStation } from 'components/Icons' -import { MouseoverTooltip } from 'components/Tooltip' import { CancelStatus } from 'components/LimitOrder/Modals/CancelOrderModal' import { DOCS_LINKS, getPayloadTracking } from 'components/LimitOrder/helpers' import { CancelOrderType, LimitOrder } from 'components/LimitOrder/types' +import { MouseoverTooltip } from 'components/Tooltip' import { useActiveWeb3React } from 'hooks' import useTheme from 'hooks/useTheme' import useTracking, { TRACKING_EVENT_TYPE } from 'hooks/useTracking' @@ -96,7 +96,7 @@ const CancelButtons = ({ }, }: { cancelStatus: CancelStatus - onDismiss: () => void + onDismiss?: () => void onSubmit?: () => void onClickGaslessCancel: () => void onClickHardCancel: () => void diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelOrderModal.tsx index 5e096f8620..427209ecd6 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelOrderModal.tsx @@ -2,18 +2,15 @@ import { ChainId } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' import { useEffect, useMemo, useState } from 'react' -import Logo from 'components/Logo' -import Modal from 'components/Modal' import CancelButtons from 'components/LimitOrder/Modals/CancelButtons' import CancelStatusCountDown from 'components/LimitOrder/Modals/CancelStatusCountDown' import { Container, Header, Label, ListInfo, Note, Rate, Value } from 'components/LimitOrder/Modals/components' import { useEstimateFee, useProcessCancelOrder } from 'components/LimitOrder/MyOrders/useRequestCancelOrder' import { calcPercentFilledOrder, formatAmountOrder } from 'components/LimitOrder/helpers' -import { - useAllActiveOrders, - useIsSupportSoftCancelOrder, -} from 'components/LimitOrder/hooks/useFetchActiveAllOrders' +import { useAllActiveOrders, useIsSupportSoftCancelOrder } from 'components/LimitOrder/hooks/useFetchActiveAllOrders' import { CancelOrderFunction, CancelOrderType, LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' +import Logo from 'components/Logo' +import Modal from 'components/Modal' import { NativeCurrencies } from 'constants/tokens' import { useCurrencyV2 } from 'hooks/Tokens' import { useBaseTradeInfoLimitOrder } from 'hooks/useBaseTradeInfo' @@ -41,7 +38,7 @@ const CancelOrderModal = ({ customChainId?: ChainId order: LimitOrder | undefined onSubmit: CancelOrderFunction - onDismiss: () => void + onDismiss?: () => void flowState: TransactionFlowState isOpen: boolean }) => { @@ -161,8 +158,10 @@ const CancelOrderModal = ({ const percent = calcPercentFilledOrder(filledTakingAmount, takingAmount, takerAssetDecimals) + const handleDismiss = () => onDismiss?.() + return ( - +
{isCancelAll && isWaiting ? ( diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelStatusCountDown.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelStatusCountDown.tsx index d3fbdc3abc..d4459462ed 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelStatusCountDown.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelStatusCountDown.tsx @@ -6,9 +6,9 @@ import { ReactComponent as TimerIcon } from 'assets/svg/clock_timer.svg' import Column from 'components/Column' import { Clock } from 'components/Icons' import WarningIcon from 'components/Icons/WarningIcon' -import Loader from 'components/Loader' import { CancelStatus } from 'components/LimitOrder/Modals/CancelOrderModal' import { DOCS_LINKS } from 'components/LimitOrder/helpers' +import Loader from 'components/Loader' import useInterval from 'hooks/useInterval' import { ExternalLink } from 'theme' import { TransactionFlowState } from 'types/TransactionFlowState' diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmOrderModal.tsx index 0153646178..990ae74709 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmOrderModal.tsx @@ -6,11 +6,11 @@ import { Repeat } from 'react-feather' import { ButtonPrimary, ButtonWarning } from 'components/Button' import CurrencyLogo from 'components/CurrencyLogo' -import Modal from 'components/Modal' -import { HStack, Stack } from 'components/Stack' import { formatAmountOrder, removeTrailingZero } from 'components/LimitOrder/helpers' import { WORSE_PRICE_DIFF_THRESHOLD } from 'components/LimitOrder/hooks/useWarningCreateOrder' import { LimitOrderCreateContext, RateInfo } from 'components/LimitOrder/types' +import Modal from 'components/Modal' +import { HStack, Stack } from 'components/Stack' import { BaseTradeInfo } from 'hooks/useBaseTradeInfo' import { CloseIcon } from 'theme/components' import { cn } from 'utils/cn' @@ -124,8 +124,8 @@ type Props = { order: LimitOrderCreateContext review: { isOpen: boolean - onDismiss: () => void - onSubmit: () => void + onDismiss?: () => void + onSubmit?: () => void } warningMessage: ReactNode[] } @@ -139,13 +139,13 @@ const ConfirmOrderModal = ({ order, review, warningMessage }: Props) => { const handleSubmit = () => { if (shouldDisablePlaceOrder) return - onSubmit() + onSubmit?.() } const handleWarningClick = (event: MouseEvent) => { const target = event.target if (target instanceof HTMLElement && target.closest('a')) { - onDismiss() + onDismiss?.() } } @@ -163,13 +163,13 @@ const ConfirmOrderModal = ({ order, review, warningMessage }: Props) => { }, [isOpen]) return ( - + onDismiss?.()} borderRadius={14}> Review your order - + diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmTakeOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmTakeOrderModal.tsx index 4635a7eea6..a594a2dfcc 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmTakeOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmTakeOrderModal.tsx @@ -2,16 +2,19 @@ import { Currency, CurrencyAmount } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' import { useEffect, useState } from 'react' import { Repeat } from 'react-feather' +import { useNavigate } from 'react-router-dom' import { ButtonOutlined, ButtonPrimary } from 'components/Button' import CurrencyLogo from 'components/CurrencyLogo' +import ProcessingOrderModal from 'components/LimitOrder/Modals/ProcessingOrderModal' +import { removeTrailingZero } from 'components/LimitOrder/helpers' +import { useTakeLimitOrder } from 'components/LimitOrder/hooks/useTakeLimitOrder' +import { LimitOrderTab, LimitOrderTakeContext } from 'components/LimitOrder/types' import Modal from 'components/Modal' import NumericalInput from 'components/NumericalInput' import { HStack, Stack } from 'components/Stack' -import ProcessingTakeOrderModal from 'components/LimitOrder/Modals/ProcessingTakeOrderModal' -import { removeTrailingZero } from 'components/LimitOrder/helpers' -import { useTakeLimitOrder } from 'components/LimitOrder/hooks/useTakeLimitOrder' -import { LimitOrderTakeContext } from 'components/LimitOrder/types' +import { APP_PATHS } from 'constants/index' +import { NETWORKS_INFO } from 'hooks/useChainsConfig' import { CloseIcon } from 'theme/components' import { cn } from 'utils/cn' import { formatDisplayNumber } from 'utils/numbers' @@ -48,8 +51,9 @@ const ConfirmTakeOrderModal = ({ }: { context: LimitOrderTakeContext | undefined isOpen: boolean - onDismiss: () => void + onDismiss?: () => void }) => { + const navigate = useNavigate() const takeOrder = useTakeLimitOrder({ context, isOpen }) const { estimateTxGas } = takeOrder const [showInvertedRate, setShowInvertedRate] = useState(false) @@ -70,7 +74,7 @@ const ConfirmTakeOrderModal = ({ const isConfirmOpen = isOpen && !takeOrder.processing.state.show const handleDismiss = () => { - onDismiss() + onDismiss?.() } const handleSubmit = () => { @@ -79,7 +83,18 @@ const ConfirmTakeOrderModal = ({ const handleProcessingDismiss = () => { takeOrder.processing.dismiss() - onDismiss() + onDismiss?.() + } + + const handleViewOrder = () => { + if (!context) return + + const route = NETWORKS_INFO[context.order.chainId]?.route + if (!route) return + + const search = new URLSearchParams({ tab: LimitOrderTab.MY_ORDER }).toString() + + navigate(`${APP_PATHS.LIMIT}/${route}?${search}`) } useEffect(() => { @@ -125,7 +140,7 @@ const ConfirmTakeOrderModal = ({ Fill Order - + @@ -225,12 +240,13 @@ const ConfirmTakeOrderModal = ({ - ) diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingOrderModal.tsx index f72bd231f8..47b522dbec 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingOrderModal.tsx @@ -1,30 +1,60 @@ import { ChainId, Currency } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' -import { AlertCircle, RefreshCw } from 'react-feather' +import { AlertCircle, RotateCw } from 'react-feather' import { ButtonLight, ButtonOutlined, ButtonPrimary } from 'components/Button' import { CheckCircle } from 'components/Icons' +import type { ProcessingOrderStep } from 'components/LimitOrder/hooks/useProcessingOrder' +import type { TakeOrderStep } from 'components/LimitOrder/hooks/useTakeLimitOrder' import Loader from 'components/Loader' import Modal from 'components/Modal' import { Center, HStack, Stack } from 'components/Stack' -import type { - ProcessingOrderController, - ProcessingOrderState, - ProcessingOrderStep, - ProcessingOrderStepStatus, -} from 'components/LimitOrder/hooks/useProcessingOrder' import { NativeCurrencies } from 'constants/tokens' import { CloseIcon } from 'theme/components' import { cn } from 'utils/cn' -const getStepStatus = (state: ProcessingOrderState, step: ProcessingOrderStep): ProcessingOrderStepStatus => { - if (state.errorStep === step) return 'error' - if (state.completedSteps.includes(step)) return 'success' - if (state.currentStep === step) return 'active' +type OrderProcessingStep = ProcessingOrderStep | TakeOrderStep +type ProcessingStepStatus = 'idle' | 'active' | 'success' | 'error' + +type ProcessingState = { + show: boolean + steps: Step[] + currentStep?: Step + errorStep?: Step + completedSteps: Step[] +} + +type ProcessingController = { + state: ProcessingState + dismiss: () => void + retryStep?: (step: Step) => void +} + +type ProcessingOrderModalProps = { + processing: ProcessingController + chainId?: ChainId + currencyIn?: Currency + onViewOrder?: () => void +} + +const getStepStatus = ({ + step, + currentStep, + errorStep, + completedSteps, +}: { + step: Step + currentStep: Step | undefined + errorStep: Step | undefined + completedSteps: Step[] +}): ProcessingStepStatus => { + if (errorStep === step) return 'error' + if (completedSteps.includes(step)) return 'success' + if (currentStep === step) return 'active' return 'idle' } -const StepIcon = ({ index, status }: { index: number; status: ProcessingOrderStepStatus }) => { +const StepIcon = ({ index, status }: { index: number; status: ProcessingStepStatus }) => { if (status === 'success') return if (status === 'active') return if (status === 'error') return @@ -41,38 +71,37 @@ const getStepLabel = ({ chainId, currencyIn, }: { - step: ProcessingOrderStep - status: ProcessingOrderStepStatus - chainId: ChainId + step: OrderProcessingStep + status: ProcessingStepStatus + chainId: ChainId | undefined currencyIn: Currency | undefined }) => { - const nativeSymbol = NativeCurrencies[chainId].symbol - const inputSymbol = currencyIn?.wrapped.symbol - if (step === 'wrap') { + const nativeSymbol = chainId ? NativeCurrencies[chainId].symbol : t`token` if (status === 'active') return t`Wrapping ${nativeSymbol}` if (status === 'success') return t`Wrapped ${nativeSymbol}` return t`Wrap ${nativeSymbol}` } if (step === 'approve') { - if (status === 'active') return t`Approving ${inputSymbol}` - if (status === 'success') return t`Approved ${inputSymbol}` - return t`Approve ${inputSymbol}` + const inputSymbol = currencyIn?.wrapped.symbol + if (status === 'active') return inputSymbol ? t`Approving ${inputSymbol}` : t`Approving token` + if (status === 'success') return inputSymbol ? t`Approved ${inputSymbol}` : t`Approved token` + return inputSymbol ? t`Approve ${inputSymbol}` : t`Approve token` } - if (status === 'active') return t`Signing order` - if (status === 'success') return t`Order successfully listed` - return t`Sign order` -} + if (step === 'create') { + if (status === 'active') return t`Signing order` + if (status === 'success') return t`Order successfully listed` + return t`Sign order` + } -const isOrderComplete = (state: ProcessingOrderState) => - state.show && - !!state.steps.length && - state.steps.every(step => state.completedSteps.includes(step)) && - !state.errorStep + if (status === 'active') return t`Filling order` + if (status === 'success') return t`Order filled` + return t`Fill order` +} -const ProcessingStepRow = ({ +const ProcessingStepRow = ({ index, step, status, @@ -81,17 +110,17 @@ const ProcessingStepRow = ({ onRetryStep, }: { index: number - step: ProcessingOrderStep - status: ProcessingOrderStepStatus - chainId: ChainId + step: Step + status: ProcessingStepStatus + chainId: ChainId | undefined currencyIn: Currency | undefined - onRetryStep: (step: ProcessingOrderStep) => void + onRetryStep?: (step: Step) => void }) => ( - + {getStepLabel({ step, status, chainId, currencyIn })} - - {status === 'error' && ( - onRetryStep(step)} - width="auto" - className="!h-7 shrink-0 gap-1 rounded-full !px-3 !py-0 text-xs text-primary" - > - - {t`Retry`} - - )} - + {status === 'error' && ( + onRetryStep?.(step)} width="auto" className="gap-1 px-2 py-1 text-xs"> + + {t`Retry`} + + )} ) -const ProcessingOrderModal = ({ +const ProcessingOrderModal = ({ + processing, chainId, currencyIn, - processing, onViewOrder, -}: { - chainId: ChainId - currencyIn: Currency | undefined - processing: ProcessingOrderController - onViewOrder: () => void -}) => { +}: ProcessingOrderModalProps) => { const { state, dismiss, retryStep } = processing - const orderComplete = isOrderComplete(state) + + const orderComplete = + state.show && + !!state.steps.length && + state.steps.every(step => state.completedSteps.includes(step)) && + !state.errorStep + const isProcessing = state.show && !!state.currentStep && !state.errorStep && !orderComplete - const handleDismiss = isProcessing ? undefined : dismiss + + const handleDismiss = () => { + if (!isProcessing) { + dismiss() + } + } + + const handleViewOrder = () => { + dismiss() + onViewOrder?.() + } return (
{t`Processing Order`}
- +
{state.steps.map((step, index) => { - const status = getStepStatus(state, step) + const status = getStepStatus({ + step, + currentStep: state.currentStep, + errorStep: state.errorStep, + completedSteps: state.completedSteps, + }) return ( {orderComplete && ( - - + + Close - + View Order diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingTakeOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingTakeOrderModal.tsx deleted file mode 100644 index 63b52ac779..0000000000 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingTakeOrderModal.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import { ChainId } from '@kyberswap/ks-sdk-core' -import { Trans, t } from '@lingui/macro' -import { AlertCircle, RefreshCw } from 'react-feather' - -import { ButtonLight, ButtonOutlined } from 'components/Button' -import { CheckCircle } from 'components/Icons' -import Loader from 'components/Loader' -import Modal from 'components/Modal' -import { Center, HStack, Stack } from 'components/Stack' -import { - TakeOrderProcessingState, - TakeOrderStep, - TakeOrderStepStatus, -} from 'components/LimitOrder/hooks/useTakeLimitOrder' -import { NativeCurrencies } from 'constants/tokens' -import { CloseIcon } from 'theme/components' -import { cn } from 'utils/cn' - -type ProcessingController = { - state: TakeOrderProcessingState - dismiss: () => void - retryStep: (step: TakeOrderStep) => void -} - -const getStepStatus = (state: TakeOrderProcessingState, step: TakeOrderStep): TakeOrderStepStatus => { - if (state.errorStep === step) return 'error' - if (state.completedSteps.includes(step)) return 'success' - if (state.currentStep === step) return 'active' - return 'idle' -} - -const StepIcon = ({ index, status }: { index: number; status: TakeOrderStepStatus }) => { - if (status === 'success') return - if (status === 'active') return - if (status === 'error') return - return ( -
- {index + 1} -
- ) -} - -const getStepLabel = (step: TakeOrderStep, status: TakeOrderStepStatus, chainId: ChainId | undefined) => { - if (step === 'wrap') { - const nativeSymbol = chainId ? NativeCurrencies[chainId].symbol : t`token` - if (status === 'active') return t`Wrapping ${nativeSymbol}` - if (status === 'success') return t`Wrapped ${nativeSymbol}` - return t`Wrap ${nativeSymbol}` - } - - if (step === 'approve') { - if (status === 'active') return t`Approving token` - if (status === 'success') return t`Approved token` - return t`Approve token` - } - - if (status === 'active') return t`Filling order` - if (status === 'success') return t`Order filled` - return t`Fill order` -} - -const isOrderComplete = (state: TakeOrderProcessingState) => - state.show && - !!state.steps.length && - state.steps.every(step => state.completedSteps.includes(step)) && - !state.errorStep - -const ProcessingStepRow = ({ - index, - step, - status, - chainId, - onRetryStep, -}: { - index: number - step: TakeOrderStep - status: TakeOrderStepStatus - chainId: ChainId | undefined - onRetryStep: (step: TakeOrderStep) => void -}) => ( - - - - {getStepLabel(step, status, chainId)} - - - {status === 'error' && ( - onRetryStep(step)} - width="auto" - className="!h-7 shrink-0 gap-1 rounded-full !px-3 !py-0 text-xs text-primary" - > - - {t`Retry`} - - )} - - -) - -const ProcessingTakeOrderModal = ({ - chainId, - processing, -}: { - chainId: ChainId | undefined - processing: ProcessingController -}) => { - const { state, dismiss, retryStep } = processing - const orderComplete = isOrderComplete(state) - const isProcessing = state.show && !!state.currentStep && !state.errorStep && !orderComplete - const handleDismiss = isProcessing ? undefined : dismiss - - return ( - - - -
{t`Processing Order`}
- -
- - - - {state.steps.map((step, index) => { - const status = getStepStatus(state, step) - return ( - - ) - })} - - - {orderComplete && ( - - Close - - )} - -
-
- ) -} - -export default ProcessingTakeOrderModal diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/components.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Modals/components.tsx index cb2bb90035..f681607171 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/components.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Modals/components.tsx @@ -44,7 +44,7 @@ export const Label = ({ children, className, style, ...rest }: React.HTMLAttribu
) -export const Header = ({ title, onDismiss }: { title: string; onDismiss: () => void }) => { +export const Header = ({ title, onDismiss }: { title: string; onDismiss?: () => void }) => { return (
diff --git a/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx index e24bba982a..834fded89e 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx @@ -6,9 +6,6 @@ import { useGetListOrdersQuery } from 'services/limitOrder' import { ReactComponent as NoDataIcon } from 'assets/svg/no_data.svg' import InfoHelper from 'components/InfoHelper' -import Pagination from 'components/Pagination' -import SearchInput from 'components/SearchInput' -import Select from 'components/Select' import CancelOrderModal from 'components/LimitOrder/Modals/CancelOrderModal' import OrderItem from 'components/LimitOrder/MyOrders/OrderItem' import { useRequestCancelOrder } from 'components/LimitOrder/MyOrders/useRequestCancelOrder' @@ -20,6 +17,9 @@ import { } from 'components/LimitOrder/helpers' import { useCancellingOrders } from 'components/LimitOrder/hooks/useCancellingOrders' import { LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' +import Pagination from 'components/Pagination' +import SearchInput from 'components/SearchInput' +import Select from 'components/Select' import { RTK_QUERY_TAGS, TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { useInvalidateTagLimitOrder } from 'hooks/useInvalidateTags' diff --git a/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/useRequestCancelOrder.tsx b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/useRequestCancelOrder.tsx index ffc1ca85e0..751d7af496 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/useRequestCancelOrder.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/useRequestCancelOrder.tsx @@ -8,11 +8,11 @@ import { useInsertCancellingOrderMutation, } from 'services/limitOrder' -import { wagmiConfig } from 'components/Web3Provider' import { CancelStatus } from 'components/LimitOrder/Modals/CancelOrderModal' import { formatAmountOrder, getErrorMessage, getPayloadTracking } from 'components/LimitOrder/helpers' import { useCancellingOrders } from 'components/LimitOrder/hooks/useCancellingOrders' import { CancelOrderFunction, CancelOrderType, LimitOrder } from 'components/LimitOrder/types' +import { wagmiConfig } from 'components/Web3Provider' import { LIMIT_ORDER_ABI } from 'constants/abis' import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React, useWeb3React } from 'hooks' @@ -206,7 +206,7 @@ export const useProcessCancelOrder = ({ getOrders, }: { onSubmit: CancelOrderFunction - onDismiss: () => void + onDismiss?: () => void isOpen: boolean getOrders: (v: boolean) => LimitOrder[] }) => { @@ -248,7 +248,7 @@ export const useProcessCancelOrder = ({ if (expired * 1000 < Date.now()) { setCancelStatus(CancelStatus.CANCEL_DONE) } - } else onDismiss() + } else onDismiss?.() } catch (error) { if (signal.aborted) return setExpiredTime(0) diff --git a/apps/kyberswap-interface/src/components/LimitOrder/OrderBook/OrderItem.tsx b/apps/kyberswap-interface/src/components/LimitOrder/OrderBook/OrderItem.tsx index 14fd8ccfe0..6ccc88d822 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/OrderBook/OrderItem.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/OrderBook/OrderItem.tsx @@ -56,7 +56,7 @@ const OrderItem = ({ }: { reverse?: boolean order: LimitOrderFromTokenPairFormatted - onTake: (order: LimitOrderFromTokenPairFormatted) => void + onTake?: (order: LimitOrderFromTokenPairFormatted) => void }) => { const upToExtraSmall = useMedia(`(max-width: ${MEDIA_WIDTHS.upToExtraSmall}px)`) const { currencyIn: makerCurrency, currencyOut: takerCurrency } = useLimitState() @@ -93,7 +93,7 @@ const OrderItem = ({ {order.hasAvailable && ( +) + +const TxLink = ({ chainId, txHash }: { chainId: LimitOrder['chainId']; txHash?: string }) => { + if (!txHash) return null + + return ( + event.stopPropagation()} + > + + + ) +} + const OrderItem = ({ order, onCancelOrder, @@ -130,9 +172,12 @@ const OrderItem = ({ isOrderCancelling: (order: LimitOrder) => boolean }) => { const navigate = useNavigate() + const [expand, setExpand] = useState(false) const isCancelling = isOrderCancelling(order) const status = isCancelling ? LimitOrderStatus.CANCELLING : order.status const isOrderActive = isActiveStatus(order.status) + const isFilledOrder = order.status === LimitOrderStatus.FILLED || order.takingAmount === order.filledTakingAmount + const txs = order.transactions || [] const native = NativeCurrencies[order.chainId] const isNative = order.nativeOutput && order.takerAssetSymbol.toLowerCase() === native?.wrapped.symbol?.toLowerCase() @@ -154,6 +199,8 @@ const OrderItem = ({ const makingTokenBalance = useTokenBalance(makerCurrency) const insufficientFund = isOrderActive && makingTokenBalance ? makingTokenBalance.lessThan(availableAmount) : false + const canExpandTxs = txs.length > 0 + const showFallbackTxLink = isFilledOrder && !txs.length && !!order.txHash const onClickOrder = () => { const search = new URLSearchParams({ tab: LimitOrderTab.ORDER_BOOK }).toString() @@ -164,54 +211,111 @@ const OrderItem = ({ } return ( -
- - Network - - - - - - - - - - {isOrderActive && ( - + <> +
-
+ onClick={onClickOrder} + > + + Network + + + + + + + + + + {showFallbackTxLink && } + {canExpandTxs && ( + { + event.stopPropagation() + setExpand(value => !value) + }} + > + + + )} + {isOrderActive && ( + { + event.stopPropagation() + onCancelOrder(order) + }} + > + + + )} + +
+ {canExpandTxs && ( +
+
+ {txs.map(tx => { + const txFilledPercent = calcPercentFilledOrder( + tx.takingAmount, + order.takingAmount, + order.takerAssetDecimals, + ) + + return ( +
+ + {txFilledPercent}% + +
+ +
+ + {new Date(tx.txTime * 1000).toLocaleString()} + + + + + + + +
+ ) + })} +
+
+ )} + ) } diff --git a/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx index 834fded89e..4e747378c3 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx @@ -1,10 +1,12 @@ import { ChainId } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' import { HTMLAttributes, useCallback, useEffect, useState } from 'react' +import { Trash } from 'react-feather' import { useSearchParams } from 'react-router-dom' import { useGetListOrdersQuery } from 'services/limitOrder' import { ReactComponent as NoDataIcon } from 'assets/svg/no_data.svg' +import { ButtonLight } from 'components/Button' import InfoHelper from 'components/InfoHelper' import CancelOrderModal from 'components/LimitOrder/Modals/CancelOrderModal' import OrderItem from 'components/LimitOrder/MyOrders/OrderItem' @@ -120,7 +122,7 @@ const TabSelector = ({ const TableHeader = () => (
@@ -166,6 +168,7 @@ const MyOrders = ({ customChainId }: { customChainId?: ChainId }) => { const [orderType, setOrderType] = useState(orderTab || LimitOrderStatus.ACTIVE) const [currentOrder, setCurrentOrder] = useState() const [isOpenCancel, setIsOpenCancel] = useState(false) + const [isCancelAll, setIsCancelAll] = useState(false) const keyword = searchParams.get('search') || '' const isTabActive = isActiveStatus(orderType) @@ -190,13 +193,16 @@ const MyOrders = ({ customChainId }: { customChainId?: ChainId }) => { const { flowState, setFlowState, onCancelOrder } = useRequestCancelOrder({ orders, - isCancelAll: false, + isCancelAll, totalOrder, }) const hasOrders = orders.length > 0 const showPagination = hasOrders && totalOrder > PAGE_SIZE + const showCancelAll = hasOrders && isTabActive const showNoOrders = !hasOrders && (isOrdersLoaded || !account) + const totalOrderNotCancelling = orders.filter(order => !isOrderCancelling(order)).length + const disabledCancelAll = totalOrderNotCancelling === 0 const onReset = useCallback(() => { setCurPage(1) @@ -290,21 +296,30 @@ const MyOrders = ({ customChainId }: { customChainId?: ChainId }) => { const hideConfirmCancel = useCallback(() => { setFlowState(TRANSACTION_STATE_DEFAULT) setIsOpenCancel(false) + setIsCancelAll(false) setTimeout(() => { setCurrentOrder(undefined) }, 300) }, [setFlowState]) const showConfirmCancel = useCallback( - (order: LimitOrder) => { + (order?: LimitOrder) => { setCurrentOrder(order) setFlowState({ ...TRANSACTION_STATE_DEFAULT, showConfirm: true }) setIsOpenCancel(true) - trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_CANCEL_ORDER, getPayloadTracking(order, networkInfo.name)) + setIsCancelAll(false) + if (order) { + trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_CANCEL_ORDER, getPayloadTracking(order, networkInfo.name)) + } }, [trackingHandler, setFlowState, networkInfo], ) + const onCancelAllOrder = () => { + showConfirmCancel() + setIsCancelAll(true) + } + useEffect(() => { if (!account) return @@ -377,16 +392,34 @@ const MyOrders = ({ customChainId }: { customChainId?: ChainId }) => { /> ))}
- {showPagination && ( -
- + {(showPagination || showCancelAll) && ( +
+ {showCancelAll && ( + + + Cancel All + + )} + {showPagination && ( + + )}
)} {showNoOrders && ( @@ -411,7 +444,7 @@ const MyOrders = ({ customChainId }: { customChainId?: ChainId }) => { onSubmit={onCancelOrder} customChainId={customChainId} order={currentOrder} - isCancelAll={false} + isCancelAll={isCancelAll} />
) diff --git a/apps/kyberswap-interface/src/components/LimitOrder/OrderList/index.tsx b/apps/kyberswap-interface/src/components/LimitOrder/OrderList/index.tsx index 4b2e60671e..3b63c6fe9b 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/OrderList/index.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/OrderList/index.tsx @@ -65,7 +65,7 @@ const TabSelector = ({ } > - + {numberOfInsufficientFundOrders} diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCreateLimitOrder.tsx b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCreateLimitOrder.tsx index ee1aab204c..9635405eb5 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCreateLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCreateLimitOrder.tsx @@ -47,7 +47,7 @@ export const useCreateLimitOrder = ({ const { account } = useActiveWeb3React() const { trackingHandler } = useTracking() const notify = useNotify() - const signOrder = useSignOrder(undefined) + const signOrder = useSignOrder() const [submitOrder] = useCreateOrderMutation() diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderExecution.tsx index 33fc34737a..25b132105e 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderExecution.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderExecution.tsx @@ -9,7 +9,6 @@ import { calcUsdPrices, getErrorMessage, removeTrailingZero } from 'components/L import { ProcessingOrderStep } from 'components/LimitOrder/hooks/useProcessingOrder' import { useValidateInputError } from 'components/LimitOrder/hooks/useValidateInputError' import { useWarningCreateOrder } from 'components/LimitOrder/hooks/useWarningCreateOrder' -import { useWrapEthStatus } from 'components/LimitOrder/hooks/useWrapEthStatus' import { LimitOrderCreateContext } from 'components/LimitOrder/types' import { wagmiConfig } from 'components/Web3Provider' import { ERC20_ABI } from 'constants/abis' @@ -114,7 +113,6 @@ export const useLimitOrderExecution = ({ const wrapInputCurrency = wrapAmountForOrder ? nativeCurrency : undefined const wrapTypedValue = wrapAmountForOrder?.toExact() - const { isWrappingEth, setTxHashWrapped } = useWrapEthStatus(switchToWeth) const { execute: onWrap } = useWrapCallback(wrapInputCurrency, WETH[chainId], wrapTypedValue, true, chainId) const maxAmountInput = useMemo(() => { @@ -338,12 +336,12 @@ export const useLimitOrderExecution = ({ openReview, }, processing: { + chainId, approval, approveCallback, checkApprovalManually, - isWrappingEth, onWrap, - setTxHashWrapped, + onWrapSuccess: switchToWeth, steps: processingSteps, }, tracking: { diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useProcessingOrder.ts b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useProcessingOrder.ts index 09b2069b97..8c82a8e0f0 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useProcessingOrder.ts +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useProcessingOrder.ts @@ -1,5 +1,7 @@ -import { useCallback, useEffect, useRef, useState } from 'react' +import { waitForTransactionReceipt } from '@wagmi/core' +import { Dispatch, SetStateAction, useCallback } from 'react' +import { wagmiConfig } from 'components/Web3Provider' import { ApprovalState } from 'hooks/useApproveCallback' export type ProcessingOrderStep = 'wrap' | 'approve' | 'create' @@ -21,19 +23,21 @@ export type ProcessingOrderController = { } type UseProcessingOrderArgs = { + processingOrder: ProcessingOrderState + setProcessingOrder: Dispatch> + chainId: number approval: ApprovalState approveCallback: () => Promise checkApprovalManually: () => Promise steps: ProcessingOrderStep[] - isWrappingEth: boolean onWrap: (() => Promise) | undefined - setTxHashWrapped?: (hash: string) => void + onWrapSuccess?: () => void onCreateOrder: () => Promise onError?: (error: unknown) => void onStart?: () => void } -const DEFAULT_PROCESSING_ORDER: ProcessingOrderState = { +export const DEFAULT_PROCESSING_ORDER: ProcessingOrderState = { show: false, steps: [], completedSteps: [], @@ -44,245 +48,202 @@ const APPROVAL_CHECK_RETRY_DELAY = 2_000 const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)) export const useProcessingOrder = ({ + processingOrder, + setProcessingOrder, + chainId, approval, approveCallback, checkApprovalManually, steps, - isWrappingEth, onWrap, - setTxHashWrapped, + onWrapSuccess, onCreateOrder, onError, onStart, }: UseProcessingOrderArgs) => { - const [processingOrder, setProcessingOrder] = useState(DEFAULT_PROCESSING_ORDER) - const processingStepStartedRef = useRef() - const processingRunIdRef = useRef(0) - const wrapTransactionPendingRef = useRef(false) - - const isCurrentProcessingRun = useCallback((processingRunId: number) => { - return processingRunIdRef.current === processingRunId - }, []) - - const startProcessingStepRun = useCallback((step: ProcessingOrderStep) => { - if (processingStepStartedRef.current === step) return - processingStepStartedRef.current = step - return processingRunIdRef.current - }, []) - - const invalidateProcessingRun = useCallback(() => { - processingRunIdRef.current += 1 - processingStepStartedRef.current = undefined - wrapTransactionPendingRef.current = false - }, []) - - const markProcessingStepSuccess = useCallback((step: ProcessingOrderStep) => { - processingStepStartedRef.current = undefined - if (step === 'wrap') wrapTransactionPendingRef.current = false - setProcessingOrder(state => { - if (!state.show || state.currentStep !== step) return state - const completedSteps = state.completedSteps.includes(step) - ? state.completedSteps - : [...state.completedSteps, step] - const nextStep = state.steps[state.steps.indexOf(step) + 1] - return { - ...state, - currentStep: nextStep, - completedSteps, - } - }) - }, []) - - const markProcessingStepError = useCallback((step: ProcessingOrderStep) => { - processingStepStartedRef.current = undefined - if (step === 'wrap') wrapTransactionPendingRef.current = false - setProcessingOrder(state => { - if (!state.show || state.currentStep !== step) return state - return { - ...state, - errorStep: step, - } - }) - }, []) - - const hideProcessingOrder = useCallback(() => { - invalidateProcessingRun() - setProcessingOrder(DEFAULT_PROCESSING_ORDER) - }, [invalidateProcessingRun]) - - const retryProcessingStep = useCallback( + const markProcessingStepSuccess = useCallback( (step: ProcessingOrderStep) => { - invalidateProcessingRun() setProcessingOrder(state => { - if (state.errorStep !== step) return state + if (!state.show || state.currentStep !== step) return state + const completedSteps = state.completedSteps.includes(step) + ? state.completedSteps + : [...state.completedSteps, step] + const nextStep = state.steps[state.steps.indexOf(step) + 1] return { ...state, - currentStep: step, - errorStep: undefined, + currentStep: nextStep, + completedSteps, } }) }, - [invalidateProcessingRun], + [setProcessingOrder], ) - const waitForManualApproval = useCallback( - async (processingRunId: number) => { - for (let attempt = 0; attempt < APPROVAL_CHECK_RETRY_COUNT; attempt++) { - if (!isCurrentProcessingRun(processingRunId)) return - const hasEnoughAllowance = await checkApprovalManually() - if (!isCurrentProcessingRun(processingRunId)) return - if (hasEnoughAllowance) return true - await sleep(APPROVAL_CHECK_RETRY_DELAY) - } - - return false + const markProcessingStepError = useCallback( + (step: ProcessingOrderStep) => { + setProcessingOrder(state => { + if (!state.show || state.currentStep !== step) return state + return { + ...state, + errorStep: step, + } + }) }, - [checkApprovalManually, isCurrentProcessingRun], + [setProcessingOrder], ) - const runWrapStep = useCallback(() => { - if (isWrappingEth) return - const processingRunId = startProcessingStepRun('wrap') - if (processingRunId === undefined) return + const hideProcessingOrder = useCallback(() => { + setProcessingOrder(DEFAULT_PROCESSING_ORDER) + }, [setProcessingOrder]) + + const waitForManualApproval = useCallback(async () => { + for (let attempt = 0; attempt < APPROVAL_CHECK_RETRY_COUNT; attempt++) { + const hasEnoughAllowance = await checkApprovalManually() + if (hasEnoughAllowance) return true + await sleep(APPROVAL_CHECK_RETRY_DELAY) + } + + return false + }, [checkApprovalManually]) - void (async () => { + const runWrapStep = useCallback(() => { + return (async () => { try { const hash = await onWrap?.() - if (!isCurrentProcessingRun(processingRunId)) return if (!hash) { markProcessingStepError('wrap') - return + return false } - setTxHashWrapped?.(hash) + const receipt = await waitForTransactionReceipt(wagmiConfig, { + chainId: chainId as (typeof wagmiConfig)['chains'][number]['id'], + hash: hash as `0x${string}`, + }) + if (receipt.status === 'reverted') { + markProcessingStepError('wrap') + return false + } + onWrapSuccess?.() + markProcessingStepSuccess('wrap') + return true } catch (error) { - if (!isCurrentProcessingRun(processingRunId)) return onError?.(error) markProcessingStepError('wrap') + return false } })() - }, [ - isCurrentProcessingRun, - isWrappingEth, - markProcessingStepError, - onError, - onWrap, - setTxHashWrapped, - startProcessingStepRun, - ]) + }, [chainId, markProcessingStepError, markProcessingStepSuccess, onError, onWrap, onWrapSuccess]) const runApproveStep = useCallback(() => { - const processingRunId = startProcessingStepRun('approve') - if (processingRunId === undefined) return - - void (async () => { + return (async () => { try { if (await checkApprovalManually()) { - if (!isCurrentProcessingRun(processingRunId)) return markProcessingStepSuccess('approve') - return + return true } if (approval !== ApprovalState.PENDING) { await approveCallback() } - const hasEnoughAllowance = await waitForManualApproval(processingRunId) - if (!isCurrentProcessingRun(processingRunId)) return + const hasEnoughAllowance = await waitForManualApproval() if (hasEnoughAllowance) { markProcessingStepSuccess('approve') - return + return true } markProcessingStepError('approve') + return false } catch (error) { - if (!isCurrentProcessingRun(processingRunId)) return onError?.(error) markProcessingStepError('approve') + return false } })() }, [ approval, approveCallback, checkApprovalManually, - isCurrentProcessingRun, markProcessingStepError, markProcessingStepSuccess, onError, - startProcessingStepRun, waitForManualApproval, ]) const runCreateStep = useCallback(() => { - const processingRunId = startProcessingStepRun('create') - if (processingRunId === undefined) return - - void (async () => { + return (async () => { try { const orderId = await onCreateOrder() - if (!isCurrentProcessingRun(processingRunId)) return if (orderId) { markProcessingStepSuccess('create') - return + return true } markProcessingStepError('create') + return false } catch (error) { - if (!isCurrentProcessingRun(processingRunId)) return onError?.(error) markProcessingStepError('create') + return false } })() - }, [ - isCurrentProcessingRun, - markProcessingStepError, - markProcessingStepSuccess, - onCreateOrder, - onError, - startProcessingStepRun, - ]) + }, [markProcessingStepError, markProcessingStepSuccess, onCreateOrder, onError]) const runProcessingStep = useCallback( (step: ProcessingOrderStep) => { if (step === 'wrap') { - runWrapStep() - return + return runWrapStep() } if (step === 'approve') { - runApproveStep() - return + return runApproveStep() } - runCreateStep() + return runCreateStep() }, [runApproveStep, runCreateStep, runWrapStep], ) + const runProcessingSequence = useCallback( + async (firstStep: ProcessingOrderStep, processingSteps: ProcessingOrderStep[]) => { + const startIndex = processingSteps.indexOf(firstStep) + if (startIndex < 0) return + + for (const step of processingSteps.slice(startIndex)) { + setProcessingOrder(state => (state.show ? { ...state, currentStep: step, errorStep: undefined } : state)) + + const isStepSuccess = await runProcessingStep(step) + if (!isStepSuccess) return + } + }, + [runProcessingStep, setProcessingOrder], + ) + + const retryProcessingStep = useCallback( + (step: ProcessingOrderStep) => { + if (processingOrder.errorStep !== step) return + + setProcessingOrder(state => ({ + ...state, + currentStep: step, + errorStep: undefined, + })) + void runProcessingSequence(step, processingOrder.steps) + }, + [processingOrder.errorStep, processingOrder.steps, runProcessingSequence, setProcessingOrder], + ) + const startProcessingOrder = useCallback(() => { - invalidateProcessingRun() + const firstStep = steps[0] + if (!firstStep) return + onStart?.() setProcessingOrder({ show: true, steps, - currentStep: steps[0], + currentStep: firstStep, completedSteps: [], }) - }, [invalidateProcessingRun, onStart, steps]) - - useEffect(() => { - if (isWrappingEth) { - wrapTransactionPendingRef.current = true - return - } - - if (wrapTransactionPendingRef.current && processingStepStartedRef.current === 'wrap') { - markProcessingStepSuccess('wrap') - } - }, [isWrappingEth, markProcessingStepSuccess]) - - useEffect(() => { - if (!processingOrder.show || !processingOrder.currentStep || processingOrder.errorStep) return - runProcessingStep(processingOrder.currentStep) - }, [processingOrder.currentStep, processingOrder.errorStep, processingOrder.show, runProcessingStep]) + void runProcessingSequence(firstStep, steps) + }, [onStart, runProcessingSequence, setProcessingOrder, steps]) return { state: processingOrder, diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useSignOrder.ts b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useSignOrder.ts index b390c84b04..3e6358c71a 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useSignOrder.ts +++ b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useSignOrder.ts @@ -1,33 +1,23 @@ import { useCallback } from 'react' import { useCreateOrderSignatureMutation } from 'services/limitOrder' -import { formatAmountOrder, getPayloadCreateOrder } from 'components/LimitOrder/helpers' +import { getPayloadCreateOrder } from 'components/LimitOrder/helpers' import { CreateOrderParam } from 'components/LimitOrder/types' -import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React } from 'hooks' -import { TransactionFlowState } from 'types/TransactionFlowState' import { formatSignature } from 'utils/transaction' import { Address } from 'utils/viem' import { signTypedDataRaw } from 'utils/walletClient' -export const useSignOrder = (setFlowState: React.Dispatch> | undefined) => { +export const useSignOrder = () => { const { account, chainId } = useActiveWeb3React() const [getMessageSignature] = useCreateOrderSignatureMutation() return useCallback( async (params: CreateOrderParam) => { - const { currencyIn, currencyOut, inputAmount, outputAmount } = params + const { currencyIn, currencyOut } = params if (!currencyIn || !currencyOut || !account) return { signature: '', salt: '' } const payload = getPayloadCreateOrder(params) - setFlowState?.({ - ...TRANSACTION_STATE_DEFAULT, - showConfirm: true, - attemptingTxn: true, - pendingText: `Sign limit order: ${formatAmountOrder(inputAmount)} ${currencyIn.symbol} to ${formatAmountOrder( - outputAmount, - )} ${currencyOut.symbol}`, - }) const messagePayload = await getMessageSignature(payload).unwrap() const rawSignature = await signTypedDataRaw({ @@ -37,6 +27,6 @@ export const useSignOrder = (setFlowState: React.Dispatch | undefined, feeBps: numbe export const useTakeLimitOrder = ({ context, - isOpen, + fillAmount, + processing, + setProcessing, }: { context: LimitOrderTakeContext | undefined - isOpen: boolean + fillAmount: string + processing: TakeOrderProcessingState + setProcessing: Dispatch> }) => { const { account, chainId, walletKey } = useActiveWeb3React() const { isSmartConnector } = useWeb3React() @@ -109,12 +112,6 @@ export const useTakeLimitOrder = ({ const estimateGas = useEstimateGasTxs() const invalidateLimitOrderTags = useInvalidateTagLimitOrder() - const [fillAmount, setFillAmount] = useState('') - const [processing, setProcessing] = useState(DEFAULT_PROCESSING) - const processingRunIdRef = useRef(0) - const processingStepStartedRef = useRef() - const wrapTransactionPendingRef = useRef(false) - const order = context?.order const payCurrency = context?.payCurrency const receiveCurrency = context?.receiveCurrency @@ -156,7 +153,6 @@ export const useTakeLimitOrder = ({ return parsedPayAmount.greaterThan(maxPayAmount) }, [maxPayAmount, parsedPayAmount]) - const { isWrappingEth, setTxHashWrapped } = useWrapEthStatus() const { execute: onWrap } = useWrapCallback( wrapAmountForOrder ? nativeCurrency : undefined, WETH[chainId], @@ -182,134 +178,105 @@ export const useTakeLimitOrder = ({ return allowanceAmount.greaterThan(parsedPayAmount) || allowanceAmount.equalTo(parsedPayAmount) }, [account, chainId, contractAddress, parsedPayAmount, payCurrency]) - const invalidateProcessingRun = useCallback(() => { - processingRunIdRef.current += 1 - processingStepStartedRef.current = undefined - wrapTransactionPendingRef.current = false - }, []) - - const isCurrentProcessingRun = useCallback((runId: number) => processingRunIdRef.current === runId, []) - - const markStepSuccess = useCallback((step: TakeOrderStep, txHash?: string) => { - processingStepStartedRef.current = undefined - if (step === 'wrap') wrapTransactionPendingRef.current = false - setProcessing(state => { - if (!state.show || state.currentStep !== step) return state - const completedSteps = state.completedSteps.includes(step) - ? state.completedSteps - : [...state.completedSteps, step] - const nextStep = state.steps[state.steps.indexOf(step) + 1] - return { ...state, currentStep: nextStep, completedSteps, txHash: txHash || state.txHash } - }) - }, []) - - const markStepError = useCallback((step: TakeOrderStep) => { - processingStepStartedRef.current = undefined - if (step === 'wrap') wrapTransactionPendingRef.current = false - setProcessing(state => { - if (!state.show || state.currentStep !== step) return state - return { ...state, errorStep: step } - }) - }, []) - - const dismissProcessing = useCallback(() => { - invalidateProcessingRun() - setProcessing(DEFAULT_PROCESSING) - }, [invalidateProcessingRun]) - - const retryStep = useCallback( - (step: TakeOrderStep) => { - invalidateProcessingRun() + const markStepSuccess = useCallback( + (step: TakeOrderStep, txHash?: string) => { setProcessing(state => { - if (state.errorStep !== step) return state - return { ...state, currentStep: step, errorStep: undefined } + if (!state.show || state.currentStep !== step) return state + const completedSteps = state.completedSteps.includes(step) + ? state.completedSteps + : [...state.completedSteps, step] + const nextStep = state.steps[state.steps.indexOf(step) + 1] + return { ...state, currentStep: nextStep, completedSteps, txHash: txHash || state.txHash } }) }, - [invalidateProcessingRun], + [setProcessing], ) - const waitForManualApproval = useCallback( - async (runId: number) => { - for (let attempt = 0; attempt < APPROVAL_CHECK_RETRY_COUNT; attempt++) { - if (!isCurrentProcessingRun(runId)) return false - const approved = await checkApprovalManually() - if (!isCurrentProcessingRun(runId)) return false - if (approved) return true - await sleep(APPROVAL_CHECK_RETRY_DELAY) - } - return false + const markStepError = useCallback( + (step: TakeOrderStep) => { + setProcessing(state => { + if (!state.show || state.currentStep !== step) return state + return { ...state, errorStep: step } + }) }, - [checkApprovalManually, isCurrentProcessingRun], + [setProcessing], ) - const startStepRun = useCallback((step: TakeOrderStep) => { - if (processingStepStartedRef.current === step) return - processingStepStartedRef.current = step - return processingRunIdRef.current - }, []) + const dismissProcessing = useCallback(() => { + setProcessing(DEFAULT_TAKE_ORDER_PROCESSING) + }, [setProcessing]) + + const waitForManualApproval = useCallback(async () => { + for (let attempt = 0; attempt < APPROVAL_CHECK_RETRY_COUNT; attempt++) { + const approved = await checkApprovalManually() + if (approved) return true + await sleep(APPROVAL_CHECK_RETRY_DELAY) + } + return false + }, [checkApprovalManually]) const runWrapStep = useCallback(() => { - if (isWrappingEth) return - const runId = startStepRun('wrap') - if (runId === undefined) return - - void (async () => { + return (async () => { try { const hash = await onWrap?.() - if (!isCurrentProcessingRun(runId)) return if (!hash) { markStepError('wrap') - return + return false } - setTxHashWrapped(hash) + const receipt = await waitForTransactionReceipt(wagmiConfig, { + chainId: chainId as (typeof wagmiConfig)['chains'][number]['id'], + hash: hash as `0x${string}`, + }) + if (receipt.status === 'reverted') { + markStepError('wrap') + return false + } + markStepSuccess('wrap') + return true } catch (error) { - if (!isCurrentProcessingRun(runId)) return notify({ type: NotificationType.ERROR, title: t`Wrap Error`, summary: getErrorMessage(error) }) markStepError('wrap') + return false } })() - }, [isCurrentProcessingRun, isWrappingEth, markStepError, notify, onWrap, setTxHashWrapped, startStepRun]) + }, [chainId, markStepError, markStepSuccess, notify, onWrap]) const runApproveStep = useCallback(() => { - const runId = startStepRun('approve') - if (runId === undefined) return - - void (async () => { + return (async () => { try { if (await checkApprovalManually()) { - if (isCurrentProcessingRun(runId)) markStepSuccess('approve') - return + markStepSuccess('approve') + return true } if (approval !== ApprovalState.PENDING) { await approveCallback(parsedPayAmount) } - const approved = await waitForManualApproval(runId) - if (!isCurrentProcessingRun(runId)) return - approved ? markStepSuccess('approve') : markStepError('approve') + const approved = await waitForManualApproval() + if (approved) { + markStepSuccess('approve') + return true + } + markStepError('approve') + return false } catch (error) { - if (!isCurrentProcessingRun(runId)) return notify({ type: NotificationType.ERROR, title: t`Approve Error`, summary: getErrorMessage(error) }) markStepError('approve') + return false } })() }, [ approveCallback, approval, checkApprovalManually, - isCurrentProcessingRun, markStepError, markStepSuccess, notify, parsedPayAmount, - startStepRun, waitForManualApproval, ]) const runFillStep = useCallback(() => { - const runId = startStepRun('fill') - if (runId === undefined) return - - void (async () => { + return (async () => { try { if (!account || !order || !parsedPayAmount || !contractAddress || !payCurrency || !receiveCurrency) { throw new Error('Wrong input') @@ -340,7 +307,6 @@ export const useTakeLimitOrder = ({ chainId, }) - if (!isCurrentProcessingRun(runId)) return if (!response?.hash) throw new Error('Transaction was not submitted') addTransactionWithType({ @@ -365,10 +331,11 @@ export const useTakeLimitOrder = ({ RTK_QUERY_TAGS.GET_LIMIT_ORDER_ACTIVE_MAKING_AMOUNT, ]) markStepSuccess('fill', response.hash) + return true } catch (error) { - if (!isCurrentProcessingRun(runId)) return notify({ type: NotificationType.ERROR, title: t`Fill Order Error`, summary: getErrorMessage(error) }) markStepError('fill') + return false } })() }, [ @@ -379,7 +346,6 @@ export const useTakeLimitOrder = ({ encodeFillOrder, getOperatorSignature, invalidateLimitOrderTags, - isCurrentProcessingRun, isSmartConnector, markStepError, markStepSuccess, @@ -390,7 +356,6 @@ export const useTakeLimitOrder = ({ receiveAmount, receiveAmountAfterFee, receiveCurrency, - startStepRun, thresholdAmount, walletKey, ]) @@ -398,19 +363,33 @@ export const useTakeLimitOrder = ({ const runStep = useCallback( (step: TakeOrderStep) => { if (step === 'wrap') { - runWrapStep() - return + return runWrapStep() } if (step === 'approve') { - runApproveStep() - return + return runApproveStep() } - runFillStep() + + return runFillStep() }, [runApproveStep, runFillStep, runWrapStep], ) + const runSequence = useCallback( + async (firstStep: TakeOrderStep, steps: TakeOrderStep[]) => { + const startIndex = steps.indexOf(firstStep) + if (startIndex < 0) return + + for (const step of steps.slice(startIndex)) { + setProcessing(state => (state.show ? { ...state, currentStep: step, errorStep: undefined } : state)) + + const isStepSuccess = await runStep(step) + if (!isStepSuccess) return + } + }, + [runStep, setProcessing], + ) + const buildProcessingSteps = useCallback((): TakeOrderStep[] => { const steps: TakeOrderStep[] = [] if (wrapAmountForOrder) steps.push('wrap') @@ -423,42 +402,39 @@ export const useTakeLimitOrder = ({ if (!contractAddress || !parsedPayAmount || insufficientBalance || exceedsAvailableAmount) return const steps = buildProcessingSteps() - invalidateProcessingRun() + const firstStep = steps[0] + if (!firstStep) return + setProcessing({ show: true, steps, - currentStep: steps[0], + currentStep: firstStep, completedSteps: [], }) + void runSequence(firstStep, steps) }, [ buildProcessingSteps, contractAddress, exceedsAvailableAmount, insufficientBalance, - invalidateProcessingRun, parsedPayAmount, + runSequence, + setProcessing, ]) - useEffect(() => { - if (!context || !isOpen) return - setFillAmount(getAvailablePayAmount(context).toExact()) - }, [context, isOpen]) - - useEffect(() => { - if (isWrappingEth) { - wrapTransactionPendingRef.current = true - return - } - - if (wrapTransactionPendingRef.current && processingStepStartedRef.current === 'wrap') { - markStepSuccess('wrap') - } - }, [isWrappingEth, markStepSuccess]) - - useEffect(() => { - if (!processing.show || !processing.currentStep || processing.errorStep) return - runStep(processing.currentStep) - }, [processing.currentStep, processing.errorStep, processing.show, runStep]) + const retryStep = useCallback( + (step: TakeOrderStep) => { + if (processing.errorStep !== step) return + + setProcessing(state => ({ + ...state, + currentStep: step, + errorStep: undefined, + })) + void runSequence(step, processing.steps) + }, + [processing.errorStep, processing.steps, runSequence, setProcessing], + ) const canSubmit = !!contractAddress && @@ -494,8 +470,6 @@ export const useTakeLimitOrder = ({ return { amount: { - fillAmount, - setFillAmount, maxPayAmount, parsedPayAmount, receiveAmount, diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useWrapEthStatus.ts b/apps/kyberswap-interface/src/components/LimitOrder/hooks/useWrapEthStatus.ts deleted file mode 100644 index 04fcbf6d9a..0000000000 --- a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useWrapEthStatus.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { useEffect, useState } from 'react' -import { usePrevious } from 'react-use' - -import { useIsTransactionPending } from 'state/transactions/hooks' - -export const useWrapEthStatus = (switchToWeth?: () => void) => { - const [txHashWrapped, setTxHashWrapped] = useState() - - const isWrappingEth = useIsTransactionPending(txHashWrapped) - const prevIsWrappingEth = usePrevious(isWrappingEth) - - useEffect(() => { - if (!isWrappingEth) { - setTxHashWrapped('') - } - }, [isWrappingEth]) - - useEffect(() => { - if (prevIsWrappingEth === true && isWrappingEth === false) { - switchToWeth?.() - } - }, [prevIsWrappingEth, isWrappingEth, switchToWeth]) - - return { isWrappingEth, setTxHashWrapped } -} From f03badbd1bd27b2b831834aad7576c6a1f0954e2 Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Fri, 19 Jun 2026 15:09:34 +0700 Subject: [PATCH 25/52] refactor(limit): organize order flows --- .../{Modals => CancelOrder}/CancelButtons.tsx | 2 +- .../CancelOrderModal.tsx | 81 +++++++++++++------ .../CancelStatusCountDown.tsx | 14 ++-- .../hooks/useCancellingOrders.ts | 0 .../hooks/useFetchActiveAllOrders.ts | 0 .../hooks}/useRequestCancelOrder.tsx | 80 +++++++++--------- .../CreateOrderConfirmModal.tsx} | 15 ++-- .../CreateOrder/CreateOrderFlow.tsx | 74 +++++++++++++++++ .../hooks/useCreateLimitOrder.tsx | 2 +- .../hooks/useLimitOrderExecution.tsx | 6 +- .../{ => CreateOrder}/hooks/useSignOrder.ts | 0 .../hooks/useWarningCreateOrder.tsx | 11 +-- .../LimitOrder/Form/LimitOrderForm.tsx | 65 +++------------ .../hooks/useLimitOrderFormState.ts | 0 .../hooks/useValidateInputError.tsx | 0 .../components/LimitOrder/MyOrders/index.tsx | 27 ++----- .../components/LimitOrder/OrderBook/index.tsx | 4 +- .../ProcessingOrderModal.tsx | 4 +- .../useProcessingOrder.ts | 0 .../LimitOrder/ReservedOrderNotice.tsx | 13 +++ .../TakeOrderConfirmModal.tsx} | 55 ++++++------- .../{hooks => TakeOrder}/useTakeLimitOrder.ts | 14 ++-- .../SwapModal/ConfirmSwapModalContent.tsx | 2 +- .../WalletPopup/Transactions/Status.tsx | 2 +- .../Transactions/TransactionItem.tsx | 2 +- .../WalletPopup/Transactions/index.tsx | 2 +- 26 files changed, 264 insertions(+), 211 deletions(-) rename apps/kyberswap-interface/src/components/LimitOrder/{Modals => CancelOrder}/CancelButtons.tsx (98%) rename apps/kyberswap-interface/src/components/LimitOrder/{Modals => CancelOrder}/CancelOrderModal.tsx (75%) rename apps/kyberswap-interface/src/components/LimitOrder/{Modals => CancelOrder}/CancelStatusCountDown.tsx (91%) rename apps/kyberswap-interface/src/components/LimitOrder/{ => CancelOrder}/hooks/useCancellingOrders.ts (100%) rename apps/kyberswap-interface/src/components/LimitOrder/{ => CancelOrder}/hooks/useFetchActiveAllOrders.ts (100%) rename apps/kyberswap-interface/src/components/LimitOrder/{MyOrders => CancelOrder/hooks}/useRequestCancelOrder.tsx (87%) rename apps/kyberswap-interface/src/components/LimitOrder/{Modals/ConfirmOrderModal.tsx => CreateOrder/CreateOrderConfirmModal.tsx} (96%) create mode 100644 apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/CreateOrderFlow.tsx rename apps/kyberswap-interface/src/components/LimitOrder/{ => CreateOrder}/hooks/useCreateLimitOrder.tsx (98%) rename apps/kyberswap-interface/src/components/LimitOrder/{ => CreateOrder}/hooks/useLimitOrderExecution.tsx (97%) rename apps/kyberswap-interface/src/components/LimitOrder/{ => CreateOrder}/hooks/useSignOrder.ts (100%) rename apps/kyberswap-interface/src/components/LimitOrder/{ => CreateOrder}/hooks/useWarningCreateOrder.tsx (85%) rename apps/kyberswap-interface/src/components/LimitOrder/{ => Form}/hooks/useLimitOrderFormState.ts (100%) rename apps/kyberswap-interface/src/components/LimitOrder/{ => Form}/hooks/useValidateInputError.tsx (100%) rename apps/kyberswap-interface/src/components/LimitOrder/{Modals => ProcessingOrder}/ProcessingOrderModal.tsx (98%) rename apps/kyberswap-interface/src/components/LimitOrder/{hooks => ProcessingOrder}/useProcessingOrder.ts (100%) create mode 100644 apps/kyberswap-interface/src/components/LimitOrder/ReservedOrderNotice.tsx rename apps/kyberswap-interface/src/components/LimitOrder/{Modals/ConfirmTakeOrderModal.tsx => TakeOrder/TakeOrderConfirmModal.tsx} (97%) rename apps/kyberswap-interface/src/components/LimitOrder/{hooks => TakeOrder}/useTakeLimitOrder.ts (100%) diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelButtons.tsx b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelButtons.tsx similarity index 98% rename from apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelButtons.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelButtons.tsx index 3ce372a398..e2cc7ae456 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelButtons.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelButtons.tsx @@ -6,7 +6,7 @@ import { ReactComponent as GasLessIcon } from 'assets/svg/gas_less_icon.svg' import { ButtonLight, ButtonOutlined, ButtonPrimary } from 'components/Button' import Column from 'components/Column' import { GasStation } from 'components/Icons' -import { CancelStatus } from 'components/LimitOrder/Modals/CancelOrderModal' +import { CancelStatus } from 'components/LimitOrder/CancelOrder/CancelOrderModal' import { DOCS_LINKS, getPayloadTracking } from 'components/LimitOrder/helpers' import { CancelOrderType, LimitOrder } from 'components/LimitOrder/types' import { MouseoverTooltip } from 'components/Tooltip' diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelOrderModal.tsx similarity index 75% rename from apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelOrderModal.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelOrderModal.tsx index 427209ecd6..ecd3672665 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelOrderModal.tsx @@ -2,20 +2,26 @@ import { ChainId } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' import { useEffect, useMemo, useState } from 'react' -import CancelButtons from 'components/LimitOrder/Modals/CancelButtons' -import CancelStatusCountDown from 'components/LimitOrder/Modals/CancelStatusCountDown' +import CancelButtons from 'components/LimitOrder/CancelOrder/CancelButtons' +import CancelStatusCountDown from 'components/LimitOrder/CancelOrder/CancelStatusCountDown' +import { + useAllActiveOrders, + useIsSupportSoftCancelOrder, +} from 'components/LimitOrder/CancelOrder/hooks/useFetchActiveAllOrders' +import { + useEstimateFee, + useProcessCancelOrder, + useRequestCancelOrder, +} from 'components/LimitOrder/CancelOrder/hooks/useRequestCancelOrder' import { Container, Header, Label, ListInfo, Note, Rate, Value } from 'components/LimitOrder/Modals/components' -import { useEstimateFee, useProcessCancelOrder } from 'components/LimitOrder/MyOrders/useRequestCancelOrder' import { calcPercentFilledOrder, formatAmountOrder } from 'components/LimitOrder/helpers' -import { useAllActiveOrders, useIsSupportSoftCancelOrder } from 'components/LimitOrder/hooks/useFetchActiveAllOrders' -import { CancelOrderFunction, CancelOrderType, LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' +import { CancelOrderType, LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' import Logo from 'components/Logo' import Modal from 'components/Modal' import { NativeCurrencies } from 'constants/tokens' import { useCurrencyV2 } from 'hooks/Tokens' import { useBaseTradeInfoLimitOrder } from 'hooks/useBaseTradeInfo' import { NETWORKS_INFO } from 'hooks/useChainsConfig' -import { TransactionFlowState } from 'types/TransactionFlowState' export enum CancelStatus { WAITING, @@ -29,17 +35,13 @@ const CancelOrderModal = ({ isCancelAll, customChainId, order, - onSubmit, onDismiss, - flowState, isOpen, }: { isCancelAll: boolean customChainId?: ChainId order: LimitOrder | undefined - onSubmit: CancelOrderFunction onDismiss?: () => void - flowState: TransactionFlowState isOpen: boolean }) => { const currencyIn = useCurrencyV2(order?.makerAsset, customChainId) || undefined @@ -59,6 +61,12 @@ const CancelOrderModal = ({ takerAssetDecimals, } = order ?? ({} as LimitOrder) + const [expiredTime, setExpiredTime] = useState(0) + const [cancelStatus, setCancelStatus] = useState(CancelStatus.WAITING) + const [cancelType, setCancelType] = useState(CancelOrderType.GAS_LESS_CANCEL) + const [attemptingTxn, setAttemptingTxn] = useState(false) + const [errorMessage, setErrorMessage] = useState('') + const { orders = [], ordersSoftCancel = [], @@ -70,16 +78,40 @@ const CancelOrderModal = ({ const supportGasLessCancel = isCancelAll ? supportCancelGaslessAllOrders : orderSupportGasless - const { onClickGaslessCancel, onClickHardCancel, expiredTime, cancelStatus, setCancelStatus } = useProcessCancelOrder( - { - isOpen, - onDismiss, - onSubmit, - getOrders: (gasLessCancel: boolean) => - isCancelAll ? (gasLessCancel ? ordersSoftCancel : orders) : order ? [order] : [], + const selectedOrders = useMemo(() => (isCancelAll ? orders : order ? [order] : []), [isCancelAll, order, orders]) + const estimateGas = useEstimateFee({ orders: selectedOrders, isCancelAll }) + + const { onCancelOrder } = useRequestCancelOrder({ + orders: selectedOrders, + isCancelAll, + onRequestStart: () => { + setAttemptingTxn(true) + setErrorMessage('') }, - ) - const [cancelType, setCancelType] = useState(CancelOrderType.GAS_LESS_CANCEL) + onRequestSuccess: () => { + setAttemptingTxn(false) + }, + onRequestError: message => { + setAttemptingTxn(false) + setErrorMessage(message) + }, + }) + const { onClickGaslessCancel, onClickHardCancel } = useProcessCancelOrder({ + isOpen, + onDismiss, + onSubmit: onCancelOrder, + expiredTime, + setExpiredTime, + setCancelStatus, + getOrders: (gasLessCancel: boolean) => + isCancelAll ? (gasLessCancel ? ordersSoftCancel : orders) : order ? [order] : [], + }) + + useEffect(() => { + setAttemptingTxn(false) + setErrorMessage('') + }, [isOpen]) + useEffect(() => { setCancelType(supportGasLessCancel ? CancelOrderType.GAS_LESS_CANCEL : CancelOrderType.HARD_CANCEL) }, [supportGasLessCancel]) @@ -140,10 +172,8 @@ const CancelOrderModal = ({ takerAssetDecimals, ]) - const formatOrders = useMemo(() => (isCancelAll ? orders : order ? [order] : []), [order, isCancelAll, orders]) - const estimateGas = useEstimateFee({ orders: formatOrders, isCancelAll }) - const disabledGasLessCancel = !supportGasLessCancel || flowState.attemptingTxn - const disabledHardCancel = flowState.attemptingTxn + const disabledGasLessCancel = !supportGasLessCancel || attemptingTxn + const disabledHardCancel = attemptingTxn const cancelGaslessText = isCancelAll ? ( ordersSoftCancel.length === orders.length || !supportGasLessCancel ? ( Gasless Cancel All Orders @@ -192,7 +222,8 @@ const CancelOrderModal = ({ expiredTime={expiredTime} cancelStatus={cancelStatus} setCancelStatus={setCancelStatus} - flowState={flowState} + attemptingTxn={attemptingTxn} + errorMessage={errorMessage} /> Hard Cancel All Orders : Hard Cancel, - disabledConfirm: flowState.attemptingTxn || (disabledGasLessCancel && disabledHardCancel), + disabledConfirm: attemptingTxn || (disabledGasLessCancel && disabledHardCancel), confirmBtnText: isCancelAll && orders.length > 1 ? Cancel Orders : Cancel Order, }} diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelStatusCountDown.tsx b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelStatusCountDown.tsx similarity index 91% rename from apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelStatusCountDown.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelStatusCountDown.tsx index d4459462ed..3b8fa3c803 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/CancelStatusCountDown.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelStatusCountDown.tsx @@ -6,12 +6,11 @@ import { ReactComponent as TimerIcon } from 'assets/svg/clock_timer.svg' import Column from 'components/Column' import { Clock } from 'components/Icons' import WarningIcon from 'components/Icons/WarningIcon' -import { CancelStatus } from 'components/LimitOrder/Modals/CancelOrderModal' +import { CancelStatus } from 'components/LimitOrder/CancelOrder/CancelOrderModal' import { DOCS_LINKS } from 'components/LimitOrder/helpers' import Loader from 'components/Loader' import useInterval from 'hooks/useInterval' import { ExternalLink } from 'theme' -import { TransactionFlowState } from 'types/TransactionFlowState' import { cn } from 'utils/cn' import { friendlyError } from 'utils/errorMessage' import { formatRemainTime } from 'utils/time' @@ -24,16 +23,15 @@ const CancelStatusCountDown = ({ expiredTime, cancelStatus, setCancelStatus, - flowState, + attemptingTxn, + errorMessage, }: { expiredTime: number cancelStatus: CancelStatus setCancelStatus: (v: CancelStatus) => void - flowState: TransactionFlowState + attemptingTxn: boolean + errorMessage: string }) => { - const { errorMessage, attemptingTxn } = flowState - const pendingText = flowState.pendingText || t`Canceling order` - const [remain, setRemain] = useState(0) const isCountDown = cancelStatus === CancelStatus.COUNTDOWN @@ -82,7 +80,7 @@ const CancelStatusCountDown = ({ ) : ( <> - {pendingText} + {t`Canceling order`} )} diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCancellingOrders.ts b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/hooks/useCancellingOrders.ts similarity index 100% rename from apps/kyberswap-interface/src/components/LimitOrder/hooks/useCancellingOrders.ts rename to apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/hooks/useCancellingOrders.ts diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useFetchActiveAllOrders.ts b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/hooks/useFetchActiveAllOrders.ts similarity index 100% rename from apps/kyberswap-interface/src/components/LimitOrder/hooks/useFetchActiveAllOrders.ts rename to apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/hooks/useFetchActiveAllOrders.ts diff --git a/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/useRequestCancelOrder.tsx b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/hooks/useRequestCancelOrder.tsx similarity index 87% rename from apps/kyberswap-interface/src/components/LimitOrder/MyOrders/useRequestCancelOrder.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/hooks/useRequestCancelOrder.tsx index 751d7af496..73c80888cc 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/useRequestCancelOrder.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/hooks/useRequestCancelOrder.tsx @@ -1,6 +1,5 @@ -import { t } from '@lingui/macro' import { readContract } from '@wagmi/core' -import { useCallback, useEffect, useRef, useState } from 'react' +import { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react' import { useCancelOrdersMutation, useCreateCancelOrderSignatureMutation, @@ -8,17 +7,15 @@ import { useInsertCancellingOrderMutation, } from 'services/limitOrder' -import { CancelStatus } from 'components/LimitOrder/Modals/CancelOrderModal' +import { CancelStatus } from 'components/LimitOrder/CancelOrder/CancelOrderModal' +import { useCancellingOrders } from 'components/LimitOrder/CancelOrder/hooks/useCancellingOrders' import { formatAmountOrder, getErrorMessage, getPayloadTracking } from 'components/LimitOrder/helpers' -import { useCancellingOrders } from 'components/LimitOrder/hooks/useCancellingOrders' import { CancelOrderFunction, CancelOrderType, LimitOrder } from 'components/LimitOrder/types' import { wagmiConfig } from 'components/Web3Provider' import { LIMIT_ORDER_ABI } from 'constants/abis' -import { TRANSACTION_STATE_DEFAULT } from 'constants/index' import { useActiveWeb3React, useWeb3React } from 'hooks' import { useTransactionAdder } from 'state/transactions/hooks' import { TRANSACTION_TYPE } from 'state/transactions/type' -import { TransactionFlowState } from 'types/TransactionFlowState' import { sendEVMTransaction } from 'utils/sendTransaction' import { formatSignature } from 'utils/transaction' import { ErrorName } from 'utils/transactionError' @@ -28,6 +25,29 @@ import { signTypedDataRaw } from 'utils/walletClient' type CancellingOrderPayload = { nonce: number } | { orderIds: number[] } +type UseRequestCancelOrderArgs = { + orders: LimitOrder[] + isCancelAll: boolean + onRequestStart?: () => void + onRequestSuccess?: () => void + onRequestError?: (message: string) => void +} + +type UseProcessCancelOrderArgs = { + onSubmit: CancelOrderFunction + onDismiss?: () => void + isOpen: boolean + getOrders: (v: boolean) => LimitOrder[] + expiredTime: number + setExpiredTime: Dispatch> + setCancelStatus: Dispatch> +} + +type UseEstimateFeeArgs = { + isCancelAll?: boolean + orders: LimitOrder[] +} + const useGetEncodeLimitOrder = () => { const { account, chainId } = useActiveWeb3React() const [getEncodeData] = useGetEncodeDataMutation() @@ -66,16 +86,13 @@ const useGetEncodeLimitOrder = () => { export const useRequestCancelOrder = ({ orders, isCancelAll, - totalOrder, -}: { - orders: LimitOrder[] - isCancelAll: boolean - totalOrder: number -}) => { + onRequestStart, + onRequestSuccess, + onRequestError, +}: UseRequestCancelOrderArgs) => { const { setCancellingOrders, cancellingOrdersIds } = useCancellingOrders() const { account, chainId, networkInfo, walletKey } = useActiveWeb3React() const { isSmartConnector } = useWeb3React() - const [flowState, setFlowState] = useState(TRANSACTION_STATE_DEFAULT) const [insertCancellingOrder] = useInsertCancellingOrderMutation() const [createCancelSignature] = useCreateCancelOrderSignatureMutation() const [cancelOrderRequest] = useCancelOrdersMutation() @@ -135,7 +152,7 @@ export const useRequestCancelOrder = ({ tokenAmountOut: amountOut, arbitrary: getPayloadTracking(order, networkInfo.name), } - : { arbitrary: { totalOrder } }, + : { arbitrary: { totalOrder: orders.length } }, }) } } @@ -176,27 +193,18 @@ export const useRequestCancelOrder = ({ const onCancelOrder = async ({ orders, cancelType }: { orders: LimitOrder[]; cancelType: CancelOrderType }) => { try { - setFlowState({ - ...TRANSACTION_STATE_DEFAULT, - pendingText: t`Canceling your orders`, - showConfirm: true, - attemptingTxn: true, - }) + onRequestStart?.() const gaslessCancel = cancelType === CancelOrderType.GAS_LESS_CANCEL const resp = await (gaslessCancel ? requestGasLessCancelOrder(orders) : requestHardCancelOrder(orders?.[0])) - setFlowState(state => ({ ...state, attemptingTxn: false })) + onRequestSuccess?.() return resp } catch (error) { - setFlowState(state => ({ - ...state, - attemptingTxn: false, - errorMessage: getErrorMessage(error), - })) + onRequestError?.(getErrorMessage(error)) throw error // keep origin error } } - return { flowState, setFlowState, onCancelOrder } + return { onCancelOrder } } export const useProcessCancelOrder = ({ @@ -204,21 +212,17 @@ export const useProcessCancelOrder = ({ onDismiss, onSubmit, getOrders, -}: { - onSubmit: CancelOrderFunction - onDismiss?: () => void - isOpen: boolean - getOrders: (v: boolean) => LimitOrder[] -}) => { + expiredTime, + setExpiredTime, + setCancelStatus, +}: UseProcessCancelOrderArgs) => { const { chainId } = useActiveWeb3React() - const [expiredTime, setExpiredTime] = useState(0) - const [cancelStatus, setCancelStatus] = useState(CancelStatus.WAITING) const controller = useRef(new AbortController()) const onResetState = useCallback(() => { setExpiredTime(0) setCancelStatus(CancelStatus.WAITING) - }, []) + }, [setCancelStatus, setExpiredTime]) useEffect(() => { if (!isOpen) { @@ -259,10 +263,10 @@ export const useProcessCancelOrder = ({ const onClickGaslessCancel = () => requestCancel(CancelOrderType.GAS_LESS_CANCEL) const onClickHardCancel = () => requestCancel(CancelOrderType.HARD_CANCEL) - return { onClickGaslessCancel, onClickHardCancel, expiredTime, cancelStatus, setCancelStatus } + return { onClickGaslessCancel, onClickHardCancel } } -export const useEstimateFee = ({ isCancelAll = false, orders }: { isCancelAll?: boolean; orders: LimitOrder[] }) => { +export const useEstimateFee = ({ isCancelAll = false, orders }: UseEstimateFeeArgs) => { const getEncodeData = useGetEncodeLimitOrder() const estimateGas = useEstimateGasTxs() const [gasFeeHardCancel, setGasFeeHardCancel] = useState('') diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/CreateOrderConfirmModal.tsx similarity index 96% rename from apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmOrderModal.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/CreateOrderConfirmModal.tsx index 990ae74709..986791fc8c 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/CreateOrderConfirmModal.tsx @@ -6,8 +6,8 @@ import { Repeat } from 'react-feather' import { ButtonPrimary, ButtonWarning } from 'components/Button' import CurrencyLogo from 'components/CurrencyLogo' +import { WORSE_PRICE_DIFF_THRESHOLD } from 'components/LimitOrder/CreateOrder/hooks/useWarningCreateOrder' import { formatAmountOrder, removeTrailingZero } from 'components/LimitOrder/helpers' -import { WORSE_PRICE_DIFF_THRESHOLD } from 'components/LimitOrder/hooks/useWarningCreateOrder' import { LimitOrderCreateContext, RateInfo } from 'components/LimitOrder/types' import Modal from 'components/Modal' import { HStack, Stack } from 'components/Stack' @@ -122,17 +122,14 @@ const MarketRateValue = ({ type Props = { order: LimitOrderCreateContext - review: { - isOpen: boolean - onDismiss?: () => void - onSubmit?: () => void - } + isOpen: boolean + onDismiss?: () => void + onSubmit?: () => void warningMessage: ReactNode[] } -const ConfirmOrderModal = ({ order, review, warningMessage }: Props) => { +const CreateOrderConfirmModal = ({ order, isOpen, onDismiss, onSubmit, warningMessage }: Props) => { const { currencyIn, currencyOut, inputAmount, outputAmount, expiredAt, rateInfo, tradeInfo, deltaRate } = order - const { isOpen, onDismiss, onSubmit } = review const [confirmed, setConfirmed] = useState(false) const shouldShowConfirmFlow = Number(deltaRate.rawPercent) < WORSE_PRICE_DIFF_THRESHOLD const shouldDisablePlaceOrder = shouldShowConfirmFlow && !confirmed @@ -225,4 +222,4 @@ const ConfirmOrderModal = ({ order, review, warningMessage }: Props) => { ) } -export default ConfirmOrderModal +export default CreateOrderConfirmModal diff --git a/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/CreateOrderFlow.tsx b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/CreateOrderFlow.tsx new file mode 100644 index 0000000000..f5794cfc96 --- /dev/null +++ b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/CreateOrderFlow.tsx @@ -0,0 +1,74 @@ +import { useCallback, useState } from 'react' +import { useNavigate } from 'react-router-dom' + +import CreateOrderConfirmModal from 'components/LimitOrder/CreateOrder/CreateOrderConfirmModal' +import { useCreateLimitOrder } from 'components/LimitOrder/CreateOrder/hooks/useCreateLimitOrder' +import type { useLimitOrderExecution } from 'components/LimitOrder/CreateOrder/hooks/useLimitOrderExecution' +import ProcessingOrderModal from 'components/LimitOrder/ProcessingOrder/ProcessingOrderModal' +import { DEFAULT_PROCESSING_ORDER, useProcessingOrder } from 'components/LimitOrder/ProcessingOrder/useProcessingOrder' +import { LimitOrderCreateContext, LimitOrderTab } from 'components/LimitOrder/types' +import { APP_PATHS } from 'constants/index' +import { NETWORKS_INFO } from 'hooks/useChainsConfig' +import { currencyId } from 'utils/currencyId' + +type CreateOrderExecution = ReturnType + +type CreateOrderFlowProps = { + order: LimitOrderCreateContext + searchParams: URLSearchParams + isOpen: boolean + onDismiss?: () => void + execution: CreateOrderExecution +} + +const CreateOrderFlow = ({ order, searchParams, isOpen, onDismiss, execution }: CreateOrderFlowProps) => { + const navigate = useNavigate() + const { currencyIn, currencyOut, chainId } = order + const [processingOrder, setProcessingOrder] = useState(DEFAULT_PROCESSING_ORDER) + + const createOrder = useCreateLimitOrder({ + order, + searchParams, + estimateUSD: execution.estimateUSD, + onError: execution.handleError, + onSuccess: execution.resetForm, + }) + + const viewCreatedOrder = useCallback(() => { + const currencyPair = + currencyIn && currencyOut ? `/${currencyId(currencyIn, chainId)}-to-${currencyId(currencyOut, chainId)}` : '' + const search = new URLSearchParams({ tab: LimitOrderTab.MY_ORDER }).toString() + + navigate(`${APP_PATHS.LIMIT}/${NETWORKS_INFO[chainId].route}${currencyPair}?${search}`) + }, [chainId, currencyIn, currencyOut, navigate]) + + const processing = useProcessingOrder({ + processingOrder, + setProcessingOrder, + ...execution.processing, + onCreateOrder: createOrder.submitCreateOrderWithTracking, + onError: execution.handleError, + onStart: onDismiss, + }) + + return ( + <> + + + + + ) +} + +export default CreateOrderFlow diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCreateLimitOrder.tsx b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useCreateLimitOrder.tsx similarity index 98% rename from apps/kyberswap-interface/src/components/LimitOrder/hooks/useCreateLimitOrder.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useCreateLimitOrder.tsx index 9635405eb5..d6f9d11762 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useCreateLimitOrder.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useCreateLimitOrder.tsx @@ -4,9 +4,9 @@ import { useCallback } from 'react' import { useCreateOrderMutation } from 'services/limitOrder' import { NotificationType } from 'components/Announcement/type' +import { useSignOrder } from 'components/LimitOrder/CreateOrder/hooks/useSignOrder' import { SummaryNotifyOrderPlaced } from 'components/LimitOrder/MyOrders/SummaryNotify' import { calcUsdPrices, getPayloadCreateOrder, removeTrailingZero } from 'components/LimitOrder/helpers' -import { useSignOrder } from 'components/LimitOrder/hooks/useSignOrder' import { CreateOrderParam, LimitOrderCreateContext } from 'components/LimitOrder/types' import { getTipLinkAttribution } from 'components/TipLinkGeneratorModal/shared' import { useActiveWeb3React } from 'hooks' diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderExecution.tsx b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useLimitOrderExecution.tsx similarity index 97% rename from apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderExecution.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useLimitOrderExecution.tsx index 25b132105e..8651125d20 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderExecution.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useLimitOrderExecution.tsx @@ -5,10 +5,10 @@ import JSBI from 'jsbi' import { useCallback, useEffect, useMemo } from 'react' import { useGetLOConfigQuery, useGetTotalActiveMakingAmountQuery } from 'services/limitOrder' +import { useWarningCreateOrder } from 'components/LimitOrder/CreateOrder/hooks/useWarningCreateOrder' +import { useValidateInputError } from 'components/LimitOrder/Form/hooks/useValidateInputError' +import { ProcessingOrderStep } from 'components/LimitOrder/ProcessingOrder/useProcessingOrder' import { calcUsdPrices, getErrorMessage, removeTrailingZero } from 'components/LimitOrder/helpers' -import { ProcessingOrderStep } from 'components/LimitOrder/hooks/useProcessingOrder' -import { useValidateInputError } from 'components/LimitOrder/hooks/useValidateInputError' -import { useWarningCreateOrder } from 'components/LimitOrder/hooks/useWarningCreateOrder' import { LimitOrderCreateContext } from 'components/LimitOrder/types' import { wagmiConfig } from 'components/Web3Provider' import { ERC20_ABI } from 'constants/abis' diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useSignOrder.ts b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useSignOrder.ts similarity index 100% rename from apps/kyberswap-interface/src/components/LimitOrder/hooks/useSignOrder.ts rename to apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useSignOrder.ts diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useWarningCreateOrder.tsx b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useWarningCreateOrder.tsx similarity index 85% rename from apps/kyberswap-interface/src/components/LimitOrder/hooks/useWarningCreateOrder.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useWarningCreateOrder.tsx index 3a3cca1258..ba6656f3d1 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useWarningCreateOrder.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/CreateOrder/hooks/useWarningCreateOrder.tsx @@ -1,8 +1,8 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans } from '@lingui/macro' import { PropsWithChildren, useMemo } from 'react' -import { Link } from 'react-router-dom' +import ReservedOrderNotice from 'components/LimitOrder/ReservedOrderNotice' import { DeltaRateLimitOrder, LimitOrderStatus, LimitOrderTab } from 'components/LimitOrder/types' const AprHighlight = ({ children }: PropsWithChildren) => {children} @@ -11,15 +11,6 @@ const WarningHighlight = ({ children }: PropsWithChildren) => ( {children} ) -export const ReservedOrderNotice = ({ symbol, to }: { symbol: string | undefined; to: string }) => ( - - - Notice: Some of your {symbol} is already reserved by an open Limit Order - - review it here. - - -) - export const WORSE_PRICE_DIFF_THRESHOLD = -5 export const BETTER_PRICE_DIFF_THRESHOLD = 30 diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx index d9a7a20469..aa333b6c1b 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/Form/LimitOrderForm.tsx @@ -1,24 +1,18 @@ import { Currency } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' -import { ReactNode, memo, useCallback, useState } from 'react' -import { useNavigate } from 'react-router-dom' +import { ReactNode, memo, useState } from 'react' import { ButtonLight, ButtonPrimary, ButtonWarning } from 'components/Button' import DateTimePicker from 'components/DateTimePicker' +import CreateOrderFlow from 'components/LimitOrder/CreateOrder/CreateOrderFlow' +import { useLimitOrderExecution } from 'components/LimitOrder/CreateOrder/hooks/useLimitOrderExecution' import LimitOrderExpirySection from 'components/LimitOrder/Form/LimitOrderExpirySection' import LimitOrderRateSection, { useGetDeltaRateLimitOrder } from 'components/LimitOrder/Form/LimitOrderRateSection' import LimitOrderTokenSection from 'components/LimitOrder/Form/LimitOrderTokenSection' import MarketPrice from 'components/LimitOrder/Form/MarketPrice' -import ConfirmOrderModal from 'components/LimitOrder/Modals/ConfirmOrderModal' -import ProcessingOrderModal from 'components/LimitOrder/Modals/ProcessingOrderModal' -import { useCreateLimitOrder } from 'components/LimitOrder/hooks/useCreateLimitOrder' -import { useLimitOrderExecution } from 'components/LimitOrder/hooks/useLimitOrderExecution' -import { useLimitOrderFormState } from 'components/LimitOrder/hooks/useLimitOrderFormState' -import { DEFAULT_PROCESSING_ORDER, useProcessingOrder } from 'components/LimitOrder/hooks/useProcessingOrder' -import { LimitOrderTab } from 'components/LimitOrder/types' +import { useLimitOrderFormState } from 'components/LimitOrder/Form/hooks/useLimitOrderFormState' import { NetworkSelector } from 'components/NetworkSelector' import { HStack, Stack } from 'components/Stack' -import { APP_PATHS } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { NETWORKS_INFO } from 'hooks/useChainsConfig' import usePageLocation from 'hooks/usePageLocation' @@ -26,7 +20,6 @@ import { useChangeNetwork } from 'hooks/web3/useChangeNetwork' import ErrorWarningPanel from 'pages/Bridge/ErrorWarning' import { useWalletModalToggle } from 'state/application/hooks' import { useLimitState } from 'state/limit/hooks' -import { currencyId } from 'utils/currencyId' type LimitOrderFormProps = { currencyIn?: Currency @@ -68,10 +61,8 @@ const LimitOrderForm = ({ currencyIn: currencyInProp, currencyOut: currencyOutPr const { changeNetwork } = useChangeNetwork() const { account } = useActiveWeb3React() const { isEmbeddedSwap } = usePageLocation() - const navigate = useNavigate() const [showReview, setShowReview] = useState(false) - const [processingOrder, setProcessingOrder] = useState(DEFAULT_PROCESSING_ORDER) const { currencyIn, currencyOut } = useLimitOrderCurrencies({ currencyIn: currencyInProp, @@ -110,34 +101,7 @@ const LimitOrderForm = ({ currencyIn: currencyInProp, currencyOut: currencyOutPr switchToWeth: form.switchToWeth, }) - const { balance, estimateUSD, review, processing: executionProcessing, tracking, validation } = execution - - const createOrder = useCreateLimitOrder({ - order, - searchParams: form.searchParams, - estimateUSD, - onError: execution.handleError, - onSuccess: execution.resetForm, - }) - - const processing = useProcessingOrder({ - processingOrder, - setProcessingOrder, - ...executionProcessing, - onCreateOrder: createOrder.submitCreateOrderWithTracking, - onError: execution.handleError, - onStart: review.closeReview, - }) - - const viewCreatedOrder = useCallback(() => { - const currencyPair = - currencyIn && currencyOut - ? `/${currencyId(currencyIn, form.chainId)}-to-${currencyId(currencyOut, form.chainId)}` - : '' - const search = new URLSearchParams({ tab: LimitOrderTab.MY_ORDER }).toString() - - navigate(`${APP_PATHS.LIMIT}/${form.networkInfo.route}${currencyPair}?${search}`) - }, [currencyIn, currencyOut, form.chainId, form.networkInfo.route, navigate]) + const { balance, estimateUSD, review, tracking, validation } = execution const validationError = validation.inputError || validation.outputError const disableReviewButton = validation.isNotFillAllInput || !!validationError || balance.insufficientBalance @@ -247,14 +211,12 @@ const LimitOrderForm = ({ currencyIn: currencyInProp, currencyOut: currencyOutPr - - - ) } diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderFormState.ts b/apps/kyberswap-interface/src/components/LimitOrder/Form/hooks/useLimitOrderFormState.ts similarity index 100% rename from apps/kyberswap-interface/src/components/LimitOrder/hooks/useLimitOrderFormState.ts rename to apps/kyberswap-interface/src/components/LimitOrder/Form/hooks/useLimitOrderFormState.ts diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useValidateInputError.tsx b/apps/kyberswap-interface/src/components/LimitOrder/Form/hooks/useValidateInputError.tsx similarity index 100% rename from apps/kyberswap-interface/src/components/LimitOrder/hooks/useValidateInputError.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/Form/hooks/useValidateInputError.tsx diff --git a/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx index 4e747378c3..5646cab097 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/MyOrders/index.tsx @@ -8,21 +8,20 @@ import { useGetListOrdersQuery } from 'services/limitOrder' import { ReactComponent as NoDataIcon } from 'assets/svg/no_data.svg' import { ButtonLight } from 'components/Button' import InfoHelper from 'components/InfoHelper' -import CancelOrderModal from 'components/LimitOrder/Modals/CancelOrderModal' +import CancelOrderModal from 'components/LimitOrder/CancelOrder/CancelOrderModal' +import { useCancellingOrders } from 'components/LimitOrder/CancelOrder/hooks/useCancellingOrders' import OrderItem from 'components/LimitOrder/MyOrders/OrderItem' -import { useRequestCancelOrder } from 'components/LimitOrder/MyOrders/useRequestCancelOrder' import { formatAmountOrder, formatRateLimitOrder, getPayloadTracking, isActiveStatus, } from 'components/LimitOrder/helpers' -import { useCancellingOrders } from 'components/LimitOrder/hooks/useCancellingOrders' import { LimitOrder, LimitOrderStatus } from 'components/LimitOrder/types' import Pagination from 'components/Pagination' import SearchInput from 'components/SearchInput' import Select from 'components/Select' -import { RTK_QUERY_TAGS, TRANSACTION_STATE_DEFAULT } from 'constants/index' +import { RTK_QUERY_TAGS } from 'constants/index' import { useActiveWeb3React } from 'hooks' import { useInvalidateTagLimitOrder } from 'hooks/useInvalidateTags' import usePageLocation from 'hooks/usePageLocation' @@ -191,12 +190,6 @@ const MyOrders = ({ customChainId }: { customChainId?: ChainId }) => { { skip: !account, pollingInterval: 10_000, refetchOnFocus: true }, ) - const { flowState, setFlowState, onCancelOrder } = useRequestCancelOrder({ - orders, - isCancelAll, - totalOrder, - }) - const hasOrders = orders.length > 0 const showPagination = hasOrders && totalOrder > PAGE_SIZE const showCancelAll = hasOrders && isTabActive @@ -294,29 +287,27 @@ const MyOrders = ({ customChainId }: { customChainId?: ChainId }) => { ) const hideConfirmCancel = useCallback(() => { - setFlowState(TRANSACTION_STATE_DEFAULT) setIsOpenCancel(false) setIsCancelAll(false) setTimeout(() => { setCurrentOrder(undefined) }, 300) - }, [setFlowState]) + }, []) - const showConfirmCancel = useCallback( + const openCancelModal = useCallback( (order?: LimitOrder) => { setCurrentOrder(order) - setFlowState({ ...TRANSACTION_STATE_DEFAULT, showConfirm: true }) setIsOpenCancel(true) setIsCancelAll(false) if (order) { trackingHandler(TRACKING_EVENT_TYPE.LO_CLICK_CANCEL_ORDER, getPayloadTracking(order, networkInfo.name)) } }, - [trackingHandler, setFlowState, networkInfo], + [trackingHandler, networkInfo], ) const onCancelAllOrder = () => { - showConfirmCancel() + openCancelModal() setIsCancelAll(true) } @@ -388,7 +379,7 @@ const MyOrders = ({ customChainId }: { customChainId?: ChainId }) => { isOrderCancelling={isOrderCancelling} key={order.id} order={order} - onCancelOrder={showConfirmCancel} + onCancelOrder={openCancelModal} /> ))}
@@ -439,9 +430,7 @@ const MyOrders = ({ customChainId }: { customChainId?: ChainId }) => { { ? visibleBuyOrders.map(order => ) : isReversedOrdersLoaded && } - setTakeOrderContext(undefined)} diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/ProcessingOrder/ProcessingOrderModal.tsx similarity index 98% rename from apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingOrderModal.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/ProcessingOrder/ProcessingOrderModal.tsx index 47b522dbec..3bf4ceb0fd 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ProcessingOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/ProcessingOrder/ProcessingOrderModal.tsx @@ -4,8 +4,8 @@ import { AlertCircle, RotateCw } from 'react-feather' import { ButtonLight, ButtonOutlined, ButtonPrimary } from 'components/Button' import { CheckCircle } from 'components/Icons' -import type { ProcessingOrderStep } from 'components/LimitOrder/hooks/useProcessingOrder' -import type { TakeOrderStep } from 'components/LimitOrder/hooks/useTakeLimitOrder' +import type { ProcessingOrderStep } from 'components/LimitOrder/ProcessingOrder/useProcessingOrder' +import type { TakeOrderStep } from 'components/LimitOrder/TakeOrder/useTakeLimitOrder' import Loader from 'components/Loader' import Modal from 'components/Modal' import { Center, HStack, Stack } from 'components/Stack' diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useProcessingOrder.ts b/apps/kyberswap-interface/src/components/LimitOrder/ProcessingOrder/useProcessingOrder.ts similarity index 100% rename from apps/kyberswap-interface/src/components/LimitOrder/hooks/useProcessingOrder.ts rename to apps/kyberswap-interface/src/components/LimitOrder/ProcessingOrder/useProcessingOrder.ts diff --git a/apps/kyberswap-interface/src/components/LimitOrder/ReservedOrderNotice.tsx b/apps/kyberswap-interface/src/components/LimitOrder/ReservedOrderNotice.tsx new file mode 100644 index 0000000000..b197b7cd93 --- /dev/null +++ b/apps/kyberswap-interface/src/components/LimitOrder/ReservedOrderNotice.tsx @@ -0,0 +1,13 @@ +import { Trans } from '@lingui/macro' +import { Link } from 'react-router-dom' + +const ReservedOrderNotice = ({ symbol, to }: { symbol: string | undefined; to: string }) => ( + + + Notice: Some of your {symbol} is already reserved by an open Limit Order - + review it here. + + +) + +export default ReservedOrderNotice diff --git a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmTakeOrderModal.tsx b/apps/kyberswap-interface/src/components/LimitOrder/TakeOrder/TakeOrderConfirmModal.tsx similarity index 97% rename from apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmTakeOrderModal.tsx rename to apps/kyberswap-interface/src/components/LimitOrder/TakeOrder/TakeOrderConfirmModal.tsx index 18c1f46e1b..e22fb7ccf2 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/Modals/ConfirmTakeOrderModal.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/TakeOrder/TakeOrderConfirmModal.tsx @@ -6,9 +6,9 @@ import { useNavigate } from 'react-router-dom' import { ButtonOutlined, ButtonPrimary } from 'components/Button' import CurrencyLogo from 'components/CurrencyLogo' -import ProcessingOrderModal from 'components/LimitOrder/Modals/ProcessingOrderModal' +import ProcessingOrderModal from 'components/LimitOrder/ProcessingOrder/ProcessingOrderModal' +import { DEFAULT_TAKE_ORDER_PROCESSING, useTakeLimitOrder } from 'components/LimitOrder/TakeOrder/useTakeLimitOrder' import { removeTrailingZero } from 'components/LimitOrder/helpers' -import { DEFAULT_TAKE_ORDER_PROCESSING, useTakeLimitOrder } from 'components/LimitOrder/hooks/useTakeLimitOrder' import { LimitOrderTab, LimitOrderTakeContext } from 'components/LimitOrder/types' import Modal from 'components/Modal' import NumericalInput from 'components/NumericalInput' @@ -44,7 +44,7 @@ const TokenBadge = ({ amount, symbol }: { amount?: CurrencyAmount; sym ) -const ConfirmTakeOrderModal = ({ +const TakeOrderConfirmModal = ({ context, isOpen, onDismiss, @@ -55,15 +55,17 @@ const ConfirmTakeOrderModal = ({ }) => { const navigate = useNavigate() const [fillAmount, setFillAmount] = useState('') + const [showInvertedRate, setShowInvertedRate] = useState(false) + const [estimatedGasUsd, setEstimatedGasUsd] = useState('') const [processingState, setProcessingState] = useState(DEFAULT_TAKE_ORDER_PROCESSING) + const takeOrder = useTakeLimitOrder({ context, fillAmount, processing: processingState, setProcessing: setProcessingState, }) - const { estimateTxGas } = takeOrder - const [showInvertedRate, setShowInvertedRate] = useState(false) + const { maxPayAmount, parsedPayAmount, @@ -74,8 +76,7 @@ const ConfirmTakeOrderModal = ({ insufficientBalance, canSubmit, } = takeOrder.amount - - const [estimatedGasUsd, setEstimatedGasUsd] = useState('') + const { estimateTxGas } = takeOrder const isConfirmOpen = isOpen && !takeOrder.processing.state.show useEffect(() => { @@ -83,6 +84,25 @@ const ConfirmTakeOrderModal = ({ setFillAmount(maxPayAmount?.toExact() || '') }, [context, isOpen, maxPayAmount]) + useEffect(() => { + const controller = new AbortController() + const fetchGas = async () => { + try { + if (!isConfirmOpen || !canSubmit) { + setEstimatedGasUsd('') + return + } + const gas = await estimateTxGas() + if (controller.signal.aborted) return + setEstimatedGasUsd(gas?.gasInUsd ? gas.gasInUsd.toString() : '') + } catch { + if (!controller.signal.aborted) setEstimatedGasUsd('') + } + } + fetchGas() + return () => controller.abort() + }, [canSubmit, estimateTxGas, isConfirmOpen]) + const handleDismiss = () => { onDismiss?.() } @@ -107,25 +127,6 @@ const ConfirmTakeOrderModal = ({ navigate(`${APP_PATHS.LIMIT}/${route}?${search}`) } - useEffect(() => { - const controller = new AbortController() - const fetchGas = async () => { - try { - if (!isConfirmOpen || !canSubmit) { - setEstimatedGasUsd('') - return - } - const gas = await estimateTxGas() - if (controller.signal.aborted) return - setEstimatedGasUsd(gas?.gasInUsd ? gas.gasInUsd.toString() : '') - } catch { - if (!controller.signal.aborted) setEstimatedGasUsd('') - } - } - fetchGas() - return () => controller.abort() - }, [canSubmit, estimateTxGas, isConfirmOpen]) - const rate = (() => { if (!context) return '--' if (!showInvertedRate) return formatRate(context) @@ -262,4 +263,4 @@ const ConfirmTakeOrderModal = ({ ) } -export default ConfirmTakeOrderModal +export default TakeOrderConfirmModal diff --git a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useTakeLimitOrder.ts b/apps/kyberswap-interface/src/components/LimitOrder/TakeOrder/useTakeLimitOrder.ts similarity index 100% rename from apps/kyberswap-interface/src/components/LimitOrder/hooks/useTakeLimitOrder.ts rename to apps/kyberswap-interface/src/components/LimitOrder/TakeOrder/useTakeLimitOrder.ts index 8b499f0f57..baeadda58d 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/hooks/useTakeLimitOrder.ts +++ b/apps/kyberswap-interface/src/components/LimitOrder/TakeOrder/useTakeLimitOrder.ts @@ -153,6 +153,13 @@ export const useTakeLimitOrder = ({ return parsedPayAmount.greaterThan(maxPayAmount) }, [maxPayAmount, parsedPayAmount]) + const canSubmit = + !!contractAddress && + !!parsedPayAmount && + JSBI.greaterThan(parsedPayAmount.quotient, JSBI.BigInt(0)) && + !exceedsAvailableAmount && + !insufficientBalance + const { execute: onWrap } = useWrapCallback( wrapAmountForOrder ? nativeCurrency : undefined, WETH[chainId], @@ -436,13 +443,6 @@ export const useTakeLimitOrder = ({ [processing.errorStep, processing.steps, runSequence, setProcessing], ) - const canSubmit = - !!contractAddress && - !!parsedPayAmount && - JSBI.greaterThan(parsedPayAmount.quotient, JSBI.BigInt(0)) && - !exceedsAvailableAmount && - !insufficientBalance - const estimateTxGas = useCallback(async () => { if (!account || !order || !parsedPayAmount || !contractAddress) return null const operatorSignatures = await getOperatorSignature({ chainId, orderIds: [order.id] }).unwrap() diff --git a/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx b/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx index 762ebdefe5..0421c40dde 100644 --- a/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx +++ b/apps/kyberswap-interface/src/components/SwapForm/SwapModal/ConfirmSwapModalContent.tsx @@ -9,8 +9,8 @@ import { calculatePriceImpact } from 'services/route/utils' import { ButtonOutlined, ButtonPrimary } from 'components/Button' import Dots from 'components/Dots' import InfoHelper from 'components/InfoHelper' +import ReservedOrderNotice from 'components/LimitOrder/ReservedOrderNotice' import { calcPercentFilledOrder } from 'components/LimitOrder/helpers' -import { ReservedOrderNotice } from 'components/LimitOrder/hooks/useWarningCreateOrder' import { LimitOrderStatus, LimitOrderTab } from 'components/LimitOrder/types' import Loader from 'components/Loader' import SlippageWarningNote from 'components/SlippageWarningNote' diff --git a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/Status.tsx b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/Status.tsx index 7d8bd35a9d..9b5df42d3f 100644 --- a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/Status.tsx +++ b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/Status.tsx @@ -7,7 +7,7 @@ import { useDispatch } from 'react-redux' import { CheckCircle } from 'components/Icons' import IconFailure from 'components/Icons/Failed' import WarningIcon from 'components/Icons/WarningIcon' -import { CancellingOrderInfo } from 'components/LimitOrder/hooks/useCancellingOrders' +import { CancellingOrderInfo } from 'components/LimitOrder/CancelOrder/hooks/useCancellingOrders' import Loader from 'components/Loader' import { PrimaryText } from 'components/WalletPopup/Transactions/TransactionItem' import { isTxsPendingTooLong as isShowPendingWarning } from 'components/WalletPopup/Transactions/helper' diff --git a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/TransactionItem.tsx b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/TransactionItem.tsx index ee30a944a9..29237e382f 100644 --- a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/TransactionItem.tsx +++ b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/TransactionItem.tsx @@ -4,7 +4,7 @@ import { CSSProperties, ReactNode, forwardRef } from 'react' import { ReactComponent as NftIcon } from 'assets/svg/nft_icon.svg' import SendIcon from 'components/Icons/SendIcon' -import { CancellingOrderInfo } from 'components/LimitOrder/hooks/useCancellingOrders' +import { CancellingOrderInfo } from 'components/LimitOrder/CancelOrder/hooks/useCancellingOrders' import Row from 'components/Row' import ContractAddress from 'components/WalletPopup/Transactions/ContractAddress' import DeltaTokenAmount from 'components/WalletPopup/Transactions/DeltaTokenAmount' diff --git a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx index 93390da3e4..740ab53298 100644 --- a/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx +++ b/apps/kyberswap-interface/src/components/WalletPopup/Transactions/index.tsx @@ -6,7 +6,7 @@ import { VariableSizeList } from 'react-window' import { ButtonOutlined, ButtonPrimary } from 'components/Button' import InfoHelper from 'components/InfoHelper' -import { CancellingOrderInfo, useCancellingOrders } from 'components/LimitOrder/hooks/useCancellingOrders' +import { CancellingOrderInfo, useCancellingOrders } from 'components/LimitOrder/CancelOrder/hooks/useCancellingOrders' import Modal from 'components/Modal' import Row, { RowBetween } from 'components/Row' import Tab from 'components/WalletPopup/Transactions/Tab' From e1e40c0e7363ebd43c5db79da48bf29d0d02e5b7 Mon Sep 17 00:00:00 2001 From: Khac Kien Date: Fri, 19 Jun 2026 16:13:14 +0700 Subject: [PATCH 26/52] refactor(limit-order): polish order modals --- .../LimitOrder/CancelOrder/CancelButtons.tsx | 28 +-- .../CancelOrder/CancelOrderModal.tsx | 80 +++---- .../CancelOrder/CancelStatusCountDown.tsx | 18 +- .../CreateOrder/CreateOrderConfirmModal.tsx | 110 ++------- .../hooks/useWarningCreateOrder.tsx | 2 +- .../Form/LimitOrderExpirySection.tsx | 4 +- .../LimitOrder/Form/LimitOrderForm.tsx | 4 +- .../LimitOrder/Form/LimitOrderRateSection.tsx | 3 + .../LimitOrder/Form/MarketPrice.tsx | 8 +- .../LimitOrder/Modals/components.tsx | 217 ++++++++++-------- .../ProcessingOrder/ProcessingOrderModal.tsx | 2 +- .../TakeOrder/TakeOrderConfirmModal.tsx | 45 ++-- .../src/theme/components.tsx | 2 +- 13 files changed, 244 insertions(+), 279 deletions(-) diff --git a/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelButtons.tsx b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelButtons.tsx index e2cc7ae456..92fa1846bd 100644 --- a/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelButtons.tsx +++ b/apps/kyberswap-interface/src/components/LimitOrder/CancelOrder/CancelButtons.tsx @@ -4,11 +4,11 @@ import { Check } from 'react-feather' import { ReactComponent as GasLessIcon } from 'assets/svg/gas_less_icon.svg' import { ButtonLight, ButtonOutlined, ButtonPrimary } from 'components/Button' -import Column from 'components/Column' import { GasStation } from 'components/Icons' import { CancelStatus } from 'components/LimitOrder/CancelOrder/CancelOrderModal' import { DOCS_LINKS, getPayloadTracking } from 'components/LimitOrder/helpers' import { CancelOrderType, LimitOrder } from 'components/LimitOrder/types' +import { HStack, Stack } from 'components/Stack' import { MouseoverTooltip } from 'components/Tooltip' import { useActiveWeb3React } from 'hooks' import useTheme from 'hooks/useTheme' @@ -17,9 +17,9 @@ import { ExternalLink } from 'theme' import { formatDisplayNumber } from 'utils/numbers' const ButtonWrapper = ({ children, style }: { children: ReactNode; style?: CSSProperties }) => ( -
+ {children} -
+ ) const ButtonGroup = ({ @@ -37,10 +37,10 @@ const ButtonGroup = ({ }) => { return ( - + {buttonGasless} {showGaslessNote && ( - + Cancel without paying gas.
Cancellation may not be instant.{' '} @@ -48,16 +48,16 @@ const ButtonGroup = ({
)} -
- + + {buttonHardCancel} - + Cancel immediately by paying {gasAmountDisplay} gas fees.{' '} Learn more ↗︎ - +
) } @@ -134,7 +134,7 @@ const CancelButtons = ({ if (isCancelDone) return ( - +  Close @@ -143,14 +143,14 @@ const CancelButtons = ({ if (isTimeout) return ( - + Try Again ) - const propsGasless = { height: '40px', width: '100%' } - const propsHardCancel = { style: { height: '40px', width: '100%' }, disabled: disabledHardCancel } + const propsGasless = { height: '44px', width: '100%' } + const propsHardCancel = { style: { height: '44px', width: '100%' }, disabled: disabledHardCancel } if (isCountDown) return ( @@ -222,7 +222,7 @@ const CancelButtons = ({ { - if (!order) return [] + const orderSummary = useMemo(() => { + if (!order) return undefined const native = NativeCurrencies[Number(order.chainId) as ChainId] const isNative = order.nativeOutput && takerAssetSymbol.toLowerCase() === native?.wrapped.symbol?.toLowerCase() const takerSymbol = isNative ? native?.symbol || takerAssetSymbol : takerAssetSymbol - return [ - { - label: t`I pay`, - content: ( - - - - {formatAmountOrder(makingAmount, makerAssetDecimals)} {makerAssetSymbol} - - - ), - }, - { - label: t`and receive`, - content: ( - - - - {formatAmountOrder(takingAmount, takerAssetDecimals)} {takerSymbol} - - - ), - }, - { - label: t`at`, - content: , - }, - ] + return { + inputCurrency: ( + + + + {formatAmountOrder(makingAmount, makerAssetDecimals)} {makerAssetSymbol} + + + ), + outputCurrency: ( + + + + {formatAmountOrder(takingAmount, takerAssetDecimals)} {takerSymbol} + + + ), + } }, [ makerAssetLogoURL, makerAssetSymbol, @@ -191,11 +180,16 @@ const CancelOrderModal = ({ const handleDismiss = () => onDismiss?.() return ( - +
{isCancelAll && isWaiting ? ( -