diff --git a/.env.dev b/.env.dev index 66d33fd4bb..8e846a857a 100644 --- a/.env.dev +++ b/.env.dev @@ -25,8 +25,7 @@ VITE_GTM_ID= VITE_GOOGLE_RECAPTCHA_KEY=6Lc7yg0iAAAAALhS4C4Ez5hqMBub8hKdFvvr9sfc VITE_POOL_FARM_BASE_URL=https://pool-farm.dev.kyberengineering.io -VITE_LIMIT_ORDER_API_WRITE=https://limit-order.dev.kyberengineering.io/write/api -VITE_LIMIT_ORDER_API_READ=https://limit-order.dev.kyberengineering.io/read-ks/api +VITE_LIMIT_ORDER_API=https://limit-order.dev.kyberengineering.io VITE_BLOCK_SERVICE_API=https://block.kyberswap.com # Kyber DAO Apis diff --git a/.env.production b/.env.production index 25a41bb57f..43b5b28a29 100644 --- a/.env.production +++ b/.env.production @@ -25,8 +25,7 @@ VITE_GTM_ID=GTM-TRQCJ8F VITE_GOOGLE_RECAPTCHA_KEY=6LfgKRMiAAAAAPDTmXAM9LZLYAlE1zACfCJXup96 VITE_POOL_FARM_BASE_URL=https://pool-farm.kyberswap.com -VITE_LIMIT_ORDER_API_WRITE=https://limit-order.kyberswap.com/write/api -VITE_LIMIT_ORDER_API_READ=https://limit-order.kyberswap.com/read-ks/api +VITE_LIMIT_ORDER_API=https://limit-order.kyberswap.com VITE_BLOCK_SERVICE_API=https://block.kyberswap.com # Kyber DAO Apis diff --git a/.env.stg b/.env.stg index df9dddb900..984c5d45eb 100644 --- a/.env.stg +++ b/.env.stg @@ -24,8 +24,7 @@ VITE_GTM_ID= VITE_GOOGLE_RECAPTCHA_KEY=6Lc7yg0iAAAAALhS4C4Ez5hqMBub8hKdFvvr9sfc VITE_POOL_FARM_BASE_URL=https://pool-farm.kyberswap.com -VITE_LIMIT_ORDER_API_WRITE=https://limit-order.stg.kyberengineering.io/write/api -VITE_LIMIT_ORDER_API_READ=https://limit-order.stg.kyberengineering.io/read-ks/api +VITE_LIMIT_ORDER_API=https://limit-order.stg.kyberengineering.io VITE_BLOCK_SERVICE_API=https://block.kyberswap.com # Kyber DAO Apis diff --git a/src/assets/svg/clock_timer.svg b/src/assets/svg/clock_timer.svg new file mode 100644 index 0000000000..fd978906c5 --- /dev/null +++ b/src/assets/svg/clock_timer.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svg/gas_less_icon.svg b/src/assets/svg/gas_less_icon.svg new file mode 100644 index 0000000000..a22379a4a4 --- /dev/null +++ b/src/assets/svg/gas_less_icon.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/svg/history.svg b/src/assets/svg/history.svg deleted file mode 100644 index 6fc7a23960..0000000000 --- a/src/assets/svg/history.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/assets/svg/no-data.svg b/src/assets/svg/no-data.svg new file mode 100644 index 0000000000..6f0d4f30fc --- /dev/null +++ b/src/assets/svg/no-data.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/components/Announcement/Popups/TopRightPopup.tsx b/src/components/Announcement/Popups/TopRightPopup.tsx index 749656b2e3..fc1eacb6a9 100644 --- a/src/components/Announcement/Popups/TopRightPopup.tsx +++ b/src/components/Announcement/Popups/TopRightPopup.tsx @@ -154,9 +154,9 @@ export default function PopupItem({ popup, hasOverlay }: { popup: PopupItemType; let popupContent switch (popupType) { case PopupType.SIMPLE: { - const { title, summary, type = NotificationType.ERROR, icon } = content as PopupContentSimple + const { type = NotificationType.ERROR } = content as PopupContentSimple notiType = type - popupContent = + popupContent = break } case PopupType.TRANSACTION: { diff --git a/src/components/Announcement/type.ts b/src/components/Announcement/type.ts index bf3dd8239b..07223ebf08 100644 --- a/src/components/Announcement/type.ts +++ b/src/components/Announcement/type.ts @@ -155,9 +155,10 @@ export type PopupContentTxn = { export type PopupContentSimple = { title: string + type: NotificationType summary?: ReactNode icon?: ReactNode - type: NotificationType + link?: string } export type PopupContentAnnouncement = { diff --git a/src/components/Icons/WarningIcon.tsx b/src/components/Icons/WarningIcon.tsx index 9aa64252e7..9114b60122 100644 --- a/src/components/Icons/WarningIcon.tsx +++ b/src/components/Icons/WarningIcon.tsx @@ -11,6 +11,7 @@ export default function WarningIcon({ return ( + ` overflow: hidden; width: fit-content; - height: 36px; + height: 32px; padding: 8px 12px; background: ${({ bgColor }) => bgColor}; color: ${({ theme, isDisabled }) => (isDisabled ? theme.border : theme.textReverse)}; @@ -62,12 +62,14 @@ export default function SubscribeNotificationButton({ trackingEvent, onClick, topicId, + style, }: { subscribeTooltip?: ReactNode iconOnly?: boolean trackingEvent?: MIXPANEL_TYPE onClick?: () => void topicId?: string + style?: CSSProperties }) { const theme = useTheme() @@ -97,7 +99,7 @@ export default function SubscribeNotificationButton({ return ( - + {hasSubscribe ? Unsubscribe : Subscribe} diff --git a/src/components/TransactionConfirmationModal/index.tsx b/src/components/TransactionConfirmationModal/index.tsx index 993f7d6a42..e5dc315c60 100644 --- a/src/components/TransactionConfirmationModal/index.tsx +++ b/src/components/TransactionConfirmationModal/index.tsx @@ -324,6 +324,7 @@ interface ConfirmationModalProps { hash: string | undefined content: () => React.ReactNode attemptingTxn: boolean + attemptingTxnContent?: () => React.ReactNode pendingText: string | React.ReactNode tokenAddToMetaMask?: Currency showTxBanner?: boolean @@ -336,6 +337,7 @@ export default function TransactionConfirmationModal({ isOpen, onDismiss, attemptingTxn, + attemptingTxnContent, hash, pendingText, content, @@ -356,7 +358,11 @@ export default function TransactionConfirmationModal({ width={!attemptingTxn && !hash ? width : undefined} > {attemptingTxn ? ( - + attemptingTxnContent ? ( + attemptingTxnContent() + ) : ( + + ) ) : hash ? ( Promise onWrapToken: () => Promise showPreview: () => void + isEdit: boolean }) { const disableBtnApproved = approval === ApprovalState.PENDING || @@ -111,7 +113,13 @@ export default function ActionButtonLimitOrder({ {checkingAllowance ? Checking Allowance... : Review Order} ) + + if (isEdit) { + return null + } + if (showWarning && !disableBtnReview) return {contentButton} + return ( {contentButton} diff --git a/src/components/swapv2/LimitOrder/DeltaRate.tsx b/src/components/swapv2/LimitOrder/DeltaRate.tsx index c5cd0479f9..0929eb0b11 100644 --- a/src/components/swapv2/LimitOrder/DeltaRate.tsx +++ b/src/components/swapv2/LimitOrder/DeltaRate.tsx @@ -9,13 +9,15 @@ import useTheme from 'hooks/useTheme' import { RateInfo } from './type' +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) { @@ -39,18 +41,18 @@ export function useGetDeltaRateLimitOrder({ return { rawPercent: percent, percent: percentText, - profit: percent && Number(percent) > 0, + profit: Boolean(percent && Number(percent) > 0), } } const DeltaRate = ({ marketPrice, rateInfo, - symbolIn, + symbol, }: { marketPrice: BaseTradeInfo | undefined rateInfo: RateInfo - symbolIn: string + symbol: string }) => { const theme = useTheme() @@ -63,7 +65,7 @@ const DeltaRate = ({ ) return (
} + {showReview ? Review your order : Edit Order} + -
+ + Editing this order will automatically cancel your existing order and a new order will be created. {status === LimitOrderStatus.PARTIALLY_FILLED && ( - + Your currently existing order is {filled}% filled. )} -
- + + + {isWaiting && ( + + )} + {renderCancelButtons()} ) diff --git a/src/components/swapv2/LimitOrder/ExpirePicker.tsx b/src/components/swapv2/LimitOrder/ExpirePicker.tsx index a81ade16f2..c96838f218 100644 --- a/src/components/swapv2/LimitOrder/ExpirePicker.tsx +++ b/src/components/swapv2/LimitOrder/ExpirePicker.tsx @@ -1,5 +1,6 @@ import { Trans } from '@lingui/macro' import dayjs from 'dayjs' +import { rgba } from 'polished' import { useCallback, useEffect, useMemo, useState } from 'react' import { Calendar, X } from 'react-feather' import { Flex, Text } from 'rebass' @@ -44,8 +45,8 @@ const DefaultOptionContainer = styled.div` ` const ResultContainer = styled.div` - border: ${({ theme }) => `1px solid ${theme.warning}`}; - padding: 10px; + background-color: ${({ theme }) => rgba(theme.warning, 0.2)}; + padding: 12px; border-radius: 20px; width: 100%; display: flex; diff --git a/src/components/swapv2/LimitOrder/LimitOrderForm.tsx b/src/components/swapv2/LimitOrder/LimitOrderForm.tsx index b8b3d55812..dcdacc5228 100644 --- a/src/components/swapv2/LimitOrder/LimitOrderForm.tsx +++ b/src/components/swapv2/LimitOrder/LimitOrderForm.tsx @@ -1,25 +1,19 @@ import { Currency, CurrencyAmount, Token, TokenAmount, WETH } from '@kyberswap/ks-sdk-core' import { Trans, t } from '@lingui/macro' import dayjs from 'dayjs' -import { ethers } from 'ethers' import JSBI from 'jsbi' -import debounce from 'lodash/debounce' -import { rgba } from 'polished' -import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { Info, Repeat } from 'react-feather' +import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react' +import { Repeat } from 'react-feather' +import { useMedia } from 'react-use' import { Flex, Text } from 'rebass' -import { - useCreateOrderMutation, - useCreateOrderSignatureMutation, - useGetLOContractAddressQuery, - useGetTotalActiveMakingAmountQuery, -} from 'services/limitOrder' +import { useCreateOrderMutation, useGetLOConfigQuery, useGetTotalActiveMakingAmountQuery } from 'services/limitOrder' import styled from 'styled-components' import { NotificationType } from 'components/Announcement/type' import ArrowRotate from 'components/ArrowRotate' import CurrencyInputPanel from 'components/CurrencyInputPanel' import CurrencyLogo from 'components/CurrencyLogo' +import InfoHelper from 'components/InfoHelper' import NumericalInput from 'components/NumericalInput' import { RowBetween } from 'components/Row' import Select from 'components/Select' @@ -29,7 +23,9 @@ import DeltaRate, { useGetDeltaRateLimitOrder } from 'components/swapv2/LimitOrd import { SummaryNotifyOrderPlaced } from 'components/swapv2/LimitOrder/ListOrder/SummaryNotify' import ConfirmOrderModal from 'components/swapv2/LimitOrder/Modals/ConfirmOrderModal' import TradePrice from 'components/swapv2/LimitOrder/TradePrice' +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 { Z_INDEXS } from 'constants/styles' @@ -45,18 +41,13 @@ 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 { MEDIA_WIDTHS } from 'theme' import { TransactionFlowState } from 'types/TransactionFlowState' import { subscribeNotificationOrderCancelled, subscribeNotificationOrderExpired } from 'utils/firebase' import { maxAmountSpend } from 'utils/maxAmountSpend' import ExpirePicker from './ExpirePicker' -import { - BETTER_PRICE_DIFF_THRESHOLD, - DEFAULT_EXPIRED, - USD_THRESHOLD, - WORSE_PRICE_DIFF_THRESHOLD, - getExpireOptions, -} from './const' +import { DEFAULT_EXPIRED, getExpireOptions } from './const' import { calcInvert, calcOutput, @@ -68,7 +59,7 @@ import { parseFraction, removeTrailingZero, } from './helpers' -import { CreateOrderParam, LimitOrder, RateInfo } from './type' +import { CreateOrderParam, EditOrderInfo, LimitOrder, RateInfo } from './type' export const Label = styled.div` font-weight: 500; @@ -84,7 +75,6 @@ const Set2Market = styled(Label)` const INPUT_HEIGHT = 28 type Props = { - refreshListOrder: () => void currencyIn: Currency | undefined currencyOut: Currency | undefined defaultInputAmount?: string @@ -93,14 +83,12 @@ type Props = { defaultExpire?: Date setIsSelectCurrencyManual?: (val: boolean) => void note?: string - onCancelOrder?: () => Promise orderInfo?: LimitOrder flowState: TransactionFlowState setFlowState: React.Dispatch> zIndexToolTip?: number - onDismissModalEdit?: () => void defaultRate?: RateInfo - isEdit?: boolean + editOrderInfo?: EditOrderInfo } const InputWrapper = styled.div` @@ -111,43 +99,51 @@ const InputWrapper = styled.div` flex-direction: column; gap: 0.5rem; display: flex; + ${({ theme }) => theme.mediaWidth.upToSmall` + width: 100%; + `} ` -const HightLight = styled.span` - font-weight: 500; - color: ${({ theme }) => theme.warning}; +const ExpiredInput = styled(InputWrapper)` + max-width: 30%; + ${({ theme }) => theme.mediaWidth.upToSmall` + max-width: unset; + `} ` - -const LimitOrderForm = function LimitOrderForm({ - refreshListOrder, - onCancelOrder, - currencyIn, - currencyOut, - defaultInputAmount = '', - defaultOutputAmount = '', - defaultActiveMakingAmount = '', - defaultExpire, - defaultRate = { rate: '', invertRate: '', invert: false }, - setIsSelectCurrencyManual, - note = '', - orderInfo, - flowState, - setFlowState, - zIndexToolTip = Z_INDEXS.TOOL_TIP_ERROR_INPUT_SWAP_FORM, - onDismissModalEdit, - isEdit = false, // else create -}: Props) { +export type LimitOrderFormHandle = { + hasChangedOrderInfo: () => boolean +} +const LimitOrderForm = forwardRef(function LimitOrderForm( + { + currencyIn, + currencyOut, + defaultInputAmount = '', + defaultOutputAmount = '', + defaultActiveMakingAmount = '', + defaultExpire, + defaultRate = { rate: '', invertRate: '', invert: false }, + setIsSelectCurrencyManual, + note = '', + orderInfo, + flowState, + setFlowState, + zIndexToolTip = Z_INDEXS.TOOL_TIP_ERROR_INPUT_SWAP_FORM, + editOrderInfo, + }, + ref, +) { + const isEdit = editOrderInfo?.isEdit || false // else create const { account, chainId, networkInfo } = useActiveWeb3React() - + const upToSmall = useMedia(`(max-width: ${MEDIA_WIDTHS.upToSmall}px)`) const theme = useTheme() const notify = useNotify() const { mixpanelHandler } = useMixpanel() - const { setCurrencyIn, setCurrencyOut, switchCurrency, setCurrentOrder, removeCurrentOrder, resetState } = + const { setCurrencyIn, setCurrencyOut, switchCurrency, removeOrderNeedCreated, resetState, setOrderEditing } = useLimitActionHandlers() - const { ordersUpdating, inputAmount: inputAmountGlobal } = useLimitState() + const { ordersNeedCreated, inputAmount: inputAmountGlobal } = useLimitState() const [inputAmount, setInputAmount] = useState(defaultInputAmount) - const [outputAmount, setOuputAmount] = useState(defaultOutputAmount) + const [outputAmount, setOutputAmount] = useState(defaultOutputAmount) const [rateInfo, setRateInfo] = useState(defaultRate) const displayRate = rateInfo.invert ? rateInfo.invertRate : rateInfo.rate @@ -183,7 +179,7 @@ const LimitOrderForm = function LimitOrderForm({ if (rate) { if (inputAmount) { const output = calcOutput(inputAmount, newRate.rateFraction || rate, currencyOut.decimals) - setOuputAmount(output) + setOutputAmount(output) } if (!invertRate) { newRate.invertRate = calcInvert(rate) @@ -196,7 +192,7 @@ const LimitOrderForm = function LimitOrderForm({ newRate.rateFraction = parseFraction(invertRate).invert() if (inputAmount) { const output = calcOutput(inputAmount, newRate.rateFraction, currencyOut.decimals) - setOuputAmount(output) + setOutputAmount(output) } setRateInfo(newRate) return @@ -213,7 +209,7 @@ const LimitOrderForm = function LimitOrderForm({ invertRate: calcInvert(rate), }) } - setOuputAmount(output) + setOutputAmount(output) } const setPriceRateMarket = () => { @@ -237,7 +233,7 @@ const LimitOrderForm = function LimitOrderForm({ (input: string) => { setInputAmount(input) if (rateInfo.rate && currencyIn && currencyOut && input) { - setOuputAmount(calcOutput(input, rateInfo.rateFraction || rateInfo.rate, currencyOut.decimals)) + setOutputAmount(calcOutput(input, rateInfo.rateFraction || rateInfo.rate, currencyOut.decimals)) } }, [rateInfo, currencyIn, currencyOut], @@ -285,8 +281,8 @@ const LimitOrderForm = function LimitOrderForm({ } const parseInputAmount = tryParseAmount(inputAmount, currencyIn ?? undefined) - const { data, isError } = useGetLOContractAddressQuery(chainId) - const limitOrderContract = isError ? undefined : data + const { currentData } = useGetLOConfigQuery(chainId) + const limitOrderContract = currentData?.contract const currentAllowance = useTokenAllowance( currencyIn as Token, @@ -394,7 +390,7 @@ const LimitOrderForm = function LimitOrderForm({ const onResetForm = () => { setInputAmount(defaultInputAmount) - setOuputAmount(defaultOutputAmount) + setOutputAmount(defaultOutputAmount) setRateInfo(defaultRate) setExpire(DEFAULT_EXPIRED) setCustomDateExpire(undefined) @@ -413,33 +409,7 @@ const LimitOrderForm = function LimitOrderForm({ [setFlowState], ) - const [getMessageSignature] = useCreateOrderSignatureMutation() - const signOrder = async (params: CreateOrderParam) => { - const { currencyIn, currencyOut, inputAmount, outputAmount, signature, salt } = params - if (signature && salt) return { signature, salt } - if (!library || !currencyIn || !currencyOut) return { signature: '', salt: '' } - - const payload = getPayloadCreateOrder(params) - setFlowState(state => ({ - ...state, - attemptingTxn: true, - pendingText: `Sign limit order: ${formatAmountOrder(inputAmount)} ${currencyIn.symbol} to ${formatAmountOrder( - outputAmount, - )} ${currencyOut.symbol}`, - })) - const messagePayload = await getMessageSignature(payload).unwrap() - - const rawSignature = await library.send('eth_signTypedData_v4', [account, JSON.stringify(messagePayload)]) - - const bytes = ethers.utils.arrayify(rawSignature) - const lastByte = bytes[64] - if (lastByte === 0 || lastByte === 1) { - // to support hardware wallet https://ethereum.stackexchange.com/a/113727 - bytes[64] += 27 - } - - return { signature: ethers.utils.hexlify(bytes), salt: messagePayload?.message?.salt } - } + const signOrder = useSignOrder(setFlowState) const [submitOrder] = useCreateOrderMutation() const onSubmitCreateOrder = async (params: CreateOrderParam) => { @@ -464,7 +434,6 @@ const LimitOrderForm = function LimitOrderForm({ 10000, ) onResetForm() - setTimeout(() => refreshListOrder?.(), 500) return response?.id } catch (error) { handleError(error) @@ -472,31 +441,6 @@ const LimitOrderForm = function LimitOrderForm({ } } - const onSubmitEditOrder = async () => { - try { - if (!onCancelOrder) return - await onCancelOrder() - if (orderInfo) { - const param = { - orderId: orderInfo?.id, - account, - chainId, - currencyIn, - currencyOut, - inputAmount, - outputAmount, - expiredAt, - } - const { signature, salt } = await signOrder(param) - setCurrentOrder({ ...param, salt, signature }) - } - onDismissModalEdit?.() - } catch (error) { - orderInfo && removeCurrentOrder(orderInfo.id) - handleError(error) - } - } - const onWrapToken = async () => { try { if (isNotFillAllInput || wrapInputError || isWrappingEth || hasInputError) return @@ -524,44 +468,62 @@ const LimitOrderForm = function LimitOrderForm({ } }, [approval, approvalSubmitted]) - const refreshActiveMakingAmount = useMemo( - () => - debounce(() => { - try { - getActiveMakingAmount() - } catch (error) {} - }, 100), - [getActiveMakingAmount], - ) + const refreshActiveMakingAmount = useCallback(() => { + try { + getActiveMakingAmount() + } catch (error) {} + }, [getActiveMakingAmount]) useEffect(() => { - if (currencyIn) refreshActiveMakingAmount() - }, [currencyIn, refreshActiveMakingAmount, isEdit]) + if (!isEdit || !orderInfo?.id) return + setOrderEditing({ + orderId: orderInfo.id, + account, + chainId, + currencyIn, + currencyOut, + inputAmount, + outputAmount, + expiredAt, + }) + }, [ + 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 refRefreshActiveMakingAmount = useRef(refreshActiveMakingAmount) - refRefreshActiveMakingAmount.current = refreshActiveMakingAmount useEffect(() => { if (!account) return // call when cancel expired/cancelled const unsubscribeCancelled = subscribeNotificationOrderCancelled(account, chainId, data => { data?.orders.forEach(order => { - const findInfo = ordersUpdating.find(e => e.orderId === order.id) + const findInfo = ordersNeedCreated.find(e => e.orderId === order.id) if (!findInfo?.orderId) return - removeCurrentOrder(findInfo.orderId) - if (order.isSuccessful) refSubmitCreateOrder.current(findInfo) + removeOrderNeedCreated(findInfo.orderId) + // when cancel order success => create a new order + if (order.isSuccessful && !isEdit) { + refSubmitCreateOrder.current(findInfo) + } }) - refRefreshActiveMakingAmount.current() + refreshActiveMakingAmount() }) - const unsubscribeExpired = subscribeNotificationOrderExpired(account, chainId, refRefreshActiveMakingAmount.current) + const unsubscribeExpired = subscribeNotificationOrderExpired(account, chainId, refreshActiveMakingAmount) return () => { unsubscribeCancelled?.() unsubscribeExpired?.() } - }, [account, chainId, ordersUpdating, removeCurrentOrder]) + }, [account, chainId, ordersNeedCreated, removeOrderNeedCreated, refreshActiveMakingAmount, isEdit]) useEffect(() => { if (inputAmountGlobal) onSetInput(inputAmountGlobal) @@ -627,49 +589,46 @@ const LimitOrderForm = function LimitOrderForm({ !enoughAllowance || (approvalSubmitted && approval === ApprovalState.APPROVED)) - const warningMessage = useMemo(() => { - const messages = [] - - if (currencyIn && displayRate && !deltaRate.profit && Number(deltaRate.rawPercent) <= WORSE_PRICE_DIFF_THRESHOLD) { - // need to remove the minus out of the percent text - const percentWithoutMinus = deltaRate.percent.slice(1) - - messages.push( - - - Your limit order price is {percentWithoutMinus} lower than the market. You will be - selling your {currencyIn.symbol} exceedingly cheap. - - , - ) - } - - const threshold = USD_THRESHOLD[chainId] - const showWarningThresHold = outputAmount && estimateUSD.rawInput && estimateUSD.rawInput < threshold - - if (showWarningThresHold) { - messages.push( - - - We suggest you increase the value of your limit order to at least ${threshold}. - This will increase the odds of your order being filled. - - , - ) - } - - return messages - }, [ - chainId, + const warningMessage = useWarningCreateOrder({ + estimateUSD: estimateUSD.rawInput, currencyIn, - deltaRate.percent, - deltaRate.profit, - deltaRate.rawPercent, - displayRate, - estimateUSD.rawInput, outputAmount, - ]) + displayRate, + deltaRate, + }) + useImperativeHandle(ref, () => ({ + hasChangedOrderInfo() { + return ( + isEdit && + (defaultInputAmount !== inputAmount || + defaultRate?.rate !== rateInfo.rate || + defaultExpire?.getTime() !== expiredAt) + ) + }, + })) + + const renderConfirmModal = (showConfirmContent = false) => ( + + ) + + if (isEdit && flowState.showConfirm) return renderConfirmModal(true) return ( <> @@ -702,10 +661,43 @@ const LimitOrderForm = function LimitOrderForm({ /> - + + + You Buy + + } + positionLabel="in" + /> + + + - + {tradeInfo && ( Market @@ -733,15 +725,19 @@ const LimitOrderForm = function LimitOrderForm({ )} - +