Commit b161022f authored by Tina's avatar Tina Committed by GitHub

feat: Use local reducer in Swap flow (#6312)

* test: swap flow cypress tests

* fix: use default parameter

* use local reducer in swap flow

* remove swap from global reducer

* fix: remove comments

* feat: add new test

* move token constant to fixtures file

---------
Co-authored-by: default avatarEddie Dugan <eddie.dugan@uniswap.org>
parent a527f009
import { SupportedChainId, WETH9 } from '@uniswap/sdk-core' import { WETH_GOERLI } from '../fixtures/constants'
import { getTestSelector } from '../utils' import { getTestSelector } from '../utils'
describe('Swap', () => { describe('Swap', () => {
...@@ -87,7 +86,7 @@ describe('Swap', () => { ...@@ -87,7 +86,7 @@ describe('Swap', () => {
}) })
it('should have the correct default input from URL params ', () => { it('should have the correct default input from URL params ', () => {
cy.visit(`/swap?inputCurrency=${WETH9[SupportedChainId.GOERLI].address}`) cy.visit(`/swap?inputCurrency=${WETH_GOERLI}`)
verifyToken('input', 'WETH') verifyToken('input', 'WETH')
verifyToken('output', null) verifyToken('output', null)
...@@ -100,7 +99,7 @@ describe('Swap', () => { ...@@ -100,7 +99,7 @@ describe('Swap', () => {
}) })
it('should have the correct default output from URL params ', () => { it('should have the correct default output from URL params ', () => {
cy.visit(`/swap?outputCurrency=${WETH9[SupportedChainId.GOERLI].address}`) cy.visit(`/swap?outputCurrency=${WETH_GOERLI}`)
verifyToken('input', null) verifyToken('input', null)
verifyToken('output', 'WETH') verifyToken('output', 'WETH')
...@@ -134,4 +133,13 @@ describe('Swap', () => { ...@@ -134,4 +133,13 @@ describe('Swap', () => {
cy.get(getTestSelector('swap-settings-button')).click() cy.get(getTestSelector('swap-settings-button')).click()
cy.contains('Settings').should('not.exist') cy.contains('Settings').should('not.exist')
}) })
it('inputs reset when navigating between pages', () => {
cy.get('#swap-currency-input .token-amount-input').clear().type('0.01')
cy.get('#swap-currency-output .token-amount-input').should('not.equal', '')
cy.visit('/pool')
cy.visit('/swap')
cy.get('#swap-currency-input .token-amount-input').should('have.value', '')
cy.get('#swap-currency-output .token-amount-input').should('not.equal', '')
})
}) })
export const WETH_GOERLI = '0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6'
...@@ -30,7 +30,7 @@ import { useSwapCallback } from 'hooks/useSwapCallback' ...@@ -30,7 +30,7 @@ import { useSwapCallback } from 'hooks/useSwapCallback'
import { useUSDPrice } from 'hooks/useUSDPrice' import { useUSDPrice } from 'hooks/useUSDPrice'
import JSBI from 'jsbi' import JSBI from 'jsbi'
import { formatSwapQuoteReceivedEventProperties } from 'lib/utils/analytics' import { formatSwapQuoteReceivedEventProperties } from 'lib/utils/analytics'
import { useCallback, useEffect, useMemo, useState } from 'react' import { useCallback, useEffect, useMemo, useReducer, useState } from 'react'
import { ReactNode } from 'react' import { ReactNode } from 'react'
import { ArrowDown, Info } from 'react-feather' import { ArrowDown, Info } from 'react-feather'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
...@@ -57,19 +57,14 @@ import { useCurrency, useDefaultActiveTokens } from '../../hooks/Tokens' ...@@ -57,19 +57,14 @@ import { useCurrency, useDefaultActiveTokens } from '../../hooks/Tokens'
import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported' import { useIsSwapUnsupported } from '../../hooks/useIsSwapUnsupported'
import useWrapCallback, { WrapErrorText, WrapType } from '../../hooks/useWrapCallback' import useWrapCallback, { WrapErrorText, WrapType } from '../../hooks/useWrapCallback'
import { Field } from '../../state/swap/actions' import { Field } from '../../state/swap/actions'
import { import { useDefaultsFromURLSearch, useDerivedSwapInfo, useSwapActionHandlers } from '../../state/swap/hooks'
useDefaultsFromURLSearch, import swapReducer, { initialState as initialSwapState } from '../../state/swap/reducer'
useDerivedSwapInfo,
useSwapActionHandlers,
useSwapState,
} from '../../state/swap/hooks'
import { useExpertModeManager } from '../../state/user/hooks' import { useExpertModeManager } from '../../state/user/hooks'
import { LinkStyledButton, ThemedText } from '../../theme' import { LinkStyledButton, ThemedText } from '../../theme'
import { computeFiatValuePriceImpact } from '../../utils/computeFiatValuePriceImpact' import { computeFiatValuePriceImpact } from '../../utils/computeFiatValuePriceImpact'
import { maxAmountSpend } from '../../utils/maxAmountSpend' import { maxAmountSpend } from '../../utils/maxAmountSpend'
import { computeRealizedPriceImpact, warningSeverity } from '../../utils/prices' import { computeRealizedPriceImpact, warningSeverity } from '../../utils/prices'
import { supportedChainId } from '../../utils/supportedChainId' import { supportedChainId } from '../../utils/supportedChainId'
const ArrowContainer = styled.div` const ArrowContainer = styled.div`
display: inline-block; display: inline-block;
display: inline-flex; display: inline-flex;
...@@ -199,7 +194,8 @@ export default function Swap({ className }: { className?: string }) { ...@@ -199,7 +194,8 @@ export default function Swap({ className }: { className?: string }) {
// for expert mode // for expert mode
const [isExpertMode] = useExpertModeManager() const [isExpertMode] = useExpertModeManager()
// swap state // swap state
const { independentField, typedValue, recipient } = useSwapState() const [state, dispatch] = useReducer(swapReducer, initialSwapState)
const { typedValue, recipient, independentField } = state
const { const {
trade: { state: tradeState, trade }, trade: { state: tradeState, trade },
allowedSlippage, allowedSlippage,
...@@ -207,7 +203,7 @@ export default function Swap({ className }: { className?: string }) { ...@@ -207,7 +203,7 @@ export default function Swap({ className }: { className?: string }) {
parsedAmount, parsedAmount,
currencies, currencies,
inputError: swapInputError, inputError: swapInputError,
} = useDerivedSwapInfo() } = useDerivedSwapInfo(state)
const { const {
wrapType, wrapType,
...@@ -248,7 +244,7 @@ export default function Swap({ className }: { className?: string }) { ...@@ -248,7 +244,7 @@ export default function Swap({ className }: { className?: string }) {
[fiatValueTradeInput, fiatValueTradeOutput, routeIsSyncing, trade] [fiatValueTradeInput, fiatValueTradeOutput, routeIsSyncing, trade]
) )
const { onSwitchTokens, onCurrencySelection, onUserInput, onChangeRecipient } = useSwapActionHandlers() const { onSwitchTokens, onCurrencySelection, onUserInput, onChangeRecipient } = useSwapActionHandlers(dispatch)
const isValid = !swapInputError const isValid = !swapInputError
const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT
......
...@@ -9,7 +9,6 @@ import logs from './logs/slice' ...@@ -9,7 +9,6 @@ import logs from './logs/slice'
import mint from './mint/reducer' import mint from './mint/reducer'
import mintV3 from './mint/v3/reducer' import mintV3 from './mint/v3/reducer'
import { routingApi } from './routing/slice' import { routingApi } from './routing/slice'
import swap from './swap/reducer'
import transactions from './transactions/reducer' import transactions from './transactions/reducer'
import user from './user/reducer' import user from './user/reducer'
import wallets from './wallets/reducer' import wallets from './wallets/reducer'
...@@ -20,7 +19,6 @@ export default { ...@@ -20,7 +19,6 @@ export default {
connection, connection,
transactions, transactions,
wallets, wallets,
swap,
mint, mint,
mintV3, mintV3,
burn, burn,
......
...@@ -6,7 +6,8 @@ import { useBestTrade } from 'hooks/useBestTrade' ...@@ -6,7 +6,8 @@ import { useBestTrade } from 'hooks/useBestTrade'
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
import { ParsedQs } from 'qs' import { ParsedQs } from 'qs'
import { ReactNode, useCallback, useEffect, useMemo } from 'react' import { ReactNode, useCallback, useEffect, useMemo } from 'react'
import { useAppDispatch, useAppSelector } from 'state/hooks' import { AnyAction } from 'redux'
import { useAppDispatch } from 'state/hooks'
import { InterfaceTrade, TradeState } from 'state/routing/types' import { InterfaceTrade, TradeState } from 'state/routing/types'
import { useUserSlippageToleranceWithDefault } from 'state/user/hooks' import { useUserSlippageToleranceWithDefault } from 'state/user/hooks'
...@@ -16,21 +17,15 @@ import useENS from '../../hooks/useENS' ...@@ -16,21 +17,15 @@ import useENS from '../../hooks/useENS'
import useParsedQueryString from '../../hooks/useParsedQueryString' import useParsedQueryString from '../../hooks/useParsedQueryString'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
import { useCurrencyBalances } from '../connection/hooks' import { useCurrencyBalances } from '../connection/hooks'
import { AppState } from '../types'
import { Field, replaceSwapState, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions' import { Field, replaceSwapState, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions'
import { SwapState } from './reducer' import { SwapState } from './reducer'
export function useSwapState(): AppState['swap'] { export function useSwapActionHandlers(dispatch: React.Dispatch<AnyAction>): {
return useAppSelector((state) => state.swap)
}
export function useSwapActionHandlers(): {
onCurrencySelection: (field: Field, currency: Currency) => void onCurrencySelection: (field: Field, currency: Currency) => void
onSwitchTokens: () => void onSwitchTokens: () => void
onUserInput: (field: Field, typedValue: string) => void onUserInput: (field: Field, typedValue: string) => void
onChangeRecipient: (recipient: string | null) => void onChangeRecipient: (recipient: string | null) => void
} { } {
const dispatch = useAppDispatch()
const onCurrencySelection = useCallback( const onCurrencySelection = useCallback(
(field: Field, currency: Currency) => { (field: Field, currency: Currency) => {
dispatch( dispatch(
...@@ -76,7 +71,7 @@ const BAD_RECIPIENT_ADDRESSES: { [address: string]: true } = { ...@@ -76,7 +71,7 @@ const BAD_RECIPIENT_ADDRESSES: { [address: string]: true } = {
} }
// from the current swap inputs, compute the best trade and return it. // from the current swap inputs, compute the best trade and return it.
export function useDerivedSwapInfo(): { export function useDerivedSwapInfo(state: SwapState): {
currencies: { [field in Field]?: Currency | null } currencies: { [field in Field]?: Currency | null }
currencyBalances: { [field in Field]?: CurrencyAmount<Currency> } currencyBalances: { [field in Field]?: CurrencyAmount<Currency> }
parsedAmount: CurrencyAmount<Currency> | undefined parsedAmount: CurrencyAmount<Currency> | undefined
...@@ -95,7 +90,7 @@ export function useDerivedSwapInfo(): { ...@@ -95,7 +90,7 @@ export function useDerivedSwapInfo(): {
[Field.INPUT]: { currencyId: inputCurrencyId }, [Field.INPUT]: { currencyId: inputCurrencyId },
[Field.OUTPUT]: { currencyId: outputCurrencyId }, [Field.OUTPUT]: { currencyId: outputCurrencyId },
recipient, recipient,
} = useSwapState() } = state
const inputCurrency = useCurrency(inputCurrencyId) const inputCurrency = useCurrency(inputCurrencyId)
const outputCurrency = useCurrency(outputCurrencyId) const outputCurrency = useCurrency(outputCurrencyId)
......
...@@ -17,7 +17,7 @@ export interface SwapState { ...@@ -17,7 +17,7 @@ export interface SwapState {
readonly recipient: string | null readonly recipient: string | null
} }
const initialState: SwapState = queryParametersToSwapState(parsedQueryString()) export const initialState: SwapState = queryParametersToSwapState(parsedQueryString())
export default createReducer<SwapState>(initialState, (builder) => export default createReducer<SwapState>(initialState, (builder) =>
builder builder
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment