Commit 8de6bb6d authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

perf(swap): initialize swap inputs from url (#2402)

* fix(swap): use undefined as initial currencyId state

Null should be used for a selection state, not an unknown state. undefined may signify that a currency was passed in the URL but not yet parsed.

* perf(swap): initialize swap with url

Initializes SwapState with URL parameters so that currency input may be rendered on the first frame.

* test(swap): update hooks tests

* test: fix casing

* fix: check nullish to allow eg 0
parent 322c45be
...@@ -221,7 +221,7 @@ export default function CurrencyInputPanel({ ...@@ -221,7 +221,7 @@ export default function CurrencyInputPanel({
<Container hideInput={hideInput}> <Container hideInput={hideInput}>
<InputRow style={hideInput ? { padding: '0', borderRadius: '8px' } : {}} selected={!onCurrencySelect}> <InputRow style={hideInput ? { padding: '0', borderRadius: '8px' } : {}} selected={!onCurrencySelect}>
<CurrencySelect <CurrencySelect
visible={currency !== null} visible={currency !== undefined}
selected={!!currency} selected={!!currency}
hideInput={hideInput} hideInput={hideInput}
className="open-currency-select-button" className="open-currency-select-button"
......
import { parseBytes32String } from '@ethersproject/strings' import { parseBytes32String } from '@ethersproject/strings'
import { Currency, Token } from '@uniswap/sdk-core' import { Currency, Token } from '@uniswap/sdk-core'
import { SupportedChainId } from 'constants/chains'
import { arrayify } from 'ethers/lib/utils' import { arrayify } from 'ethers/lib/utils'
import { useMemo } from 'react' import { useMemo } from 'react'
...@@ -181,8 +182,16 @@ export function useCurrency(currencyId: string | null | undefined): Currency | n ...@@ -181,8 +182,16 @@ export function useCurrency(currencyId: string | null | undefined): Currency | n
const { chainId } = useActiveWeb3React() const { chainId } = useActiveWeb3React()
const isETH = currencyId?.toUpperCase() === 'ETH' const isETH = currencyId?.toUpperCase() === 'ETH'
const token = useToken(isETH ? undefined : currencyId) const token = useToken(isETH ? undefined : currencyId)
const extendedEther = useMemo(() => (chainId ? ExtendedEther.onChain(chainId) : undefined), [chainId]) const extendedEther = useMemo(
() =>
chainId
? ExtendedEther.onChain(chainId)
: // display mainnet when not connected
ExtendedEther.onChain(SupportedChainId.MAINNET),
[chainId]
)
const weth = chainId ? WETH9_EXTENDED[chainId] : undefined const weth = chainId ? WETH9_EXTENDED[chainId] : undefined
if (weth?.address?.toLowerCase() === currencyId?.toLowerCase()) return weth if (currencyId === null || currencyId === undefined) return currencyId
if (weth?.address?.toUpperCase() === currencyId?.toUpperCase()) return weth
return isETH ? extendedEther : token return isETH ? extendedEther : token
} }
...@@ -9,7 +9,7 @@ describe('hooks', () => { ...@@ -9,7 +9,7 @@ describe('hooks', () => {
expect( expect(
queryParametersToSwapState( queryParametersToSwapState(
parse( parse(
'?inputCurrency=ETH&outputCurrency=0x6b175474e89094c44da98b954eedeac495271d0f&exactAmount=20.5&exactField=outPUT', '?inputCurrency=ETH&outputCurrency=0x6b175474e89094c44da98b954eedeac495271d0f&exactAmount=20.5&exactField=output',
{ parseArrays: false, ignoreQueryPrefix: true } { parseArrays: false, ignoreQueryPrefix: true }
) )
) )
...@@ -27,7 +27,7 @@ describe('hooks', () => { ...@@ -27,7 +27,7 @@ describe('hooks', () => {
queryParametersToSwapState(parse('?outputCurrency=invalid', { parseArrays: false, ignoreQueryPrefix: true })) queryParametersToSwapState(parse('?outputCurrency=invalid', { parseArrays: false, ignoreQueryPrefix: true }))
).toEqual({ ).toEqual({
[Field.INPUT]: { currencyId: 'ETH' }, [Field.INPUT]: { currencyId: 'ETH' },
[Field.OUTPUT]: { currencyId: '' }, [Field.OUTPUT]: { currencyId: null },
typedValue: '', typedValue: '',
independentField: Field.INPUT, independentField: Field.INPUT,
recipient: null, recipient: null,
...@@ -41,7 +41,7 @@ describe('hooks', () => { ...@@ -41,7 +41,7 @@ describe('hooks', () => {
) )
).toEqual({ ).toEqual({
[Field.OUTPUT]: { currencyId: 'ETH' }, [Field.OUTPUT]: { currencyId: 'ETH' },
[Field.INPUT]: { currencyId: '' }, [Field.INPUT]: { currencyId: null },
typedValue: '20.5', typedValue: '20.5',
independentField: Field.INPUT, independentField: Field.INPUT,
recipient: null, recipient: null,
...@@ -55,7 +55,7 @@ describe('hooks', () => { ...@@ -55,7 +55,7 @@ describe('hooks', () => {
) )
).toEqual({ ).toEqual({
[Field.OUTPUT]: { currencyId: 'ETH' }, [Field.OUTPUT]: { currencyId: 'ETH' },
[Field.INPUT]: { currencyId: '' }, [Field.INPUT]: { currencyId: null },
typedValue: '20.5', typedValue: '20.5',
independentField: Field.INPUT, independentField: Field.INPUT,
recipient: null, recipient: null,
...@@ -72,7 +72,7 @@ describe('hooks', () => { ...@@ -72,7 +72,7 @@ describe('hooks', () => {
) )
).toEqual({ ).toEqual({
[Field.OUTPUT]: { currencyId: 'ETH' }, [Field.OUTPUT]: { currencyId: 'ETH' },
[Field.INPUT]: { currencyId: '' }, [Field.INPUT]: { currencyId: null },
typedValue: '20.5', typedValue: '20.5',
independentField: Field.INPUT, independentField: Field.INPUT,
recipient: '0x0fF2D1eFd7A57B7562b2bf27F3f37899dB27F4a5', recipient: '0x0fF2D1eFd7A57B7562b2bf27F3f37899dB27F4a5',
...@@ -88,7 +88,7 @@ describe('hooks', () => { ...@@ -88,7 +88,7 @@ describe('hooks', () => {
) )
).toEqual({ ).toEqual({
[Field.OUTPUT]: { currencyId: 'ETH' }, [Field.OUTPUT]: { currencyId: 'ETH' },
[Field.INPUT]: { currencyId: '' }, [Field.INPUT]: { currencyId: null },
typedValue: '20.5', typedValue: '20.5',
independentField: Field.INPUT, independentField: Field.INPUT,
recipient: 'bob.argent.xyz', recipient: 'bob.argent.xyz',
......
...@@ -281,10 +281,10 @@ export function queryParametersToSwapState(parsedQs: ParsedQs): SwapState { ...@@ -281,10 +281,10 @@ export function queryParametersToSwapState(parsedQs: ParsedQs): SwapState {
return { return {
[Field.INPUT]: { [Field.INPUT]: {
currencyId: inputCurrency, currencyId: inputCurrency === '' ? null : inputCurrency ?? null,
}, },
[Field.OUTPUT]: { [Field.OUTPUT]: {
currencyId: outputCurrency, currencyId: outputCurrency === '' ? null : outputCurrency ?? null,
}, },
typedValue: parseTokenAmountURLParameter(parsedQs.exactAmount), typedValue: parseTokenAmountURLParameter(parsedQs.exactAmount),
independentField: parseIndependentFieldURLParameter(parsedQs.exactField), independentField: parseIndependentFieldURLParameter(parsedQs.exactField),
......
import { createReducer } from '@reduxjs/toolkit' import { createReducer } from '@reduxjs/toolkit'
import { parsedQueryString } from 'hooks/useParsedQueryString'
import { Field, replaceSwapState, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions' import { Field, replaceSwapState, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions'
import { queryParametersToSwapState } from './hooks'
export interface SwapState { export interface SwapState {
readonly independentField: Field readonly independentField: Field
...@@ -15,17 +17,7 @@ export interface SwapState { ...@@ -15,17 +17,7 @@ export interface SwapState {
readonly recipient: string | null readonly recipient: string | null
} }
const initialState: SwapState = { const initialState: SwapState = queryParametersToSwapState(parsedQueryString())
independentField: Field.INPUT,
typedValue: '',
[Field.INPUT]: {
currencyId: null,
},
[Field.OUTPUT]: {
currencyId: null,
},
recipient: null,
}
export default createReducer<SwapState>(initialState, (builder) => export default createReducer<SwapState>(initialState, (builder) =>
builder builder
...@@ -34,10 +26,10 @@ export default createReducer<SwapState>(initialState, (builder) => ...@@ -34,10 +26,10 @@ export default createReducer<SwapState>(initialState, (builder) =>
(state, { payload: { typedValue, recipient, field, inputCurrencyId, outputCurrencyId } }) => { (state, { payload: { typedValue, recipient, field, inputCurrencyId, outputCurrencyId } }) => {
return { return {
[Field.INPUT]: { [Field.INPUT]: {
currencyId: inputCurrencyId, currencyId: inputCurrencyId ?? null,
}, },
[Field.OUTPUT]: { [Field.OUTPUT]: {
currencyId: outputCurrencyId, currencyId: outputCurrencyId ?? null,
}, },
independentField: field, independentField: field,
typedValue, typedValue,
......
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