Add Custom url parameters (#423)

* query params for input and output currencies

* add slippage option

* add slippage cusytom param

* updated for sender address

* add field and amount support

* update params for pool page

* finish basic url support

* update app format

* update error checking to top level

* update for all pages

* fix build

* param updates

* fix slippage to basis points, update theme text, refactor to minimize lookups

* fix code styles

* update theme logic, remove extra setting, update rounding

* remove eslint comment errors

* remove logs, ignore lock

* remove lock
This commit is contained in:
Ian Lapham 2019-09-17 18:47:32 -04:00 committed by Noah Zinsmeister
parent 61d6556a0d
commit 4f566ab0c2
18 changed files with 302 additions and 104 deletions

4
.gitignore vendored

@ -26,4 +26,6 @@ yarn-error.log*
notes.txt
.idea/
.vscode/
.vscode/
package-lock.json

@ -10,6 +10,7 @@
"@uniswap/sdk": "^1.0.0-beta.4",
"copy-to-clipboard": "^3.2.0",
"escape-string-regexp": "^2.0.0",
"history": "^4.9.0",
"ethers": "^4.0.36",
"i18next": "^15.0.9",
"i18next-browser-languagedetector": "^3.0.1",

@ -75,7 +75,8 @@ export default function AddressInputPanel({ title, initialInput = '', onChange =
const { library } = useWeb3Context()
const [input, setInput] = useState(initialInput)
const [input, setInput] = useState(initialInput.address ? initialInput.address : '')
const debouncedInput = useDebounce(input, 150)
const [data, setData] = useState({ address: undefined, name: undefined })

@ -336,9 +336,9 @@ export default function CurrencyInputPanel({
<Input
type="number"
min="0"
step="0.000000000000000001"
error={!!errorMessage}
placeholder="0.0"
step="0.000000000000000001"
onChange={e => onValueChange(e.target.value)}
onKeyPress={e => {
const charCode = e.which ? e.which : e.keyCode

@ -1,5 +1,6 @@
import React, { useState, useReducer, useEffect } from 'react'
import ReactGA from 'react-ga'
import { createBrowserHistory } from 'history'
import { useTranslation } from 'react-i18next'
import { useWeb3Context } from 'web3-react'
@ -119,13 +120,17 @@ function calculateEtherTokenInputFromOutput(outputAmount, inputReserve, outputRe
return numerator.div(denominator).add(ethers.constants.One)
}
function getInitialSwapState(outputCurrency) {
function getInitialSwapState(state) {
return {
independentValue: '', // this is a user input
independentValue: state.exactFieldURL && state.exactAmountURL ? state.exactAmountURL : '', // this is a user input
dependentValue: '', // this is a calculated number
independentField: INPUT,
inputCurrency: 'ETH',
outputCurrency: outputCurrency ? outputCurrency : ''
independentField: state.exactFieldURL === 'output' ? OUTPUT : INPUT,
inputCurrency: state.inputCurrencyURL ? state.inputCurrencyURL : 'ETH',
outputCurrency: state.outputCurrencyURL
? state.outputCurrencyURL
: state.initialCurrency
? state.initialCurrency
: ''
}
}
@ -235,14 +240,32 @@ function getMarketRate(
}
}
export default function ExchangePage({ initialCurrency, sending }) {
export default function ExchangePage({ initialCurrency, sending = false, params }) {
const { t } = useTranslation()
const { account } = useWeb3Context()
const addTransaction = useTransactionAdder()
const [rawSlippage, setRawSlippage] = useState(ALLOWED_SLIPPAGE_DEFAULT)
const [rawTokenSlippage, setRawTokenSlippage] = useState(TOKEN_ALLOWED_SLIPPAGE_DEFAULT)
// check if URL specifies valid slippage, if so use as default
const initialSlippage = (token = false) => {
let slippage = Number.parseInt(params.slippage)
if (!isNaN(slippage) && (slippage === 0 || slippage >= 1)) {
return slippage // round to match custom input availability
}
// check for token <-> token slippage option
return token ? TOKEN_ALLOWED_SLIPPAGE_DEFAULT : ALLOWED_SLIPPAGE_DEFAULT
}
// check URL params for recipient, only on send page
const initialRecipient = () => {
if (sending && params.recipient) {
return params.recipient
}
return ''
}
const [rawSlippage, setRawSlippage] = useState(() => initialSlippage())
const [rawTokenSlippage, setRawTokenSlippage] = useState(() => initialSlippage(true))
const allowedSlippageBig = ethers.utils.bigNumberify(rawSlippage)
const tokenAllowedSlippageBig = ethers.utils.bigNumberify(rawTokenSlippage)
@ -253,11 +276,21 @@ export default function ExchangePage({ initialCurrency, sending }) {
}, [])
// core swap state
const [swapState, dispatchSwapState] = useReducer(swapStateReducer, initialCurrency, getInitialSwapState)
const [swapState, dispatchSwapState] = useReducer(
swapStateReducer,
{
initialCurrency: initialCurrency,
inputCurrencyURL: params.inputCurrency,
outputCurrencyURL: params.outputCurrency,
exactFieldURL: params.exactField,
exactAmountURL: params.exactAmount
},
getInitialSwapState
)
const { independentValue, dependentValue, independentField, inputCurrency, outputCurrency } = swapState
const [recipient, setRecipient] = useState({ address: '', name: '' })
const [recipient, setRecipient] = useState({ address: initialRecipient(), name: '' })
const [recipientError, setRecipientError] = useState()
// get swap type from the currency types
@ -468,6 +501,11 @@ export default function ExchangePage({ initialCurrency, sending }) {
t
])
useEffect(() => {
const history = createBrowserHistory()
history.push(window.location.pathname + '')
}, [])
const [inverted, setInverted] = useState(false)
const exchangeRate = getExchangeRate(inputValueParsed, inputDecimals, outputValueParsed, outputDecimals)
const exchangeRateInverted = getExchangeRate(inputValueParsed, inputDecimals, outputValueParsed, outputDecimals, true)
@ -655,7 +693,7 @@ export default function ExchangePage({ initialCurrency, sending }) {
<DownArrow active={isValid} alt="arrow" />
</DownArrowBackground>
</OversizedPanel>
<AddressInputPanel onChange={setRecipient} onError={setRecipientError} />
<AddressInputPanel onChange={setRecipient} onError={setRecipientError} initialInput={recipient} />
</>
) : (
''

@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from 'react'
import React, { useState, useEffect, useRef, useCallback } from 'react'
import ReactGA from 'react-ga'
import { useTranslation } from 'react-i18next'
import styled, { css, keyframes } from 'styled-components'
@ -502,40 +502,94 @@ export default function TransactionDetails(props) {
checkBounds(debouncedInput)
}
// destructure props for to limit effect callbacks
const setRawSlippage = props.setRawSlippage
const setRawTokenSlippage = props.setRawTokenSlippage
const setcustomSlippageError = props.setcustomSlippageError
const updateSlippage = useCallback(
newSlippage => {
// round to 2 decimals to prevent ethers error
let numParsed = parseInt(newSlippage * 100)
// set both slippage values in parents
setRawSlippage(numParsed)
setRawTokenSlippage(numParsed)
},
[setRawSlippage, setRawTokenSlippage]
)
// used for slippage presets
const setFromFixed = (index, slippage) => {
// update slippage in parent, reset errors and input state
updateSlippage(slippage)
setWarningType(WARNING_TYPE.none)
setActiveIndex(index)
props.setcustomSlippageError('valid`')
}
const setFromFixed = useCallback(
(index, slippage) => {
// update slippage in parent, reset errors and input state
updateSlippage(slippage)
setWarningType(WARNING_TYPE.none)
setActiveIndex(index)
setcustomSlippageError('valid`')
},
[setcustomSlippageError, updateSlippage]
)
const checkBounds = slippageValue => {
setWarningType(WARNING_TYPE.none)
props.setcustomSlippageError('valid')
/**
* @todo
* Breaks without useState here, able to
* break input parsing if typing is faster than
* debounce time
*/
if (slippageValue === '' || slippageValue === '.') {
props.setcustomSlippageError('invalid')
return setWarningType(WARNING_TYPE.emptyInput)
}
const [initialSlippage] = useState(props.rawSlippage)
// check bounds and set errors
if (Number(slippageValue) < 0 || Number(slippageValue) > 50) {
props.setcustomSlippageError('invalid')
return setWarningType(WARNING_TYPE.invalidEntryBound)
useEffect(() => {
switch (Number.parseInt(initialSlippage)) {
case 10:
setFromFixed(1, 0.1)
break
case 50:
setFromFixed(2, 0.5)
break
case 100:
setFromFixed(3, 1)
break
default:
// restrict to 2 decimal places
let acceptableValues = [/^$/, /^\d{1,2}$/, /^\d{0,2}\.\d{0,2}$/]
// if its within accepted decimal limit, update the input state
if (acceptableValues.some(val => val.test(initialSlippage / 100))) {
setUserInput(initialSlippage / 100)
setActiveIndex(4)
}
}
if (Number(slippageValue) >= 0 && Number(slippageValue) < 0.1) {
props.setcustomSlippageError('valid')
setWarningType(WARNING_TYPE.riskyEntryLow)
}
if (Number(slippageValue) > 5) {
props.setcustomSlippageError('warning')
setWarningType(WARNING_TYPE.riskyEntryHigh)
}
//update the actual slippage value in parent
updateSlippage(Number(slippageValue))
}
}, [initialSlippage, setFromFixed])
const checkBounds = useCallback(
slippageValue => {
setWarningType(WARNING_TYPE.none)
setcustomSlippageError('valid')
if (slippageValue === '' || slippageValue === '.') {
setcustomSlippageError('invalid')
return setWarningType(WARNING_TYPE.emptyInput)
}
// check bounds and set errors
if (Number(slippageValue) < 0 || Number(slippageValue) > 50) {
setcustomSlippageError('invalid')
return setWarningType(WARNING_TYPE.invalidEntryBound)
}
if (Number(slippageValue) >= 0 && Number(slippageValue) < 0.1) {
setcustomSlippageError('valid')
setWarningType(WARNING_TYPE.riskyEntryLow)
}
if (Number(slippageValue) > 5) {
setcustomSlippageError('warning')
setWarningType(WARNING_TYPE.riskyEntryHigh)
}
//update the actual slippage value in parent
updateSlippage(Number(slippageValue))
},
[setcustomSlippageError, updateSlippage]
)
// check that the theyve entered number and correct decimal
const parseInput = e => {
@ -549,15 +603,6 @@ export default function TransactionDetails(props) {
}
}
const updateSlippage = newSlippage => {
// round to 2 decimals to prevent ethers error
let numParsed = parseInt(newSlippage * 100)
// set both slippage values in parents
props.setRawSlippage(numParsed)
props.setRawTokenSlippage(numParsed)
}
const b = text => <Bold>{text}</Bold>
const renderTransactionDetails = () => {

@ -4,3 +4,8 @@ export const FACTORY_ADDRESSES = {
4: '0xf5D915570BC477f9B8D6C0E980aA81757A3AaC36',
42: '0xD3E51Ef092B2845f10401a0159B2B96e8B6c3D30'
}
export const SUPPORTED_THEMES = {
DARK: 'DARK',
LIGHT: 'LIGHT'
}

@ -68,14 +68,12 @@ export function useFetchAllBalances() {
Object.keys(allTokens).map(async k => {
let balance = null
let ethRate = null
if (isAddress(k) || k === 'ETH') {
if (k === 'ETH') {
balance = await getEtherBalance(account, library).catch(() => null)
ethRate = ONE
} else {
balance = await getTokenBalance(k, account, library).catch(() => null)
// only get values for tokens with positive balances
if (!!balance && balance.gt(ZERO)) {
const tokenReserves = await getTokenReserves(k, library).catch(() => null)

@ -95,11 +95,14 @@ export function useBetaMessageManager() {
export function useDarkModeManager() {
const [state, { updateKey }] = useLocalStorageContext()
const isDarkMode = state[DARK_MODE]
let isDarkMode = state[DARK_MODE]
const toggleDarkMode = useCallback(() => {
updateKey(DARK_MODE, !isDarkMode)
}, [updateKey, isDarkMode])
const toggleDarkMode = useCallback(
value => {
updateKey(DARK_MODE, value === false || value === true ? value : !isDarkMode)
},
[updateKey, isDarkMode]
)
return [state[DARK_MODE], toggleDarkMode]
}

@ -7,7 +7,7 @@ import Header from '../components/Header'
import Footer from '../components/Footer'
import NavigationTabs from '../components/NavigationTabs'
import { isAddress } from '../utils'
import { isAddress, getAllQueryParams } from '../utils'
const Swap = lazy(() => import('./Swap'))
const Send = lazy(() => import('./Send'))
@ -48,6 +48,7 @@ const Body = styled.div`
`
export default function App() {
const params = getAllQueryParams()
return (
<>
<Suspense fallback={null}>
@ -63,27 +64,33 @@ export default function App() {
{/* this Suspense is for route code-splitting */}
<Suspense fallback={null}>
<Switch>
<Route exact strict path="/swap" component={Swap} />
<Route exact strict path="/swap" component={() => <Swap params={params} />} />
<Route
exact
strict
path="/swap/:tokenAddress?"
render={({ match }) => {
render={({ match, location }) => {
if (isAddress(match.params.tokenAddress)) {
return <Swap initialCurrency={isAddress(match.params.tokenAddress)} />
return (
<Swap
location={location}
initialCurrency={isAddress(match.params.tokenAddress)}
params={params}
/>
)
} else {
return <Redirect to={{ pathname: '/swap' }} />
}
}}
/>
<Route exact strict path="/send" component={Send} />
<Route exact strict path="/send" component={() => <Send params={params} />} />
<Route
exact
strict
path="/send/:tokenAddress?"
render={({ match }) => {
render={({ match, location }) => {
if (isAddress(match.params.tokenAddress)) {
return <Send initialCurrency={isAddress(match.params.tokenAddress)} />
return <Send initialCurrency={isAddress(match.params.tokenAddress)} params={params} />
} else {
return <Redirect to={{ pathname: '/send' }} />
}
@ -96,7 +103,7 @@ export default function App() {
'/create-exchange',
'/create-exchange/:tokenAddress?'
]}
component={Pool}
component={() => <Pool params={params} />}
/>
<Redirect to="/swap" />
</Switch>

@ -1,6 +1,7 @@
import React, { useReducer, useState, useCallback, useEffect, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { useWeb3Context } from 'web3-react'
import { createBrowserHistory } from 'history'
import { ethers } from 'ethers'
import ReactGA from 'react-ga'
import styled from 'styled-components'
@ -118,11 +119,13 @@ function calculateSlippageBounds(value) {
}
}
const initialAddLiquidityState = {
inputValue: '',
outputValue: '',
lastEditedField: INPUT,
outputCurrency: ''
function initialAddLiquidityState(state) {
return {
inputValue: state.ethAmountURL ? state.ethAmountURL : '',
outputValue: state.tokenAmountURL && !state.ethAmountURL ? state.tokenAmountURL : '',
lastEditedField: state.tokenAmountURL && state.ethAmountURL === '' ? OUTPUT : INPUT,
outputCurrency: state.tokenURL ? state.tokenURL : ''
}
}
function addLiquidityStateReducer(state, action) {
@ -153,7 +156,7 @@ function addLiquidityStateReducer(state, action) {
}
}
default: {
return initialAddLiquidityState
return initialAddLiquidityState()
}
}
}
@ -189,11 +192,21 @@ function getMarketRate(reserveETH, reserveToken, decimals, invert = false) {
return getExchangeRate(reserveETH, 18, reserveToken, decimals, invert)
}
export default function AddLiquidity() {
export default function AddLiquidity({ params }) {
const { t } = useTranslation()
const { library, active, account } = useWeb3Context()
const [addLiquidityState, dispatchAddLiquidityState] = useReducer(addLiquidityStateReducer, initialAddLiquidityState)
// clear url of query
useEffect(() => {
const history = createBrowserHistory()
history.push(window.location.pathname + '')
}, [])
const [addLiquidityState, dispatchAddLiquidityState] = useReducer(
addLiquidityStateReducer,
{ ethAmountURL: params.ethAmount, tokenAmountURL: params.tokenAmount, tokenURL: params.token },
initialAddLiquidityState
)
const { inputValue, outputValue, lastEditedField, outputCurrency } = addLiquidityState
const inputCurrency = 'ETH'

@ -1,11 +1,11 @@
import React, { useState, useEffect } from 'react'
import { withRouter } from 'react-router'
import { useWeb3Context } from 'web3-react'
import { createBrowserHistory } from 'history'
import { ethers } from 'ethers'
import styled from 'styled-components'
import { useTranslation } from 'react-i18next'
import ReactGA from 'react-ga'
import { Button } from '../../theme'
import AddressInputPanel from '../../components/AddressInputPanel'
import OversizedPanel from '../../components/OversizedPanel'
@ -54,13 +54,13 @@ const Flex = styled.div`
}
`
function CreateExchange({ history, location }) {
function CreateExchange({ location, params }) {
const { t } = useTranslation()
const { account } = useWeb3Context()
const factory = useFactoryContract()
const [tokenAddress, setTokenAddress] = useState({
address: '',
address: params.tokenAddress ? params.tokenAddress : '',
name: ''
})
const [tokenAddressError, setTokenAddressError] = useState()
@ -68,12 +68,11 @@ function CreateExchange({ history, location }) {
const { name, symbol, decimals, exchangeAddress } = useTokenDetails(tokenAddress.address)
const addTransaction = useTransactionAdder()
// clear location state, if it exists
// clear url of query
useEffect(() => {
if (location.state) {
history.replace(location.pathname)
}
}, []) // eslint-disable-line react-hooks/exhaustive-deps
const history = createBrowserHistory()
history.push(window.location.pathname + '')
}, [])
// validate everything
const [errorMessage, setErrorMessage] = useState(!account && t('noWallet'))
@ -118,7 +117,11 @@ function CreateExchange({ history, location }) {
<>
<AddressInputPanel
title={t('tokenAddress')}
initialInput={(location.state && location.state.tokenAddress) || ''}
initialInput={
params.tokenAddress
? { address: params.tokenAddress }
: { address: (location.state && location.state.tokenAddress) || '' }
}
onChange={setTokenAddress}
onError={setTokenAddressError}
/>

@ -1,6 +1,7 @@
import React, { useState, useEffect, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import ReactGA from 'react-ga'
import { createBrowserHistory } from 'history'
import { useWeb3Context } from 'web3-react'
import { ethers } from 'ethers'
import styled from 'styled-components'
@ -141,14 +142,20 @@ function calculateSlippageBounds(value) {
}
}
export default function RemoveLiquidity() {
export default function RemoveLiquidity({ params }) {
const { library, account, active } = useWeb3Context()
const { t } = useTranslation()
const addTransaction = useTransactionAdder()
const [outputCurrency, setOutputCurrency] = useState('')
const [value, setValue] = useState('')
// clear url of query
useEffect(() => {
const history = createBrowserHistory()
history.push(window.location.pathname + '')
}, [])
const [outputCurrency, setOutputCurrency] = useState(params.poolTokenAddress)
const [value, setValue] = useState(params.poolTokenAmount ? params.poolTokenAmount : '')
const [inputError, setInputError] = useState()
const [valueParsed, setValueParsed] = useState()
// parse value

@ -1,27 +1,32 @@
import React, { Suspense, lazy, useEffect } from 'react'
import ReactGA from 'react-ga'
import { Switch, Route, Redirect } from 'react-router-dom'
import ModeSelector from './ModeSelector'
const AddLiquidity = lazy(() => import('./AddLiquidity'))
const RemoveLiquidity = lazy(() => import('./RemoveLiquidity'))
const CreateExchange = lazy(() => import('./CreateExchange'))
export default function Pool() {
export default function Pool({ params }) {
useEffect(() => {
ReactGA.pageview(window.location.pathname + window.location.search)
}, [])
const AddLiquidityParams = () => <AddLiquidity params={params} />
const RemoveLiquidityParams = () => <RemoveLiquidity params={params} />
const CreateExchangeParams = () => <CreateExchange params={params} />
return (
<>
<ModeSelector />
{/* this Suspense is for route code-splitting */}
<Suspense fallback={null}>
<Switch>
<Route exact strict path="/add-liquidity" component={AddLiquidity} />
<Route exact strict path="/remove-liquidity" component={RemoveLiquidity} />
<Route exact strict path="/create-exchange" component={CreateExchange} />
<Route exact strict path="/add-liquidity" component={AddLiquidityParams} />
<Route exact strict path="/remove-liquidity" component={RemoveLiquidityParams} />
<Route exact strict path="/create-exchange" component={CreateExchangeParams} />
<Route
path="/create-exchange/:tokenAddress"
render={({ match }) => {

@ -1,6 +1,6 @@
import React from 'react'
import ExchangePage from '../../components/ExchangePage'
export default function Send({ initialCurrency }) {
return <ExchangePage initialCurrency={initialCurrency} sending={true} />
export default function Send({ initialCurrency, params }) {
return <ExchangePage initialCurrency={initialCurrency} params={params} sending={true} />
}

@ -1,6 +1,6 @@
import React from 'react'
import ExchangePage from '../../components/ExchangePage'
export default function Swap({ initialCurrency }) {
return <ExchangePage initialCurrency={initialCurrency} />
export default function Swap({ initialCurrency, params }) {
return <ExchangePage initialCurrency={initialCurrency} params={params} />
}

@ -1,5 +1,7 @@
import React from 'react'
import React, { useEffect } from 'react'
import { ThemeProvider as StyledComponentsThemeProvider, createGlobalStyle, css } from 'styled-components'
import { getQueryParam, checkSupportedTheme } from '../utils'
import { SUPPORTED_THEMES } from '../constants'
import { useDarkModeManager } from '../contexts/LocalStorage'
export * from './components'
@ -32,6 +34,22 @@ const flexRowNoWrap = css`
const white = '#FFFFFF'
const black = '#000000'
export default function ThemeProvider({ children }) {
const [darkMode, toggleDarkMode] = useDarkModeManager()
const themeURL = checkSupportedTheme(getQueryParam(window.location, 'theme'))
const themeToRender = themeURL
? themeURL.toUpperCase() === SUPPORTED_THEMES.DARK
? true
: themeURL.toUpperCase() === SUPPORTED_THEMES.LIGHT
? false
: darkMode
: darkMode
useEffect(() => {
toggleDarkMode(themeToRender)
}, [toggleDarkMode, themeToRender])
return <StyledComponentsThemeProvider theme={theme(themeToRender)}>{children}</StyledComponentsThemeProvider>
}
const theme = darkMode => ({
white,
black,
@ -84,12 +102,6 @@ const theme = darkMode => ({
flexRowNoWrap
})
export default function ThemeProvider({ children }) {
const [darkMode] = useDarkModeManager()
return <StyledComponentsThemeProvider theme={theme(darkMode)}>{children}</StyledComponentsThemeProvider>
}
export const GlobalStyle = createGlobalStyle`
@import url('https://rsms.me/inter/inter.css');
html { font-family: 'Inter', sans-serif; }

@ -4,7 +4,7 @@ import FACTORY_ABI from '../constants/abis/factory'
import EXCHANGE_ABI from '../constants/abis/exchange'
import ERC20_ABI from '../constants/abis/erc20'
import ERC20_BYTES32_ABI from '../constants/abis/erc20_bytes32'
import { FACTORY_ADDRESSES } from '../constants'
import { FACTORY_ADDRESSES, SUPPORTED_THEMES } from '../constants'
import { formatFixed } from '@uniswap/sdk'
import UncheckedJsonRpcSigner from './signer'
@ -33,6 +33,7 @@ const ETHERSCAN_PREFIXES = {
5: 'goerli.',
42: 'kovan.'
}
export function getEtherscanLink(networkId, data, type) {
const prefix = `https://${ETHERSCAN_PREFIXES[networkId] || ETHERSCAN_PREFIXES[1]}etherscan.io`
@ -47,6 +48,63 @@ export function getEtherscanLink(networkId, data, type) {
}
}
export function getQueryParam(windowLocation, name) {
var q = windowLocation.search.match(new RegExp('[?&]' + name + '=([^&#?]*)'))
return q && q[1]
}
export function getAllQueryParams() {
let params = {}
params.theme = checkSupportedTheme(getQueryParam(window.location, 'theme'))
params.inputCurrency = isAddress(getQueryParam(window.location, 'inputCurrency'))
? getQueryParam(window.location, 'inputCurrency')
: ''
params.outputCurrency = isAddress(getQueryParam(window.location, 'outputCurrency'))
? getQueryParam(window.location, 'outputCurrency')
: ''
params.slippage = !isNaN(getQueryParam(window.location, 'slippage')) ? getQueryParam(window.location, 'slippage') : ''
params.exactField = getQueryParam(window.location, 'exactField')
params.exactAmount = !isNaN(getQueryParam(window.location, 'exactAmount'))
? getQueryParam(window.location, 'exactAmount')
: ''
params.theme = checkSupportedTheme(getQueryParam(window.location, 'theme'))
params.recipient = isAddress(getQueryParam(window.location, 'recipient'))
? getQueryParam(window.location, 'recipient')
: ''
// Add Liquidity params
params.ethAmount = !isNaN(getQueryParam(window.location, 'ethAmount'))
? getQueryParam(window.location, 'ethAmount')
: ''
params.tokenAmount = !isNaN(getQueryParam(window.location, 'tokenAmount'))
? getQueryParam(window.location, 'tokenAmount')
: ''
params.token = isAddress(getQueryParam(window.location, 'token')) ? getQueryParam(window.location, 'token') : ''
// Remove liquidity params
params.poolTokenAmount = !isNaN(getQueryParam(window.location, 'poolTokenAmount'))
? getQueryParam(window.location, 'poolTokenAmount')
: ''
params.poolTokenAddress = isAddress(getQueryParam(window.location, 'poolTokenAddress'))
? getQueryParam(window.location, 'poolTokenAddress')
: ''
// Create Exchange params
params.tokenAddress = isAddress(getQueryParam(window.location, 'tokenAddress'))
? getQueryParam(window.location, 'tokenAddress')
: ''
return params
}
export function checkSupportedTheme(themeName) {
if (themeName && themeName.toUpperCase() in SUPPORTED_THEMES) {
return themeName.toUpperCase()
}
return null
}
export function getNetworkName(networkId) {
switch (networkId) {
case 1: {