diff --git a/index.html b/index.html
index fc957827ad..a8a39ca983 100644
--- a/index.html
+++ b/index.html
@@ -52,78 +52,78 @@
window.EventEmitter = EventEmitter
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/hooks/useSyncTokenSymbolToUrl.ts b/src/hooks/useSyncTokenSymbolToUrl.ts
index ecd1616e3a..9499dc686d 100644
--- a/src/hooks/useSyncTokenSymbolToUrl.ts
+++ b/src/hooks/useSyncTokenSymbolToUrl.ts
@@ -129,7 +129,7 @@ export default function useSyncTokenSymbolToUrl(
!disabled
) {
// call once
- setTimeout(() => findTokenPairFromUrl(chainId))
+ // setTimeout(() => findTokenPairFromUrl(chainId))
checkedTokenFromUrlWhenInit.current = true
}
}, [isLoadedTokenDefault, firstTokenChainId, chainId, network, disabled, findTokenPairFromUrl])
diff --git a/src/pages/SwapV3/PopulatedSwapForm.tsx b/src/pages/SwapV3/PopulatedSwapForm.tsx
index 7dc23ccfe9..d3c85f540b 100644
--- a/src/pages/SwapV3/PopulatedSwapForm.tsx
+++ b/src/pages/SwapV3/PopulatedSwapForm.tsx
@@ -4,34 +4,22 @@ import { useLocation, useSearchParams } from 'react-router-dom'
import SwapForm, { SwapFormProps } from 'components/SwapForm'
import { APP_PATHS } from 'constants/index'
-import useSyncTokenSymbolToUrl from 'hooks/useSyncTokenSymbolToUrl'
-import { useAppSelector } from 'state/hooks'
import { Field } from 'state/swap/actions'
import { useInputCurrency, useOutputCurrency, useSwapActionHandlers } from 'state/swap/hooks'
import { useDegenModeManager, usePermitData, useUserSlippageTolerance, useUserTransactionTTL } from 'state/user/hooks'
import { useCurrencyBalances } from 'state/wallet/hooks'
import { DetailedRouteSummary } from 'types/route'
-import useResetCurrenciesOnRemoveImportedTokens from './useResetCurrenciesOnRemoveImportedTokens'
-
type Props = {
routeSummary: DetailedRouteSummary | undefined
setRouteSummary: React.Dispatch>
- onSelectSuggestedPair: (fromToken: Currency | undefined, toToken: Currency | undefined, amount?: string) => void
hidden: boolean
onOpenGasToken: () => void
}
-const PopulatedSwapForm: React.FC = ({
- routeSummary,
- setRouteSummary,
- hidden,
- onSelectSuggestedPair,
- onOpenGasToken,
-}) => {
+const PopulatedSwapForm: React.FC = ({ routeSummary, setRouteSummary, hidden, onOpenGasToken }) => {
const currencyIn = useInputCurrency()
const currencyOut = useOutputCurrency()
- const isSelectTokenManually = useAppSelector(state => state.swap.isSelectTokenManually)
const [balanceIn, balanceOut] = useCurrencyBalances(
useMemo(() => [currencyIn ?? undefined, currencyOut ?? undefined], [currencyIn, currencyOut]),
)
@@ -40,13 +28,11 @@ const PopulatedSwapForm: React.FC = ({
const [slippage] = useUserSlippageTolerance()
const permitData = usePermitData(currencyIn?.wrapped.address)
- const { onCurrencySelection, onResetSelectCurrency } = useSwapActionHandlers()
+ const { onCurrencySelection } = useSwapActionHandlers()
const { pathname } = useLocation()
const [searchParams, setSearchParams] = useSearchParams()
const isPartnerSwap = pathname.startsWith(APP_PATHS.PARTNER_SWAP)
- useSyncTokenSymbolToUrl(currencyIn, currencyOut, onSelectSuggestedPair, isSelectTokenManually, isPartnerSwap)
- useResetCurrenciesOnRemoveImportedTokens(currencyIn, currencyOut, onResetSelectCurrency)
const outId =
searchParams.get('outputCurrency') || (currencyOut?.isNative ? currencyOut.symbol : currencyOut?.wrapped.address)
diff --git a/src/pages/SwapV3/index.tsx b/src/pages/SwapV3/index.tsx
index ed810285ce..c409bf6fc2 100644
--- a/src/pages/SwapV3/index.tsx
+++ b/src/pages/SwapV3/index.tsx
@@ -1,8 +1,7 @@
-import { Currency } from '@kyberswap/ks-sdk-core'
import { Trans } from '@lingui/macro'
import { ReactNode, Suspense, lazy, useCallback, useEffect, useMemo, useState } from 'react'
import Skeleton from 'react-loading-skeleton'
-import { useLocation } from 'react-router-dom'
+import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'
import { Flex, Text } from 'rebass'
import styled from 'styled-components'
@@ -29,6 +28,7 @@ import {
import { APP_PATHS } from 'constants/index'
import { useActiveWeb3React } from 'hooks'
import { useAllTokens } from 'hooks/Tokens'
+import { NETWORKS_INFO } from 'hooks/useChainsConfig'
import useParsedQueryString from 'hooks/useParsedQueryString'
import useTheme from 'hooks/useTheme'
import { BodyWrapper } from 'pages/AppBody'
@@ -37,9 +37,6 @@ import CrossChainLink from 'pages/CrossChain/CrossChainLink'
import CrossChainTransfersHistory from 'pages/CrossChain/TransfersHistory'
import Header from 'pages/SwapV3/Header'
import useCurrenciesByPage from 'pages/SwapV3/useCurrenciesByPage'
-import { useLimitActionHandlers } from 'state/limit/hooks'
-import { Field } from 'state/swap/actions'
-import { useDefaultsFromURLSearch, useSwapActionHandlers } from 'state/swap/hooks'
import { useTutorialSwapGuide } from 'state/tutorial/hooks'
import { useShowTradeRoutes } from 'state/user/hooks'
import { DetailedRouteSummary } from 'types/route'
@@ -105,6 +102,17 @@ export default function Swap() {
const [isSelectCurrencyManually, setIsSelectCurrencyManually] = useState(false) // true when: select token input, output manually or click rotate token.
const { pathname } = useLocation()
+ const [searchParams] = useSearchParams()
+ const navigate = useNavigate()
+ useEffect(() => {
+ const inputCurrency = searchParams.get('inputCurrency')
+ const outputCurrency = searchParams.get('outputCurrency')
+ console.log(inputCurrency, outputCurrency)
+
+ if (inputCurrency || outputCurrency) {
+ navigate(`/swap/${NETWORKS_INFO[chainId].route}/${inputCurrency || ''}-to-${outputCurrency || ''}`)
+ }
+ }, [searchParams, chainId, navigate])
const shouldHighlightSwapBox = qs.highlightBox === 'true'
@@ -119,42 +127,14 @@ export default function Swap() {
const [activeTab, setActiveTab] = useState(getDefaultTab())
- const { onSelectPair: onSelectPairLimit } = useLimitActionHandlers()
-
useEffect(() => {
setActiveTab(getDefaultTab())
}, [getDefaultTab])
- useDefaultsFromURLSearch()
-
- const { onCurrencySelection, onUserInput } = useSwapActionHandlers()
-
const tradeRouteComposition = useMemo(() => {
return getTradeComposition(chainId, routeSummary?.parsedAmountIn, undefined, routeSummary?.route, defaultTokens)
}, [chainId, defaultTokens, routeSummary])
- const handleTypeInput = useCallback(
- (value: string) => {
- onUserInput(Field.INPUT, value)
- },
- [onUserInput],
- )
-
- const onSelectSuggestedPair = useCallback(
- (fromToken: Currency | undefined, toToken: Currency | undefined, amount?: string) => {
- if (isLimitPage) {
- onSelectPairLimit(fromToken, toToken, amount)
- setIsSelectCurrencyManually(true)
- return
- }
-
- if (fromToken) onCurrencySelection(Field.INPUT, fromToken)
- if (toToken) onCurrencySelection(Field.OUTPUT, toToken)
- if (amount) handleTypeInput(amount)
- },
- [handleTypeInput, onCurrencySelection, onSelectPairLimit, isLimitPage],
- )
-
const onBackToSwapTab = () => setActiveTab(getDefaultTab())
return (
@@ -173,7 +153,6 @@ export default function Swap() {
>
{isSwapPage && (
{
@@ -20,8 +17,10 @@ const useUpdateSlippageInStableCoinSwap = (chainId: ChainId) => {
const inputTokenFromParam = searchParams.get('inputCurrency') ?? ''
const outputTokenFromParam = searchParams.get('outputCurrency') ?? ''
- const inputCurrencyId = useSelector((state: AppState) => state.swap[Field.INPUT].currencyId) || inputTokenFromParam
- const outputCurrencyId = useSelector((state: AppState) => state.swap[Field.OUTPUT].currencyId) || outputTokenFromParam
+ const { fromCurrency, toCurrency } = useCurrencyFromUrl()
+
+ const inputCurrencyId = fromCurrency || inputTokenFromParam
+ const outputCurrencyId = toCurrency || outputTokenFromParam
const isCorrelatedPair = useCheckCorrelatedPair()
const previousInputCurrencyId = usePrevious(inputCurrencyId)
diff --git a/src/services/blackjack.ts b/src/services/blackjack.ts
index 57eaa4b84f..1af42aab18 100644
--- a/src/services/blackjack.ts
+++ b/src/services/blackjack.ts
@@ -21,6 +21,7 @@ const blackjackApi = createApi({
baseQuery: fetchBaseQuery({
baseUrl: `${BLACKJACK_API}/v1`,
}),
+ keepUnusedDataFor: 1,
endpoints: builder => ({
checkBlackjack: builder.query({
query: (address: string) => ({
diff --git a/src/state/limit/hooks.ts b/src/state/limit/hooks.ts
index cdf731d2b3..c65f5cd8d2 100644
--- a/src/state/limit/hooks.ts
+++ b/src/state/limit/hooks.ts
@@ -1,10 +1,8 @@
import { Currency } from '@kyberswap/ks-sdk-core'
-import { useCallback, useEffect } from 'react'
+import { useCallback } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { CreateOrderParam } from 'components/swapv2/LimitOrder/type'
-import { APP_PATHS } from 'constants/index'
-import useDefaultsTokenFromURLSearch from 'hooks/useDefaultsTokenFromURLSearch'
import { AppDispatch, AppState } from 'state/index'
import { Field } from 'state/swap/actions'
import { useInputCurrency, useOutputCurrency, useSwapActionHandlers, useSwapState } from 'state/swap/hooks'
@@ -32,11 +30,8 @@ export function useLimitState(): LimitState & {
export function useLimitActionHandlers() {
const dispatch = useDispatch()
- const { currencyIn, currencyOut } = useLimitState()
const { onSwitchTokensV2, onCurrencySelection, onUserInput } = useSwapActionHandlers()
- const { inputCurrency, outputCurrency } = useDefaultsTokenFromURLSearch(currencyIn, currencyOut, APP_PATHS.LIMIT)
-
const setInputValue = useCallback(
(inputAmount: string) => {
onUserInput(Field.INPUT, inputAmount)
@@ -69,15 +64,6 @@ export function useLimitActionHandlers() {
[setInputValue, setCurrencyIn, setCurrencyOut],
)
- useEffect(() => {
- if (
- (inputCurrency && !currencyIn?.equals(inputCurrency)) ||
- (outputCurrency && !currencyOut?.equals(outputCurrency))
- ) {
- onSelectPair(inputCurrency ?? undefined, outputCurrency ?? undefined)
- }
- }, [onSelectPair, inputCurrency, outputCurrency, currencyIn, currencyOut])
-
const pushOrderNeedCreated = useCallback(
(order: CreateOrderParam) => {
dispatch(pushOrderNeedCreatedAction(order))
diff --git a/src/state/swap/actions.ts b/src/state/swap/actions.ts
index 2b8fe6c0d5..c1bc061a60 100644
--- a/src/state/swap/actions.ts
+++ b/src/state/swap/actions.ts
@@ -7,7 +7,6 @@ export enum Field {
OUTPUT = 'OUTPUT',
}
-export const selectCurrency = createAction<{ field: Field; currencyId: string }>('swap/selectCurrency')
export const resetSelectCurrency = createAction<{ field: Field }>('swap/resetSelectCurrency')
export const switchCurrencies = createAction('swap/switchCurrencies')
diff --git a/src/state/swap/hooks.ts b/src/state/swap/hooks.ts
index cac39deb23..d08d41dfc9 100644
--- a/src/state/swap/hooks.ts
+++ b/src/state/swap/hooks.ts
@@ -1,38 +1,21 @@
-import { Trade } from '@kyberswap/ks-sdk-classic'
-import { ChainId, Currency, CurrencyAmount, TradeType } from '@kyberswap/ks-sdk-core'
-import { t } from '@lingui/macro'
+import { ChainId, Currency, CurrencyAmount } from '@kyberswap/ks-sdk-core'
import { ParsedUrlQuery } from 'querystring'
-import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
+import { useCallback, useEffect, useMemo } from 'react'
import { useDispatch, useSelector } from 'react-redux'
-import { useLocation, useNavigate, useParams } from 'react-router-dom'
+import { useNavigate, useParams } from 'react-router-dom'
-import { APP_PATHS, BAD_RECIPIENT_ADDRESSES } from 'constants/index'
+import { APP_PATHS } from 'constants/index'
import { CORRELATED_COINS_ADDRESS, DEFAULT_OUTPUT_TOKEN_BY_CHAIN, NativeCurrencies } from 'constants/tokens'
import { useActiveWeb3React } from 'hooks'
-import { useCurrencyV2, useStableCoins } from 'hooks/Tokens'
-import { useTradeExactIn } from 'hooks/Trades'
-import useENS from 'hooks/useENS'
-import useParsedQueryString from 'hooks/useParsedQueryString'
-import { getUrlMatchParams } from 'hooks/useSyncTokenSymbolToUrl'
+import { useAllTokens, useCurrencyV2, useStableCoins } from 'hooks/Tokens'
+import { NETWORKS_INFO } from 'hooks/useChainsConfig'
import { AppDispatch, AppState } from 'state/index'
-import {
- Field,
- replaceSwapState,
- resetSelectCurrency,
- selectCurrency,
- setRecipient,
- setTrade,
- switchCurrencies,
- switchCurrenciesV2,
- typeInput,
-} from 'state/swap/actions'
+import { Field, resetSelectCurrency, setRecipient, setTrade, typeInput } from 'state/swap/actions'
import { SwapState } from 'state/swap/reducer'
-import { useDegenModeManager, useUserSlippageTolerance } from 'state/user/hooks'
-import { useCurrencyBalances } from 'state/wallet/hooks'
+import { useDegenModeManager } from 'state/user/hooks'
import { isAddress, isAddressString } from 'utils'
import { Aggregator } from 'utils/aggregator'
import { parseFraction } from 'utils/numbers'
-import { computeSlippageAdjustedAmounts } from 'utils/prices'
export function useSwapState(): AppState['swap'] {
return useSelector(state => state.swap)
@@ -50,16 +33,41 @@ export function useSwapActionHandlers(): {
const { chainId } = useActiveWeb3React()
const dispatch = useDispatch()
+ const navigate = useNavigate()
+ const { fromCurrency, toCurrency } = useCurrencyFromUrl()
+
+ const allTokens = useAllTokens()
+
const onCurrencySelection = useCallback(
(field: Field, currency: Currency) => {
- dispatch(
- selectCurrency({
- field,
- currencyId: currency.isNative ? (NativeCurrencies[chainId].symbol as string) : currency.address,
- }),
+ let f = fromCurrency,
+ to = toCurrency
+
+ const isWhitelisted = allTokens[currency?.wrapped.address || '']?.isWhitelisted
+
+ if (field === Field.INPUT) {
+ const newFrom =
+ isWhitelisted || currency.isNative ? currency.symbol?.toLowerCase() || '' : currency.address.toLowerCase()
+ f = newFrom
+ if (newFrom === toCurrency || currency.symbol?.toLowerCase() === toCurrency) {
+ to = fromCurrency
+ }
+ } else {
+ const newTo =
+ isWhitelisted || currency.isNative ? currency.symbol?.toLowerCase() || '' : currency.address.toLowerCase()
+ to = newTo
+ if (newTo === f || currency?.symbol?.toLowerCase() === fromCurrency) {
+ f = toCurrency
+ }
+ }
+
+ navigate(
+ `/${window.location.pathname.startsWith('/limit') ? 'limit' : 'swap'}/${
+ NETWORKS_INFO[chainId].route
+ }/${f}-to-${to}`,
)
},
- [dispatch, chainId],
+ [fromCurrency, chainId, toCurrency, navigate, allTokens],
)
const [isDegenMode] = useDegenModeManager()
@@ -80,12 +88,20 @@ export function useSwapActionHandlers(): {
)
const onSwitchTokens = useCallback(() => {
- dispatch(switchCurrencies())
- }, [dispatch])
+ navigate(
+ `/${window.location.pathname.startsWith('/limit') ? 'limit' : 'swap'}/${
+ NETWORKS_INFO[chainId].route
+ }/${toCurrency}-to-${fromCurrency}`,
+ )
+ }, [fromCurrency, toCurrency, navigate, chainId])
const onSwitchTokensV2 = useCallback(() => {
- dispatch(switchCurrenciesV2())
- }, [dispatch])
+ navigate(
+ `/${window.location.pathname.startsWith('/limit') ? 'limit' : 'swap'}/${
+ NETWORKS_INFO[chainId].route
+ }/${toCurrency}-to-${fromCurrency}`,
+ )
+ }, [fromCurrency, toCurrency, navigate, chainId])
const onUserInput = useCallback(
(field: Field, typedValue: string) => {
@@ -144,119 +160,6 @@ export function tryParseAmount(
return undefined
}
-/**
- * Returns true if any of the pairs or tokens in a trade have the given checksummed address
- * @param trade to check for the given address
- * @param checksummedAddress address to check in the pairs and tokens
- */
-function involvesAddress(trade: Trade, checksummedAddress: string): boolean {
- return (
- trade.route.path.some(token => token.address === checksummedAddress) ||
- trade.route.pairs.some(pair => pair.liquidityToken.address === checksummedAddress)
- )
-}
-
-// from the current swap inputs, compute the best trade and return it.
-function useDerivedSwapInfo(): {
- currencies: { [field in Field]?: Currency }
- currencyBalances: { [field in Field]?: CurrencyAmount }
- parsedAmount: CurrencyAmount | undefined
- v2Trade: Trade | undefined
- inputError?: string
-} {
- const { account, chainId } = useActiveWeb3React()
-
- const {
- independentField,
- typedValue,
- [Field.INPUT]: { currencyId: inputCurrencyId },
- [Field.OUTPUT]: { currencyId: outputCurrencyId },
- recipient,
- } = useSwapState()
-
- const inputCurrency = useCurrencyV2(inputCurrencyId)
- const outputCurrency = useCurrencyV2(outputCurrencyId)
- const recipientLookup = useENS(recipient ?? undefined)
- const to: string | null = (recipient === null ? account : recipientLookup.address) ?? null
-
- const relevantTokenBalances = useCurrencyBalances(
- useMemo(() => [inputCurrency ?? undefined, outputCurrency ?? undefined], [inputCurrency, outputCurrency]),
- )
-
- const isExactIn = useMemo(() => independentField === Field.INPUT, [independentField])
- const parsedAmount = useMemo(
- () => tryParseAmount(typedValue, (isExactIn ? inputCurrency : outputCurrency) ?? undefined),
- [inputCurrency, isExactIn, outputCurrency, typedValue],
- )
-
- const currencyAmountIn = useMemo(() => (isExactIn ? parsedAmount : undefined), [isExactIn, parsedAmount])
- const currencyOut = useMemo(() => outputCurrency ?? undefined, [outputCurrency])
- const bestTradeExactIn = useTradeExactIn(currencyAmountIn, currencyOut)
-
- const v2Trade = bestTradeExactIn
-
- const currencyBalances = {
- [Field.INPUT]: relevantTokenBalances[0],
- [Field.OUTPUT]: relevantTokenBalances[1],
- }
-
- const currencies: { [field in Field]?: Currency } = useMemo(() => {
- return {
- [Field.INPUT]: inputCurrency ?? undefined,
- [Field.OUTPUT]: outputCurrency ?? undefined,
- }
- }, [inputCurrency, outputCurrency])
-
- let inputError: string | undefined
- if (!account) {
- inputError = t`Connect wallet`
- }
-
- if (!parsedAmount) {
- if (typedValue) inputError = inputError ?? t`Invalid amount`
- else inputError = inputError ?? t`Enter an amount`
- }
-
- if (!currencies[Field.INPUT] || !currencies[Field.OUTPUT]) {
- inputError = inputError ?? t`Select a token`
- }
-
- const formattedTo = isAddress(chainId, to)
- if (!to || !formattedTo) {
- inputError = inputError ?? t`Enter a recipient`
- } else {
- if (
- BAD_RECIPIENT_ADDRESSES.has(formattedTo) ||
- (bestTradeExactIn && involvesAddress(bestTradeExactIn, formattedTo))
- ) {
- inputError = inputError ?? t`Invalid recipient`
- }
- }
-
- const [allowedSlippage] = useUserSlippageTolerance()
-
- const slippageAdjustedAmounts = v2Trade && allowedSlippage && computeSlippageAdjustedAmounts(v2Trade, allowedSlippage)
-
- // compare input balance to max input based on version
- const [balanceIn, amountIn] = [
- currencyBalances[Field.INPUT],
- slippageAdjustedAmounts ? slippageAdjustedAmounts[Field.INPUT] : null,
- ]
-
- if (balanceIn && amountIn && balanceIn.lessThan(amountIn)) {
- const symbol = amountIn.currency.symbol
- inputError = t`Insufficient ${symbol} balance.`
- }
-
- return {
- currencies,
- currencyBalances,
- parsedAmount,
- v2Trade: v2Trade ?? undefined,
- inputError,
- }
-}
-
function parseCurrencyFromURLParameter(urlParam: any, chainId: ChainId): string {
if (typeof urlParam === 'string') {
const valid = isAddress(chainId, urlParam)
@@ -285,7 +188,14 @@ export function queryParametersToSwapState(
parsedQs: ParsedUrlQuery,
chainId: ChainId,
isMatchPath: boolean,
-): SwapState {
+): SwapState & {
+ [Field.INPUT]: {
+ currencyId: string
+ }
+ [Field.OUTPUT]: {
+ currencyId: string
+ }
+} {
let inputCurrency = parseCurrencyFromURLParameter(isMatchPath ? parsedQs.inputCurrency : null, chainId)
let outputCurrency = parseCurrencyFromURLParameter(isMatchPath ? parsedQs.outputCurrency : null, chainId)
if (inputCurrency === outputCurrency) {
@@ -317,121 +227,77 @@ export function queryParametersToSwapState(
}
}
-const getCurrencySymbolOrAddress = (currency: Currency | undefined): string | undefined => {
- if (!currency) return ''
- return currency.isNative ? currency.symbol : currency.address
-}
-
-// updates the swap state to use the defaults for a given network
-export const useDefaultsFromURLSearch = ():
- | {
- inputCurrencyId?: string
- outputCurrencyId?: string
- }
- | undefined => {
- // TODO: this hook is called more than 100 times just on startup, need to check
-
- const dispatch = useDispatch()
- const params = useParams()
- const { fromCurrency, toCurrency } = getUrlMatchParams(params)
+export const useCurrencyFromUrl = () => {
const { chainId } = useActiveWeb3React()
-
- // this is already memo-ed
- const parsedQs = useParsedQueryString()
-
- const [result, setResult] = useState<{
- inputCurrencyId?: string
- outputCurrencyId?: string
- }>()
-
- const { currencies } = useDerivedSwapInfo()
-
- const currenciesRef = useRef(currencies)
- currenciesRef.current = currencies
- const { pathname } = useLocation()
- const refPathname = useRef(pathname)
- refPathname.current = pathname
-
- useEffect(() => {
- if (!chainId) {
- return
+ const { currency: currencyParam } = useParams()
+
+ return useMemo(() => {
+ const matches = currencyParam?.split('-to-')
+ const fromCurrency = matches?.[0]?.toLowerCase() || ''
+ let toCurrency = matches?.[1]?.toLowerCase() || ''
+ const nativeSymbol = NativeCurrencies[chainId].symbol?.toLowerCase() || 'eth'
+ const defaultOutput = DEFAULT_OUTPUT_TOKEN_BY_CHAIN[chainId]?.symbol?.toLowerCase() || ''
+
+ if (!fromCurrency && !toCurrency)
+ return {
+ fromCurrency: nativeSymbol,
+ toCurrency: defaultOutput,
+ }
+
+ if (fromCurrency === toCurrency) {
+ toCurrency = ''
}
- const parsed = queryParametersToSwapState(
- parsedQs,
- chainId,
- refPathname.current.startsWith(APP_PATHS.SWAP) || refPathname.current.startsWith(APP_PATHS.PARTNER_SWAP),
- )
-
- const outputCurrencyAddress = DEFAULT_OUTPUT_TOKEN_BY_CHAIN[chainId]?.address || ''
-
- // symbol or address of the input
- const storedInputValue = getCurrencySymbolOrAddress(currenciesRef.current[Field.INPUT])
- const storedOutputValue = getCurrencySymbolOrAddress(currenciesRef.current[Field.OUTPUT])
-
- const native = NativeCurrencies[chainId].symbol
-
- const parsedInputValue = parsed[Field.INPUT].currencyId // default inputCurrency is the native token
- const parsedOutputValue = parsed[Field.OUTPUT].currencyId || outputCurrencyAddress
-
- // priority order
- // 1. address on url (inputCurrency, outputCurrency)
- // 2. previous currency (to not reset default pair when back to swap page)
- // 3. default pair
- const inputCurrencyId = parsedQs.inputCurrency ? parsedInputValue : storedInputValue || parsedInputValue
- let outputCurrencyId = parsedQs.outputCurrency ? parsedOutputValue : storedOutputValue || parsedOutputValue
-
- if (outputCurrencyId === native && inputCurrencyId === native) {
- outputCurrencyId = outputCurrencyAddress
+ return {
+ fromCurrency: fromCurrency || (toCurrency === nativeSymbol ? defaultOutput : nativeSymbol),
+ toCurrency: toCurrency || defaultOutput,
}
-
- if (fromCurrency || toCurrency) return
- dispatch(
- replaceSwapState({
- field: parsed.independentField,
- inputCurrencyId,
- outputCurrencyId,
- recipient: parsed.recipient,
- typedValue: parsed.typedValue,
- }),
- )
-
- setResult({
- inputCurrencyId,
- outputCurrencyId,
- })
- // can not add `currencies` && pathname as dependency here because it will retrigger replaceSwapState => got some issue when we have in/outputCurrency on URL
- }, [dispatch, chainId, parsedQs, fromCurrency, toCurrency])
-
- return result
+ }, [currencyParam, chainId])
}
export const useInputCurrency = () => {
- const inputCurrencyId = useSelector((state: AppState) => state.swap[Field.INPUT].currencyId)
- const inputCurrency = useCurrencyV2(inputCurrencyId)
+ const { fromCurrency } = useCurrencyFromUrl()
+ const allTokens = useAllTokens()
+
+ const token = useMemo(() => {
+ return Object.values(allTokens).find(item => item?.symbol?.toLowerCase() === fromCurrency.toLowerCase())
+ }, [allTokens, fromCurrency])
+
+ const inputCurrency = useCurrencyV2(token ? token.address : fromCurrency)
return inputCurrency || undefined
}
export const useOutputCurrency = () => {
- const outputCurrencyId = useSelector((state: AppState) => state.swap[Field.OUTPUT].currencyId)
- const outputCurrency = useCurrencyV2(outputCurrencyId)
+ const { toCurrency } = useCurrencyFromUrl()
+ const allTokens = useAllTokens()
+
+ const token = useMemo(() => {
+ return Object.values(allTokens).find(item => item?.symbol?.toLowerCase() === toCurrency.toLowerCase())
+ }, [allTokens, toCurrency])
+
+ const outputCurrency = useCurrencyV2(token ? token.address : toCurrency)
return outputCurrency || undefined
}
export const useCheckStablePairSwap = () => {
const { chainId } = useActiveWeb3React()
const { isStableCoin } = useStableCoins(chainId)
- const inputCurrencyId = useSelector((state: AppState) => state.swap[Field.INPUT].currencyId)
- const outputCurrencyId = useSelector((state: AppState) => state.swap[Field.OUTPUT].currencyId)
+ const inputCurrency = useInputCurrency()
+ const outputCurrency = useOutputCurrency()
- const isStablePairSwap = isStableCoin(inputCurrencyId) && isStableCoin(outputCurrencyId)
+ const isStablePairSwap = isStableCoin(inputCurrency?.wrapped.address) && isStableCoin(outputCurrency?.wrapped.address)
return isStablePairSwap
}
export const useCheckCorrelatedPair = (customIn?: string, customOut?: string) => {
const { chainId } = useActiveWeb3React()
- const inputCurrencyId = useSelector((state: AppState) => customIn || state.swap[Field.INPUT].currencyId)
- const outputCurrencyId = useSelector((state: AppState) => customOut || state.swap[Field.OUTPUT].currencyId)
+
+ const inputCurrency = useInputCurrency()
+ const outputCurrency = useOutputCurrency()
+
+ const inputCurrencyId = customIn || inputCurrency?.wrapped.address
+ const outputCurrencyId = customOut || outputCurrency?.wrapped.address
+
const inputAddress =
NativeCurrencies[chainId].symbol === inputCurrencyId
? NativeCurrencies[chainId].wrapped.address
@@ -447,8 +313,10 @@ export const useCheckCorrelatedPair = (customIn?: string, customOut?: string) =>
export const useSwitchPairToLimitOrder = () => {
const navigate = useNavigate()
- const inputCurrencyId = useSelector((state: AppState) => state.swap[Field.INPUT].currencyId)
- const outputCurrencyId = useSelector((state: AppState) => state.swap[Field.OUTPUT].currencyId)
+
+ const inputCurrencyId = useInputCurrency()?.wrapped.address
+ const outputCurrencyId = useOutputCurrency()?.wrapped.address
+
const { networkInfo } = useActiveWeb3React()
return useCallback(
diff --git a/src/state/swap/reducer.ts b/src/state/swap/reducer.ts
index fb92eabab5..ea106b08d8 100644
--- a/src/state/swap/reducer.ts
+++ b/src/state/swap/reducer.ts
@@ -1,14 +1,11 @@
import { createReducer } from '@reduxjs/toolkit'
-import { APP_PATHS } from 'constants/index'
import { Aggregator } from 'utils/aggregator'
-import { queryStringToObject } from 'utils/string'
import {
Field,
replaceSwapState,
resetSelectCurrency,
- selectCurrency,
setRecipient,
setTrade,
setTrendingSoonShowed,
@@ -20,12 +17,12 @@ import {
export interface SwapState {
readonly independentField: Field // TODO: remove since unused anymore
readonly typedValue: string
- readonly [Field.INPUT]: {
- readonly currencyId: string | undefined
- }
- readonly [Field.OUTPUT]: {
- readonly currencyId: string | undefined
- }
+ // readonly [Field.INPUT]: {
+ // readonly currencyId: string | undefined
+ // }
+ // readonly [Field.OUTPUT]: {
+ // readonly currencyId: string | undefined
+ // }
// the typed recipient address or ENS name, or null if swap should go to sender
readonly recipient: string | null
readonly trendingSoonShowed?: boolean
@@ -40,20 +37,20 @@ export interface SwapState {
readonly isSelectTokenManually: boolean
}
-const { search, pathname } = window.location
-const { inputCurrency = '', outputCurrency = '' } = pathname.startsWith(APP_PATHS.SWAP)
- ? queryStringToObject(search)
- : {}
+// const { search, pathname } = window.location
+// const { inputCurrency = '', outputCurrency = '' } = pathname.startsWith(APP_PATHS.SWAP)
+// ? queryStringToObject(search)
+// : {}
const initialState: SwapState = {
independentField: Field.INPUT,
typedValue: '1',
- [Field.INPUT]: {
- currencyId: inputCurrency?.toString() || '',
- },
- [Field.OUTPUT]: {
- currencyId: outputCurrency?.toString() || '',
- },
+ // [Field.INPUT]: {
+ // currencyId: inputCurrency?.toString() || '',
+ // },
+ // [Field.OUTPUT]: {
+ // currencyId: outputCurrency?.toString() || '',
+ // },
recipient: null,
// Flag to only show animation of trending soon banner 1 time
trendingSoonShowed: false,
@@ -70,43 +67,40 @@ const initialState: SwapState = {
export default createReducer(initialState, builder =>
builder
- .addCase(
- replaceSwapState,
- (state, { payload: { typedValue, recipient, field, inputCurrencyId, outputCurrencyId } }) => {
- return {
- ...state,
- [Field.INPUT]: {
- currencyId: inputCurrencyId,
- },
- [Field.OUTPUT]: {
- currencyId: outputCurrencyId,
- },
- independentField: field,
- typedValue: typedValue || state.typedValue || '1',
- recipient,
- }
- },
- )
- .addCase(selectCurrency, (state, { payload: { currencyId, field } }) => {
- const otherField = field === Field.INPUT ? Field.OUTPUT : Field.INPUT
- if (currencyId === state[otherField].currencyId) {
- // the case where we have to swap the order
- return {
- ...state,
- isSelectTokenManually: true,
- independentField: state.independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT,
- [field]: { currencyId },
- [otherField]: { currencyId: state[field].currencyId },
- }
- } else {
- // the normal case
- return {
- ...state,
- isSelectTokenManually: true,
- [field]: { currencyId },
- }
+ .addCase(replaceSwapState, (state, { payload: { typedValue, recipient, field } }) => {
+ return {
+ ...state,
+ // [Field.INPUT]: {
+ // currencyId: inputCurrencyId,
+ // },
+ // [Field.OUTPUT]: {
+ // currencyId: outputCurrencyId,
+ // },
+ independentField: field,
+ typedValue: typedValue || state.typedValue || '1',
+ recipient,
}
})
+ // .addCase(selectCurrency, (state, { payload: { currencyId, field } }) => {
+ // const otherField = field === Field.INPUT ? Field.OUTPUT : Field.INPUT
+ // if (currencyId === state[otherField].currencyId) {
+ // // the case where we have to swap the order
+ // return {
+ // ...state,
+ // isSelectTokenManually: true,
+ // independentField: state.independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT,
+ // [field]: { currencyId },
+ // [otherField]: { currencyId: state[field].currencyId },
+ // }
+ // } else {
+ // // the normal case
+ // return {
+ // ...state,
+ // isSelectTokenManually: true,
+ // [field]: { currencyId },
+ // }
+ // }
+ // })
.addCase(resetSelectCurrency, (state, { payload: { field } }) => {
return {
...state,
@@ -118,8 +112,8 @@ export default createReducer(initialState, builder =>
...state,
isSelectTokenManually: true,
independentField: state.independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT,
- [Field.INPUT]: { currencyId: state[Field.OUTPUT].currencyId },
- [Field.OUTPUT]: { currencyId: state[Field.INPUT].currencyId },
+ // [Field.INPUT]: { currencyId: state[Field.OUTPUT].currencyId },
+ // [Field.OUTPUT]: { currencyId: state[Field.INPUT].currencyId },
}
})
.addCase(switchCurrenciesV2, state => {
@@ -127,8 +121,8 @@ export default createReducer(initialState, builder =>
...state,
independentField: Field.INPUT,
isSelectTokenManually: true,
- [Field.INPUT]: { currencyId: state[Field.OUTPUT].currencyId },
- [Field.OUTPUT]: { currencyId: state[Field.INPUT].currencyId },
+ // [Field.INPUT]: { currencyId: state[Field.OUTPUT].currencyId },
+ // [Field.OUTPUT]: { currencyId: state[Field.INPUT].currencyId },
}
})
.addCase(typeInput, (state, { payload: { field, typedValue } }) => {
diff --git a/src/state/swap/useAggregator.ts b/src/state/swap/useAggregator.ts
deleted file mode 100644
index fec080c236..0000000000
--- a/src/state/swap/useAggregator.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-import { Currency, CurrencyAmount } from '@kyberswap/ks-sdk-core'
-import { t } from '@lingui/macro'
-import { useMemo } from 'react'
-
-import { BAD_RECIPIENT_ADDRESSES } from 'constants/index'
-import { useActiveWeb3React } from 'hooks'
-import { useCurrency } from 'hooks/Tokens'
-import { useTradeExactInV2 } from 'hooks/Trades'
-import useENS from 'hooks/useENS'
-import { useUserSlippageTolerance } from 'state/user/hooks'
-import { useCurrencyBalances } from 'state/wallet/hooks'
-import { isAddress } from 'utils'
-import { Aggregator } from 'utils/aggregator'
-import { computeSlippageAdjustedAmounts } from 'utils/prices'
-
-import { Field } from './actions'
-import { tryParseAmount, useSwapState } from './hooks'
-
-// from the current swap inputs, compute the best trade and return it.
-export function useDerivedSwapInfoV2(): {
- currencies: { [field in Field]?: Currency }
- currencyBalances: { [field in Field]?: CurrencyAmount }
- parsedAmount: CurrencyAmount | undefined
- v2Trade: Aggregator | undefined
- inputError?: string
- onRefresh: (resetRoute: boolean, minimumLoadingTime: number) => void
- loading: boolean
-} {
- const { account, chainId } = useActiveWeb3React()
-
- const {
- independentField,
- typedValue,
- [Field.INPUT]: { currencyId: inputCurrencyId },
- [Field.OUTPUT]: { currencyId: outputCurrencyId },
- recipient,
- } = useSwapState()
-
- const inputCurrency = useCurrency(inputCurrencyId)
- const outputCurrency = useCurrency(outputCurrencyId)
- const recipientLookup = useENS(recipient ?? undefined)
- const to: string | null = (recipient === null || recipient === '' ? account : recipientLookup.address) ?? null
-
- const relevantTokenBalances = useCurrencyBalances(
- useMemo(() => [inputCurrency ?? undefined, outputCurrency ?? undefined], [inputCurrency, outputCurrency]),
- )
-
- const isExactIn: boolean = independentField === Field.INPUT
-
- const currency = isExactIn ? inputCurrency : outputCurrency
- const parsedAmount = useMemo(() => {
- return tryParseAmount(typedValue, currency ?? undefined)
- }, [typedValue, currency])
-
- const [allowedSlippage] = useUserSlippageTolerance()
-
- const {
- trade: bestTradeExactIn,
- onUpdateCallback,
- loading,
- } = useTradeExactInV2(isExactIn ? parsedAmount : undefined, outputCurrency ?? undefined, to)
-
- const v2Trade = isExactIn ? bestTradeExactIn : undefined
-
- const balanceInput = relevantTokenBalances[0]
- const balanceOutput = relevantTokenBalances[1]
- const currencyBalances = useMemo(() => {
- return {
- [Field.INPUT]: balanceInput,
- [Field.OUTPUT]: balanceOutput,
- }
- }, [balanceInput, balanceOutput])
-
- const currencies: { [field in Field]?: Currency } = useMemo(() => {
- return {
- [Field.INPUT]: inputCurrency ?? undefined,
- [Field.OUTPUT]: outputCurrency ?? undefined,
- }
- }, [inputCurrency, outputCurrency])
-
- let inputError: string | undefined
- if (!account) {
- inputError = t`Connect wallet`
- }
-
- if (!parsedAmount) {
- if (typedValue) inputError = inputError ?? t`Invalid amount`
- else inputError = inputError ?? t`Enter an amount`
- }
-
- if (!currencies[Field.INPUT] || !currencies[Field.OUTPUT]) {
- inputError = inputError ?? t`Select a token`
- }
-
- const formattedTo = isAddress(chainId, to)
- if (!to || !formattedTo) {
- inputError = inputError ?? t`Enter a recipient`
- } else {
- if (BAD_RECIPIENT_ADDRESSES.has(formattedTo)) {
- inputError = inputError ?? t`Invalid recipient`
- }
- }
-
- const slippageAdjustedAmounts = useMemo(
- () => (v2Trade && allowedSlippage ? computeSlippageAdjustedAmounts(v2Trade, allowedSlippage) : null),
- [allowedSlippage, v2Trade],
- )
-
- // compare input balance to max input based on version
- const [balanceIn, amountIn] = [currencyBalances[Field.INPUT], slippageAdjustedAmounts?.[Field.INPUT]]
-
- if (amountIn && ((balanceIn && balanceIn.lessThan(amountIn)) || !balanceIn)) {
- const symbol = amountIn.currency.symbol
- inputError = t`Insufficient ${symbol} balance.`
- }
-
- return useMemo(
- () => ({
- currencies,
- currencyBalances,
- parsedAmount,
- v2Trade: v2Trade ?? undefined,
- inputError,
- onRefresh: onUpdateCallback,
- loading,
- }),
- [currencies, currencyBalances, inputError, loading, onUpdateCallback, parsedAmount, v2Trade],
- )
-}