From 2fc430a2980fb4842dbe1298e81d89c62b4cf2c5 Mon Sep 17 00:00:00 2001 From: leonthuongto Date: Tue, 7 Jan 2025 10:28:41 +0700 Subject: [PATCH] Done get best swap --- src/pages/DexV2/Swap/components/SwapCard.tsx | 27 ++++-- src/pages/DexV2/Swap/components/SwapPair.tsx | 93 +++++++------------ .../DexV2/Swap/components/TokenInput.tsx | 90 ++++++++++++------ src/state/dexV2/swap/useSor.ts | 3 + 4 files changed, 114 insertions(+), 99 deletions(-) diff --git a/src/pages/DexV2/Swap/components/SwapCard.tsx b/src/pages/DexV2/Swap/components/SwapCard.tsx index d634ead1d..20fd2bfa5 100644 --- a/src/pages/DexV2/Swap/components/SwapCard.tsx +++ b/src/pages/DexV2/Swap/components/SwapCard.tsx @@ -72,6 +72,7 @@ const SwapCard: React.FC = () => { return 'Swap' }, [swapping.wrapType, swapping.tokenIn?.symbol, swapping.tokenOut?.symbol]) const pools: SubgraphPoolBase[] = swapping.sor.pools + console.log('pools', pools) const error = useMemo(() => { if (isMismatchedNetwork) { return { @@ -162,11 +163,25 @@ const SwapCard: React.FC = () => { // modalSwapPreviewIsOpen.value = false; TODO: Review UX } + async function swap() { + return swapping.swap(() => { + swapping.resetAmounts() + // emit('close'); + }) + } + useEffect(() => { populateInitialTokens() setInitialized(true) }, []) + useEffect(() => { + // if (!swapping.isLoading) { + // swapping.handleAmountChange() + // } + }, [tokenInAmount, tokenOutAmount]) + + console.log("swapping.isLoading", swapping.isLoading) return ( @@ -187,24 +202,18 @@ const SwapCard: React.FC = () => { -
{account ? Next : Connect Wallet}
+
+ {account ? Next : Connect Wallet} +
) } diff --git a/src/pages/DexV2/Swap/components/SwapPair.tsx b/src/pages/DexV2/Swap/components/SwapPair.tsx index efdfa824f..56cb0fa58 100644 --- a/src/pages/DexV2/Swap/components/SwapPair.tsx +++ b/src/pages/DexV2/Swap/components/SwapPair.tsx @@ -7,90 +7,69 @@ import SwapIcon from 'assets/images/dex-v2/swap.svg' import { emptyToken, UseSwapping } from 'state/dexV2/swap/useSwapping' import useNumbers from 'hooks/dex-v2/useNumbers' import { useTokens } from 'state/dexV2/tokens/hooks/useTokens' +import { useSwapState } from 'state/dexV2/swap/useSwapState' type Props = { - tokenInAmount: string - tokenInAddress: string - tokenOutAmount: string - tokenOutAddress: string exactIn: boolean priceImpact?: number effectivePriceMessage?: UseSwapping['effectivePriceMessage'] swapLoading?: boolean amountChange: () => void - setTokenInAmount: (amount: string) => void - setTokenOutAmount: (amount: string) => void - setTokenInAddress: (address: string) => void - setTokenOutAddress: (address: string) => void setExactIn: (exactIn: boolean) => void } const SwapPair: React.FC = ({ - tokenInAmount, - tokenInAddress, - tokenOutAmount, - tokenOutAddress, exactIn, priceImpact, effectivePriceMessage, swapLoading, amountChange, setExactIn, - setTokenInAmount, - setTokenOutAmount, - setTokenInAddress, - setTokenOutAddress, }) => { const { fNum } = useNumbers() const { getToken } = useTokens() + const { + tokenInAddress, + tokenOutAddress, + tokenInAmount, + tokenOutAmount, + setTokenInAddress, + setTokenOutAddress, + setTokenInAmount, + setTokenOutAmount, + setInitialized, + } = useSwapState() - const [_tokenInAmount, setLocalTokenInAmount] = useState('') - const [_tokenOutAmount, setLocalTokenOutAmount] = useState('') - const [_tokenInAddress, setLocalTokenInAddress] = useState('') - const [_tokenOutAddress, setLocalTokenOutAddress] = useState('') const [isInRate, setIsInRate] = useState(true) const [typingTimeout, setTypingTimeout] = useState(undefined) - const missingToken = !_tokenInAddress || !_tokenOutAddress - const missingAmount = !_tokenInAmount || !_tokenOutAmount + const missingToken = !tokenInAddress || !tokenOutAddress + const missingAmount = !tokenInAmount || !tokenOutAmount - const tokenIn = _tokenInAddress ? getToken(_tokenInAddress) : emptyToken - const tokenOut = _tokenOutAddress ? getToken(_tokenOutAddress) : emptyToken - - function preventUpdatesOnTyping(callback: () => void) { - if (typingTimeout.value) { - clearTimeout(typingTimeout.value) - } - typingTimeout.value = setTimeout(() => { - callback() - }, 300) - } + const tokenIn = tokenInAddress ? getToken(tokenInAddress) : emptyToken + const tokenOut = tokenOutAddress ? getToken(tokenOutAddress) : emptyToken function handleInAmountChange(value: string): void { setTokenInAmount(value) - preventUpdatesOnTyping(() => { - amountChange() - }) + setExactIn(true) } function handleOutAmountChange(value: string): void { setTokenOutAmount(value) - preventUpdatesOnTyping(() => { - amountChange() - }) + setExactIn(false) } function handleTokenSwitch(): void { setExactIn(!exactIn) - setTokenInAmount(_tokenOutAmount) - setTokenInAddress(_tokenOutAddress) - setTokenOutAmount(_tokenInAmount) - setTokenOutAddress(_tokenInAddress) + setTokenInAmount(tokenOutAmount) + setTokenInAddress(tokenOutAddress) + setTokenOutAmount(tokenInAmount) + setTokenOutAddress(tokenInAddress) amountChange() } async function handleInputTokenChange(newTokenIn: string) { - if (newTokenIn === _tokenOutAddress) { + if (newTokenIn === tokenOutAddress) { handleTokenSwitch() return } @@ -98,20 +77,13 @@ const SwapPair: React.FC = ({ } async function handleOutputTokenChange(newTokenOut: string) { - if (newTokenOut === _tokenInAddress) { + if (newTokenOut === tokenInAddress) { handleTokenSwitch() return } setTokenOutAddress(newTokenOut) } - useEffect(() => { - setLocalTokenInAmount(tokenInAmount) - setLocalTokenOutAmount(tokenOutAmount) - setLocalTokenInAddress(tokenInAddress) - setLocalTokenOutAddress(tokenOutAddress) - }, [tokenInAmount, tokenOutAmount, tokenInAddress, tokenOutAddress]) - useEffect(() => { // populates initial tokenOutAmount if (tokenOutAmount) { @@ -119,18 +91,20 @@ const SwapPair: React.FC = ({ } }, []) + console.log('tokenInAmount', tokenInAmount) + console.log('tokenOutAmount', tokenOutAmount) + return (
setExactIn(true)} setMax={() => setExactIn(true)} />
@@ -139,16 +113,15 @@ const SwapPair: React.FC = ({ setExactIn(true)} + updateAmount={handleOutAmountChange} + updateAddress={handleOutputTokenChange} />
diff --git a/src/pages/DexV2/Swap/components/TokenInput.tsx b/src/pages/DexV2/Swap/components/TokenInput.tsx index d4c2cd616..89db61f19 100644 --- a/src/pages/DexV2/Swap/components/TokenInput.tsx +++ b/src/pages/DexV2/Swap/components/TokenInput.tsx @@ -6,7 +6,7 @@ import _get from 'lodash/get' import TokenSelectInput from '../../common/TokenSelectInput' import { ReactComponent as WalletIcon } from 'assets/images/dex-v2/wallet.svg' import { useTokens } from 'state/dexV2/tokens/hooks/useTokens' -import useNumbers from 'hooks/dex-v2/useNumbers' +import useNumbers, { FNumFormats } from 'hooks/dex-v2/useNumbers' import { bnum, isSameAddress } from 'lib/utils' import { TokenInfo } from 'types/TokenList' import { useAccount } from 'wagmi' @@ -85,9 +85,10 @@ const defaultProps: Props = { } const TokenInput: React.FC = (props = defaultProps) => { - const { name, amount, address, customBalance, excludedTokens, autoFocus, disableNativeAssetBuffer } = props - const [_address, setAddress] = useState('') - const [_amount, setAmount] = useState('') + const { name, noMax, disableMax, customBalance, excludedTokens, autoFocus, disableNativeAssetBuffer, updateAddress } = + props + const [address, setAddress] = useState('') + const [amount, setAmount] = useState('') const { address: account } = useAccount() const isWalletReady = useMemo(() => account !== null, [account]) @@ -99,14 +100,15 @@ const TokenInput: React.FC = (props = defaultProps) => { */ const tokenBalance = useMemo(() => { if (customBalance) return customBalance - return balanceFor(_address) - }, [_address, customBalance]) - const hasToken = !!_address - const amountBN = bnum(_amount) + return balanceFor(_get(props, 'address', '')) + }, [props.address, customBalance]) + + const hasToken = !!props.address + const amountBN = bnum(props.amount) const tokenBalanceBN = bnum(tokenBalance) const hasAmount = amountBN.gt(0) const hasBalance = tokenBalanceBN.gt(0) - const shouldUseTxBuffer = _address === nativeAsset.address && !disableNativeAssetBuffer + const shouldUseTxBuffer = props.address === nativeAsset.address && !disableNativeAssetBuffer const amountExceedsTokenBalance = amountBN.gt(tokenBalance) const shouldShowTxBufferMessage = useMemo(() => { if (amountExceedsTokenBalance || !shouldUseTxBuffer || !hasBalance || !hasAmount) { @@ -118,18 +120,18 @@ const TokenInput: React.FC = (props = defaultProps) => { const isMaxed = useMemo(() => { if (shouldUseTxBuffer) { - return _amount === tokenBalanceBN.minus(nativeAsset.minTransactionBuffer).toString() + return props.amount === tokenBalanceBN.minus(nativeAsset.minTransactionBuffer).toString() } else { - return _amount === tokenBalance + return props.amount === tokenBalance } - }, [_amount, tokenBalance, shouldUseTxBuffer]) + }, [props.amount, tokenBalance, shouldUseTxBuffer]) const token = useMemo((): TokenInfo | undefined => { if (!hasToken) return undefined - return getToken(_address) - }, [_address, hasToken]) + return getToken(_get(props, 'address', '')) + }, [props.address, hasToken]) - const tokenValue = props.tokenValue ?? toFiat(amount, _address) + const tokenValue = props.tokenValue ?? toFiat(amount, _get(props, 'address', '')) const inputRules = useMemo(() => { if (!hasToken || !isWalletReady || props.noRules) { @@ -163,13 +165,10 @@ const TokenInput: React.FC = (props = defaultProps) => { const decimalLimit = token?.decimals || 18 - const updateAddress = (address: string) => { - setAddress(address) - } - function handleAmountChange(amount: InputValue) { const safeAmount = overflowProtected(amount, decimalLimit) + setAmount(safeAmount) props.updateAmount(safeAmount) } @@ -178,19 +177,26 @@ const TokenInput: React.FC = (props = defaultProps) => { const maxAmount = props.customBalance ? props.customBalance - : getMaxBalanceFor(_address.value, props.disableNativeAssetBuffer) + : getMaxBalanceFor(_get(props, 'address', ''), props.disableNativeAssetBuffer) // emit('setMax', maxAmount) handleAmountChange(maxAmount) } - useEffect(() => { - setAmount(amount.toString()) - }, [amount]) + function blockInvalidChar(event: KeyboardEvent) { + if (['e', 'E', '+', '-'].includes(event.key)) { + event.preventDefault() + } + } + + function onKeyDown(event: React.KeyboardEvent): void { + blockInvalidChar(event.nativeEvent) + } useEffect(() => { - setAddress(address) - }, [address]) + setAddress(props.address) + setAmount(props.amount) + }, [props.address, props.amount]) return ( @@ -199,23 +205,30 @@ const TokenInput: React.FC = (props = defaultProps) => { placeholder="0.00" min="0" step="0.01" - onKeyDown={() => {}} + onKeyDown={onKeyDown} type="text" inputMode="decimal" pattern="[0-9]*[.,]?[0-9]*" - value={''} + value={amount} name={name} autoFocus={autoFocus} - onChange={(e) => {}} + onChange={(e) => handleAmountChange(e.target.value)} /> - + + {hasBalance && !noMax && !disableMax ? MAX : null} + updateAddress(value)} + /> + $0.00 - 346.93 + {fNum(tokenBalance, FNumFormats.token)} @@ -257,3 +270,20 @@ const StyledNumber = styled.div` font-weight: 500; letter-spacing: -0.42px; ` + +const MaxButton = styled.button` + display: flex; + padding: 8px 16px; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 10px; + align-self: stretch; + border-radius: 8px; + background: #fff; + outline: none; + border: none; + font-weight: 600; + color: #66f; + font-size: 9px; +` diff --git a/src/state/dexV2/swap/useSor.ts b/src/state/dexV2/swap/useSor.ts index add7e3d77..7cfb485bb 100644 --- a/src/state/dexV2/swap/useSor.ts +++ b/src/state/dexV2/swap/useSor.ts @@ -307,6 +307,8 @@ export default function useSor({ tokenInAmountScaled ) + console.log('swapReturn', swapReturn) + setSorReturn(swapReturn) let tokenOutAmount = swapReturn.returnAmount @@ -359,6 +361,7 @@ export default function useSor({ setSorReturn(swapReturn) // TO DO - is it needed? let tokenInAmount = swapReturn.returnAmount + setTokenInAmountInput(tokenInAmount.gt(0) ? formatAmount(formatUnits(tokenInAmount, tokenInDecimals)) : '') if (!sorReturn.hasSwaps) {