Commit d265b120 authored by ian-jh's avatar ian-jh

Merge remote-tracking branch 'upstream/beta' into beta

parents 870b3f7e 30887ef1
...@@ -80,5 +80,6 @@ ...@@ -80,5 +80,6 @@
"symbol": "Symbol", "symbol": "Symbol",
"decimals": "Decimals", "decimals": "Decimals",
"enterTokenCont": "Enter a token address to continue", "enterTokenCont": "Enter a token address to continue",
"priceChange": "This trade will cause the price to change by" "priceChange": "Expected price slippage",
"forAtLeast" : "for at least "
} }
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="9" cy="9" r="9" fill="#E1E1E1"/>
<path d="M8.06493 10.8317H9.15706V10.7592C9.17233 9.88089 9.42436 9.48757 10.0735 9.08662C10.7571 8.67421 11.1771 8.09378 11.1771 7.23459C11.1771 5.99354 10.2377 5.15344 8.83629 5.15344C7.54942 5.15344 6.51839 5.90571 6.46875 7.28041H7.62961C7.67543 6.47086 8.25204 6.11573 8.83629 6.11573C9.48546 6.11573 10.0124 6.54724 10.0124 7.22313C10.0124 7.79211 9.65729 8.19306 9.20288 8.47564C8.49262 8.91096 8.07257 9.34246 8.06493 10.7592V10.8317ZM8.64154 13.1534C9.05777 13.1534 9.40527 12.8136 9.40527 12.3897C9.40527 11.9735 9.05777 11.6298 8.64154 11.6298C8.22149 11.6298 7.87782 11.9735 7.87782 12.3897C7.87782 12.8136 8.22149 13.1534 8.64154 13.1534Z" fill="#737373"/>
</svg>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="8" fill="#E1E1E1"/>
<path d="M7.09618 9.67828H8.18831V9.60573C8.20358 8.72745 8.45561 8.33413 9.10477 7.93317C9.78831 7.52076 10.2084 6.94033 10.2084 6.08115C10.2084 4.8401 9.26897 4 7.86754 4C6.58067 4 5.54964 4.75227 5.5 6.12697H6.66086C6.70668 5.31742 7.28329 4.96229 7.86754 4.96229C8.51671 4.96229 9.04368 5.39379 9.04368 6.06969C9.04368 6.63866 8.68854 7.03962 8.23413 7.3222C7.52387 7.75752 7.10382 8.18902 7.09618 9.60573V9.67828ZM7.67279 12C8.08902 12 8.43652 11.6601 8.43652 11.2363C8.43652 10.82 8.08902 10.4764 7.67279 10.4764C7.25274 10.4764 6.90907 10.82 6.90907 11.2363C6.90907 11.6601 7.25274 12 7.67279 12Z" fill="#737373"/>
</svg>
...@@ -21,7 +21,7 @@ const ContainerRow = styled.div` ...@@ -21,7 +21,7 @@ const ContainerRow = styled.div`
justify-content: center; justify-content: center;
align-items: center; align-items: center;
border-radius: 1.25rem; border-radius: 1.25rem;
box-shadow: 0 0 0 0.5px ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)}; box-shadow: 0 0 0 1px ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)};
background-color: ${({ theme }) => theme.white}; background-color: ${({ theme }) => theme.white};
transition: box-shadow 200ms ease-in-out; transition: box-shadow 200ms ease-in-out;
` `
......
...@@ -32,10 +32,10 @@ const SummaryWrapperContainer = styled.div` ...@@ -32,10 +32,10 @@ const SummaryWrapperContainer = styled.div`
const Details = styled.div` const Details = styled.div`
background-color: ${({ theme }) => theme.concreteGray}; background-color: ${({ theme }) => theme.concreteGray};
padding: 1.5rem; /* padding: 1.25rem 1.25rem 1rem 1.25rem; */
border-radius: 1rem; border-radius: 1rem;
font-size: 0.75rem; font-size: 0.75rem;
margin-top: 1rem; margin: 1rem 0.5rem 0 0.5rem;
` `
const ErrorSpan = styled.span` const ErrorSpan = styled.span`
...@@ -89,13 +89,12 @@ export default function ContextualInfo({ ...@@ -89,13 +89,12 @@ export default function ContextualInfo({
closeDetailsText = 'Hide Details', closeDetailsText = 'Hide Details',
contextualInfo = '', contextualInfo = '',
allowExpand = false, allowExpand = false,
renderTransactionDetails = () => {},
isError = false, isError = false,
slippageWarning, slippageWarning,
highSlippageWarning highSlippageWarning,
dropDownContent
}) { }) {
const [showDetails, setShowDetails] = useState(false) const [showDetails, setShowDetails] = useState(false)
return !allowExpand ? ( return !allowExpand ? (
<SummaryWrapper>{contextualInfo}</SummaryWrapper> <SummaryWrapper>{contextualInfo}</SummaryWrapper>
) : ( ) : (
...@@ -117,7 +116,7 @@ export default function ContextualInfo({ ...@@ -117,7 +116,7 @@ export default function ContextualInfo({
)} )}
</> </>
</SummaryWrapperContainer> </SummaryWrapperContainer>
{showDetails && <Details>{renderTransactionDetails()}</Details>} {showDetails && <Details>{dropDownContent()}</Details>}
</> </>
) )
} }
...@@ -70,7 +70,7 @@ const CurrencySelect = styled.button` ...@@ -70,7 +70,7 @@ const CurrencySelect = styled.button`
} }
:focus { :focus {
box-shadow: 0 0 0.5px 0.5px ${({ theme }) => theme.malibuBlue}; box-shadow: 0 0 1px 1px ${({ theme }) => theme.malibuBlue};
} }
:active { :active {
...@@ -104,12 +104,12 @@ const InputPanel = styled.div` ...@@ -104,12 +104,12 @@ const InputPanel = styled.div`
const Container = styled.div` const Container = styled.div`
border-radius: 1.25rem; border-radius: 1.25rem;
box-shadow: 0 0 0 0.5px ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)}; box-shadow: 0 0 0 1px ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)};
background-color: ${({ theme }) => theme.white}; background-color: ${({ theme }) => theme.white};
transition: box-shadow 200ms ease-in-out; transition: box-shadow 200ms ease-in-out;
:focus-within { :focus-within {
box-shadow: 0 0 0.5px 0.5px ${({ theme }) => theme.malibuBlue}; box-shadow: 0 0 1px 1px ${({ theme }) => theme.malibuBlue};
} }
` `
......
...@@ -5,7 +5,8 @@ import { DialogOverlay, DialogContent } from '@reach/dialog' ...@@ -5,7 +5,8 @@ import { DialogOverlay, DialogContent } from '@reach/dialog'
import '@reach/dialog/styles.css' import '@reach/dialog/styles.css'
const AnimatedDialogOverlay = animated(DialogOverlay) const AnimatedDialogOverlay = animated(DialogOverlay)
const StyledDialogOverlay = styled(AnimatedDialogOverlay).attrs({ const WrappedDialogOverlay = ({ suppressClassNameWarning, ...rest }) => <AnimatedDialogOverlay {...rest} />
const StyledDialogOverlay = styled(WrappedDialogOverlay).attrs({
suppressClassNameWarning: true suppressClassNameWarning: true
})` })`
&[data-reach-dialog-overlay] { &[data-reach-dialog-overlay] {
......
...@@ -5,7 +5,7 @@ import styled from 'styled-components' ...@@ -5,7 +5,7 @@ import styled from 'styled-components'
import { transparentize, darken } from 'polished' import { transparentize, darken } from 'polished'
import { useBodyKeyDown } from '../../hooks' import { useBodyKeyDown } from '../../hooks'
import { useBetaMessageManager } from '../../contexts/Application' import { useBetaMessageManager } from '../../contexts/LocalStorage'
const tabOrder = [ const tabOrder = [
{ {
...@@ -84,11 +84,11 @@ const StyledNavLink = styled(NavLink).attrs({ ...@@ -84,11 +84,11 @@ const StyledNavLink = styled(NavLink).attrs({
&.${activeClassName} { &.${activeClassName} {
background-color: ${({ theme }) => theme.white}; background-color: ${({ theme }) => theme.white};
border-radius: 3rem; border-radius: 3rem;
box-shadow: 0 0 0.5px 1px ${({ theme }) => theme.mercuryGray}; box-shadow: 0 0 1px 1px ${({ theme }) => theme.mercuryGray};
font-weight: 500; font-weight: 500;
color: ${({ theme }) => theme.royalBlue}; color: ${({ theme }) => theme.royalBlue};
:hover { :hover {
box-shadow: 0 0 0.5px 1px ${({ theme }) => darken(0.1, theme.mercuryGray)}; box-shadow: 0 0 1px 1px ${({ theme }) => darken(0.1, theme.mercuryGray)};
} }
} }
......
This diff is collapsed.
...@@ -5,7 +5,7 @@ import { useWeb3Context, Connectors } from 'web3-react' ...@@ -5,7 +5,7 @@ import { useWeb3Context, Connectors } from 'web3-react'
import { darken, transparentize } from 'polished' import { darken, transparentize } from 'polished'
import Jazzicon from 'jazzicon' import Jazzicon from 'jazzicon'
import { ethers } from 'ethers' import { ethers } from 'ethers'
import { Activity, ArrowRight } from 'react-feather' import { Activity } from 'react-feather'
import { shortenAddress } from '../../utils' import { shortenAddress } from '../../utils'
import { useENSName } from '../../hooks' import { useENSName } from '../../hooks'
...@@ -91,13 +91,6 @@ const NetworkIcon = styled(Activity)` ...@@ -91,13 +91,6 @@ const NetworkIcon = styled(Activity)`
height: 16px; height: 16px;
` `
const ArrowIcon = styled(ArrowRight)`
margin-left: 0.25rem;
margin-right: 0.5rem;
width: 16px;
height: 16px;
`
const SpinnerWrapper = styled(Spinner)` const SpinnerWrapper = styled(Spinner)`
margin: 0 0.25rem 0 0.25rem; margin: 0 0.25rem 0 0.25rem;
` `
...@@ -251,7 +244,6 @@ export default function Web3Status() { ...@@ -251,7 +244,6 @@ export default function Web3Status() {
return ( return (
<Web3StatusConnect onClick={onClick}> <Web3StatusConnect onClick={onClick}>
<Text>{t('Connect')}</Text> <Text>{t('Connect')}</Text>
<ArrowIcon />
</Web3StatusConnect> </Web3StatusConnect>
) )
} else { } else {
......
...@@ -2,10 +2,8 @@ import React, { createContext, useContext, useReducer, useMemo, useCallback, use ...@@ -2,10 +2,8 @@ import React, { createContext, useContext, useReducer, useMemo, useCallback, use
import { useWeb3Context } from 'web3-react' import { useWeb3Context } from 'web3-react'
import { safeAccess } from '../utils' import { safeAccess } from '../utils'
const SHOW_BETA_MESSAGE = 'SHOW_BETA_MESSAGE'
const BLOCK_NUMBERS = 'BLOCK_NUMBERS' const BLOCK_NUMBERS = 'BLOCK_NUMBERS'
const DISMISS_BETA_MESSAGE = 'DISMISS_BETA_MESSAGE'
const UPDATE_BLOCK_NUMBER = 'UPDATE_BLOCK_NUMBER' const UPDATE_BLOCK_NUMBER = 'UPDATE_BLOCK_NUMBER'
const ApplicationContext = createContext() const ApplicationContext = createContext()
...@@ -16,12 +14,6 @@ function useApplicationContext() { ...@@ -16,12 +14,6 @@ function useApplicationContext() {
function reducer(state, { type, payload }) { function reducer(state, { type, payload }) {
switch (type) { switch (type) {
case DISMISS_BETA_MESSAGE: {
return {
...state,
[SHOW_BETA_MESSAGE]: false
}
}
case UPDATE_BLOCK_NUMBER: { case UPDATE_BLOCK_NUMBER: {
const { networkId, blockNumber } = payload const { networkId, blockNumber } = payload
return { return {
...@@ -40,25 +32,15 @@ function reducer(state, { type, payload }) { ...@@ -40,25 +32,15 @@ function reducer(state, { type, payload }) {
export default function Provider({ children }) { export default function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, { const [state, dispatch] = useReducer(reducer, {
[SHOW_BETA_MESSAGE]: true,
[BLOCK_NUMBERS]: {} [BLOCK_NUMBERS]: {}
}) })
const dismissBetaMessage = useCallback(() => {
dispatch({ type: DISMISS_BETA_MESSAGE })
}, [])
const updateBlockNumber = useCallback((networkId, blockNumber) => { const updateBlockNumber = useCallback((networkId, blockNumber) => {
dispatch({ type: UPDATE_BLOCK_NUMBER, payload: { networkId, blockNumber } }) dispatch({ type: UPDATE_BLOCK_NUMBER, payload: { networkId, blockNumber } })
}, []) }, [])
return ( return (
<ApplicationContext.Provider <ApplicationContext.Provider value={useMemo(() => [state, { updateBlockNumber }], [state, updateBlockNumber])}>
value={useMemo(() => [state, { dismissBetaMessage, updateBlockNumber }], [
state,
dismissBetaMessage,
updateBlockNumber
])}
>
{children} {children}
</ApplicationContext.Provider> </ApplicationContext.Provider>
) )
...@@ -101,12 +83,6 @@ export function Updater() { ...@@ -101,12 +83,6 @@ export function Updater() {
return null return null
} }
export function useBetaMessageManager() {
const [state, { dismissBetaMessage }] = useApplicationContext()
return [safeAccess(state, [SHOW_BETA_MESSAGE]), dismissBetaMessage]
}
export function useBlockNumber() { export function useBlockNumber() {
const { networkId } = useWeb3Context() const { networkId } = useWeb3Context()
......
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
const UNISWAP = 'UNISWAP'
const VERSION = 'VERSION'
const CURRENT_VERSION = 0
const LAST_SAVED = 'LAST_SAVED'
const BETA_MESSAGE_DISMISSED = 'BETA_MESSAGE_DISMISSED'
const UPDATABLE_KEYS = [BETA_MESSAGE_DISMISSED]
const UPDATE_KEY = 'UPDATE_KEY'
const LocalStorageContext = createContext()
function useLocalStorageContext() {
return useContext(LocalStorageContext)
}
function reducer(state, { type, payload }) {
switch (type) {
case UPDATE_KEY: {
const { key, value } = payload
if (!UPDATABLE_KEYS.some(k => k === key)) {
throw Error(`Unexpected key in LocalStorageContext reducer: '${key}'.`)
} else {
return {
...state,
[key]: value
}
}
}
default: {
throw Error(`Unexpected action type in LocalStorageContext reducer: '${type}'.`)
}
}
}
function init() {
const defaultLocalStorage = {
[VERSION]: CURRENT_VERSION,
[BETA_MESSAGE_DISMISSED]: false
}
try {
const parsed = JSON.parse(window.localStorage.getItem(UNISWAP))
if (parsed[VERSION] !== CURRENT_VERSION) {
// this is where we could run migration logic
return defaultLocalStorage
} else {
return parsed
}
} catch {
return defaultLocalStorage
}
}
export default function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, undefined, init)
const updateKey = useCallback((key, value) => {
dispatch({ type: UPDATE_KEY, payload: { key, value } })
}, [])
return (
<LocalStorageContext.Provider value={useMemo(() => [state, { updateKey }], [state, updateKey])}>
{children}
</LocalStorageContext.Provider>
)
}
export function Updater() {
const [state] = useLocalStorageContext()
useEffect(() => {
window.localStorage.setItem(UNISWAP, JSON.stringify({ ...state, [LAST_SAVED]: Math.floor(Date.now() / 1000) }))
})
return null
}
export function useBetaMessageManager() {
const [state, { updateKey }] = useLocalStorageContext()
const dismissBetaMessage = useCallback(() => {
updateKey(BETA_MESSAGE_DISMISSED, true)
}, [updateKey])
return [!state[BETA_MESSAGE_DISMISSED], dismissBetaMessage]
}
...@@ -89,6 +89,14 @@ const INITIAL_TOKENS_CONTEXT = { ...@@ -89,6 +89,14 @@ const INITIAL_TOKENS_CONTEXT = {
[DECIMALS]: 9, [DECIMALS]: 9,
[EXCHANGE_ADDRESS]: '0xb92dE8B30584392Af27726D5ce04Ef3c4e5c9924' [EXCHANGE_ADDRESS]: '0xb92dE8B30584392Af27726D5ce04Ef3c4e5c9924'
}, },
'0xc719d010B63E5bbF2C0551872CD5316ED26AcD83': {
[NAME]: 'Decentralized Insurance Protocol',
[SYMBOL]: 'DIP',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x61792F290e5100FBBcBb2309F03A1Bab869fb850'
},
'0x4946Fcea7C692606e8908002e55A582af44AC121': { '0x4946Fcea7C692606e8908002e55A582af44AC121': {
[NAME]: 'FOAM Token', [NAME]: 'FOAM Token',
[SYMBOL]: 'FOAM', [SYMBOL]: 'FOAM',
...@@ -191,6 +199,12 @@ const INITIAL_TOKENS_CONTEXT = { ...@@ -191,6 +199,12 @@ const INITIAL_TOKENS_CONTEXT = {
[DECIMALS]: 18, [DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0x2C4Bd064b998838076fa341A83d007FC2FA50957' [EXCHANGE_ADDRESS]: '0x2C4Bd064b998838076fa341A83d007FC2FA50957'
}, },
'0xec67005c4E498Ec7f55E092bd1d35cbC47C91892': {
[NAME]: 'Melon Token',
[SYMBOL]: 'MLN',
[DECIMALS]: 18,
[EXCHANGE_ADDRESS]: '0xA931F4eB165AC307fD7431b5EC6eADde53E14b0C'
},
'0x957c30aB0426e0C93CD8241E2c60392d08c6aC8e': { '0x957c30aB0426e0C93CD8241E2c60392d08c6aC8e': {
[NAME]: 'Modum Token', [NAME]: 'Modum Token',
[SYMBOL]: 'MOD', [SYMBOL]: 'MOD',
......
...@@ -4,6 +4,7 @@ import ReactGA from 'react-ga' ...@@ -4,6 +4,7 @@ import ReactGA from 'react-ga'
import Web3Provider, { Connectors } from 'web3-react' import Web3Provider, { Connectors } from 'web3-react'
import ThemeProvider, { GlobalStyle } from './theme' import ThemeProvider, { GlobalStyle } from './theme'
import LocalStorageContextProvider, { Updater as LocalStorageContextUpdater } from './contexts/LocalStorage'
import ApplicationContextProvider, { Updater as ApplicationContextUpdater } from './contexts/Application' import ApplicationContextProvider, { Updater as ApplicationContextUpdater } from './contexts/Application'
import TransactionContextProvider, { Updater as TransactionContextUpdater } from './contexts/Transactions' import TransactionContextProvider, { Updater as TransactionContextUpdater } from './contexts/Transactions'
import TokensContextProvider from './contexts/Tokens' import TokensContextProvider from './contexts/Tokens'
...@@ -29,21 +30,24 @@ const connectors = { Injected, Network } ...@@ -29,21 +30,24 @@ const connectors = { Injected, Network }
function ContextProviders({ children }) { function ContextProviders({ children }) {
return ( return (
<ApplicationContextProvider> <LocalStorageContextProvider>
<TransactionContextProvider> <ApplicationContextProvider>
<TokensContextProvider> <TransactionContextProvider>
<BalancesContextProvider> <TokensContextProvider>
<AllowancesContextProvider>{children}</AllowancesContextProvider> <BalancesContextProvider>
</BalancesContextProvider> <AllowancesContextProvider>{children}</AllowancesContextProvider>
</TokensContextProvider> </BalancesContextProvider>
</TransactionContextProvider> </TokensContextProvider>
</ApplicationContextProvider> </TransactionContextProvider>
</ApplicationContextProvider>
</LocalStorageContextProvider>
) )
} }
function Updaters() { function Updaters() {
return ( return (
<> <>
<LocalStorageContextUpdater />
<ApplicationContextUpdater /> <ApplicationContextUpdater />
<TransactionContextUpdater /> <TransactionContextUpdater />
</> </>
......
...@@ -362,6 +362,7 @@ export default function AddLiquidity() { ...@@ -362,6 +362,7 @@ export default function AddLiquidity() {
}) })
const deadline = Math.ceil(Date.now() / 1000) + DEADLINE_FROM_NOW const deadline = Math.ceil(Date.now() / 1000) + DEADLINE_FROM_NOW
const estimatedGasLimit = await exchangeContract.estimate.addLiquidity( const estimatedGasLimit = await exchangeContract.estimate.addLiquidity(
isNewExchange ? ethers.constants.Zero : liquidityTokensMin, isNewExchange ? ethers.constants.Zero : liquidityTokensMin,
isNewExchange ? outputValueParsed : outputValueMax, isNewExchange ? outputValueParsed : outputValueMax,
...@@ -371,6 +372,8 @@ export default function AddLiquidity() { ...@@ -371,6 +372,8 @@ export default function AddLiquidity() {
} }
) )
const gasLimit = calculateGasMargin(estimatedGasLimit, GAS_MARGIN)
exchangeContract exchangeContract
.addLiquidity( .addLiquidity(
isNewExchange ? ethers.constants.Zero : liquidityTokensMin, isNewExchange ? ethers.constants.Zero : liquidityTokensMin,
...@@ -378,7 +381,7 @@ export default function AddLiquidity() { ...@@ -378,7 +381,7 @@ export default function AddLiquidity() {
deadline, deadline,
{ {
value: inputValueParsed, value: inputValueParsed,
gasLimit: calculateGasMargin(estimatedGasLimit, GAS_MARGIN) gasLimit
} }
) )
.then(response => { .then(response => {
......
...@@ -64,7 +64,7 @@ const StyledNavLink = styled(NavLink).attrs({ ...@@ -64,7 +64,7 @@ const StyledNavLink = styled(NavLink).attrs({
&.${activeClassName} { &.${activeClassName} {
background-color: ${({ theme }) => theme.white}; background-color: ${({ theme }) => theme.white};
border-radius: 3rem; border-radius: 3rem;
box-shadow: 0 0 0.5px 0.5px ${({ theme }) => theme.mercuryGray}; box-shadow: 0 0 1px 1px ${({ theme }) => theme.mercuryGray};
font-weight: 500; font-weight: 500;
color: ${({ theme }) => theme.royalBlue}; color: ${({ theme }) => theme.royalBlue};
} }
......
...@@ -612,7 +612,7 @@ export default function Swap({ initialCurrency }) { ...@@ -612,7 +612,7 @@ export default function Swap({ initialCurrency }) {
isError={isError} isError={isError}
slippageWarning={slippageWarning && slippageWarningText} slippageWarning={slippageWarning && slippageWarningText}
highSlippageWarning={highSlippageWarning && slippageWarningText} highSlippageWarning={highSlippageWarning && slippageWarningText}
renderTransactionDetails={renderTransactionDetails} dropDownContent={renderTransactionDetails}
/> />
) )
} }
...@@ -760,13 +760,13 @@ export default function Swap({ initialCurrency }) { ...@@ -760,13 +760,13 @@ export default function Swap({ initialCurrency }) {
{inverted ? ( {inverted ? (
<span> <span>
{exchangeRate {exchangeRate
? `1 ${outputSymbol} = ${amountFormatter(exchangeRateInverted, 18, 4, false)} ${inputSymbol}` ? `1 ${inputSymbol} = ${amountFormatter(exchangeRate, 18, 4, false)} ${outputSymbol}`
: ' - '} : ' - '}
</span> </span>
) : ( ) : (
<span> <span>
{exchangeRate {exchangeRate
? `1 ${inputSymbol} = ${amountFormatter(exchangeRate, 18, 4, false)} ${outputSymbol}` ? `1 ${outputSymbol} = ${amountFormatter(exchangeRateInverted, 18, 4, false)} ${inputSymbol}`
: ' - '} : ' - '}
</span> </span>
)} )}
......
...@@ -7,8 +7,8 @@ import styled from 'styled-components' ...@@ -7,8 +7,8 @@ import styled from 'styled-components'
import { Button } from '../../theme' import { Button } from '../../theme'
import CurrencyInputPanel from '../../components/CurrencyInputPanel' import CurrencyInputPanel from '../../components/CurrencyInputPanel'
import NewContextualInfo from '../../components/ContextualInfoNew'
import OversizedPanel from '../../components/OversizedPanel' import OversizedPanel from '../../components/OversizedPanel'
import TransactionDetails from '../../components/TransactionDetails'
import ArrowDownBlue from '../../assets/images/arrow-down-blue.svg' import ArrowDownBlue from '../../assets/images/arrow-down-blue.svg'
import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg' import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg'
import { amountFormatter, calculateGasMargin } from '../../utils' import { amountFormatter, calculateGasMargin } from '../../utils'
...@@ -26,8 +26,8 @@ const TOKEN_TO_ETH = 1 ...@@ -26,8 +26,8 @@ const TOKEN_TO_ETH = 1
const TOKEN_TO_TOKEN = 2 const TOKEN_TO_TOKEN = 2
// denominated in bips // denominated in bips
const ALLOWED_SLIPPAGE = ethers.utils.bigNumberify(200) const ALLOWED_SLIPPAGE_DEFAULT = 100
const TOKEN_ALLOWED_SLIPPAGE = ethers.utils.bigNumberify(400) const TOKEN_ALLOWED_SLIPPAGE_DEFAULT = 100
// denominated in seconds // denominated in seconds
const DEADLINE_FROM_NOW = 60 * 15 const DEADLINE_FROM_NOW = 60 * 15
...@@ -35,14 +35,6 @@ const DEADLINE_FROM_NOW = 60 * 15 ...@@ -35,14 +35,6 @@ const DEADLINE_FROM_NOW = 60 * 15
// denominated in bips // denominated in bips
const GAS_MARGIN = ethers.utils.bigNumberify(1000) const GAS_MARGIN = ethers.utils.bigNumberify(1000)
const BlueSpan = styled.span`
color: ${({ theme }) => theme.royalBlue};
`
const LastSummaryText = styled.div`
margin-top: 1rem;
`
const DownArrowBackground = styled.div` const DownArrowBackground = styled.div`
${({ theme }) => theme.flexRowNoWrap} ${({ theme }) => theme.flexRowNoWrap}
justify-content: center; justify-content: center;
...@@ -81,9 +73,9 @@ const Flex = styled.div` ...@@ -81,9 +73,9 @@ const Flex = styled.div`
} }
` `
function calculateSlippageBounds(value, token = false) { function calculateSlippageBounds(value, token = false, tokenAllowedSlippage, allowedSlippage) {
if (value) { if (value) {
const offset = value.mul(token ? TOKEN_ALLOWED_SLIPPAGE : ALLOWED_SLIPPAGE).div(ethers.utils.bigNumberify(10000)) const offset = value.mul(token ? tokenAllowedSlippage : allowedSlippage).div(ethers.utils.bigNumberify(10000))
const minimum = value.sub(offset) const minimum = value.sub(offset)
const maximum = value.add(offset) const maximum = value.add(offset)
return { return {
...@@ -244,12 +236,18 @@ export default function Swap({ initialCurrency }) { ...@@ -244,12 +236,18 @@ export default function Swap({ initialCurrency }) {
const addTransaction = useTransactionAdder() const addTransaction = useTransactionAdder()
const [rawSlippage, setRawSlippage] = useState(ALLOWED_SLIPPAGE_DEFAULT)
const [rawTokenSlippage, setRawTokenSlippage] = useState(TOKEN_ALLOWED_SLIPPAGE_DEFAULT)
let allowedSlippageBig = ethers.utils.bigNumberify(rawSlippage)
let tokenAllowedSlippageBig = ethers.utils.bigNumberify(rawTokenSlippage)
// analytics // analytics
useEffect(() => { useEffect(() => {
ReactGA.pageview(window.location.pathname + window.location.search) ReactGA.pageview(window.location.pathname + window.location.search)
}, []) }, [])
// core swap state // core swap state-
const [swapState, dispatchSwapState] = useReducer(swapStateReducer, initialCurrency, getInitialSwapState) const [swapState, dispatchSwapState] = useReducer(swapStateReducer, initialCurrency, getInitialSwapState)
const { independentValue, dependentValue, independentField, inputCurrency, outputCurrency } = swapState const { independentValue, dependentValue, independentField, inputCurrency, outputCurrency } = swapState
...@@ -326,7 +324,9 @@ export default function Swap({ initialCurrency }) { ...@@ -326,7 +324,9 @@ export default function Swap({ initialCurrency }) {
// calculate slippage from target rate // calculate slippage from target rate
const { minimum: dependentValueMinumum, maximum: dependentValueMaximum } = calculateSlippageBounds( const { minimum: dependentValueMinumum, maximum: dependentValueMaximum } = calculateSlippageBounds(
dependentValue, dependentValue,
swapType === TOKEN_TO_TOKEN swapType === TOKEN_TO_TOKEN,
tokenAllowedSlippageBig,
allowedSlippageBig
) )
// validate input allowance + balance // validate input allowance + balance
...@@ -496,118 +496,6 @@ export default function Swap({ initialCurrency }) { ...@@ -496,118 +496,6 @@ export default function Swap({ initialCurrency }) {
return `Balance: ${value}` return `Balance: ${value}`
} }
function renderTransactionDetails() {
ReactGA.event({
category: 'TransactionDetail',
action: 'Open'
})
const b = text => <BlueSpan>{text}</BlueSpan>
if (independentField === INPUT) {
return (
<div>
<div>
{t('youAreSelling')}{' '}
{b(
`${amountFormatter(
independentValueParsed,
independentDecimals,
Math.min(4, independentDecimals)
)} ${inputSymbol}`
)}
.
</div>
<LastSummaryText>
{t('youWillReceive')}{' '}
{b(
`${amountFormatter(
dependentValueMinumum,
dependentDecimals,
Math.min(4, dependentDecimals)
)} ${outputSymbol}`
)}{' '}
{t('orTransFail')}
</LastSummaryText>
<LastSummaryText>
{(slippageWarning || highSlippageWarning) && (
<span role="img" aria-label="warning">
⚠️
</span>
)}
{t('priceChange')} {b(`${percentSlippageFormatted}%`)}.
</LastSummaryText>
</div>
)
} else {
return (
<div>
<div>
{t('youAreBuying')}{' '}
{b(
`${amountFormatter(
independentValueParsed,
independentDecimals,
Math.min(4, independentDecimals)
)} ${outputSymbol}`
)}
.
</div>
<LastSummaryText>
{t('itWillCost')}{' '}
{b(
`${amountFormatter(
dependentValueMaximum,
dependentDecimals,
Math.min(4, dependentDecimals)
)} ${inputSymbol}`
)}{' '}
{t('orTransFail')}
</LastSummaryText>
<LastSummaryText>
{t('priceChange')} {b(`${percentSlippageFormatted}%`)}.
</LastSummaryText>
</div>
)
}
}
function renderSummary() {
let contextualInfo = ''
let isError = false
if (inputError || independentError) {
contextualInfo = inputError || independentError
isError = true
} else if (!inputCurrency || !outputCurrency) {
contextualInfo = t('selectTokenCont')
} else if (!independentValue) {
contextualInfo = t('enterValueCont')
} else if (!account) {
contextualInfo = t('noWallet')
isError = true
}
const slippageWarningText = highSlippageWarning
? t('highSlippageWarning')
: slippageWarning
? t('slippageWarning')
: ''
return (
<NewContextualInfo
openDetailsText={t('transactionDetails')}
closeDetailsText={t('hideDetails')}
contextualInfo={contextualInfo ? contextualInfo : slippageWarningText}
allowExpand={!!(inputCurrency && outputCurrency && inputValueParsed && outputValueParsed)}
isError={isError}
slippageWarning={slippageWarning && !contextualInfo}
highSlippageWarning={highSlippageWarning && !contextualInfo}
renderTransactionDetails={renderTransactionDetails}
/>
)
}
async function onSwap() { async function onSwap() {
const deadline = Math.ceil(Date.now() / 1000) + DEADLINE_FROM_NOW const deadline = Math.ceil(Date.now() / 1000) + DEADLINE_FROM_NOW
...@@ -664,6 +552,8 @@ export default function Swap({ initialCurrency }) { ...@@ -664,6 +552,8 @@ export default function Swap({ initialCurrency }) {
}) })
} }
const [customSlippageError, setcustomSlippageError] = useState('')
return ( return (
<> <>
<CurrencyInputPanel <CurrencyInputPanel
...@@ -731,22 +621,51 @@ export default function Swap({ initialCurrency }) { ...@@ -731,22 +621,51 @@ export default function Swap({ initialCurrency }) {
{inverted ? ( {inverted ? (
<span> <span>
{exchangeRate {exchangeRate
? `1 ${outputSymbol} = ${amountFormatter(exchangeRateInverted, 18, 4, false)} ${inputSymbol}` ? `1 ${inputSymbol} = ${amountFormatter(exchangeRate, 18, 4, false)} ${outputSymbol}`
: ' - '} : ' - '}
</span> </span>
) : ( ) : (
<span> <span>
{exchangeRate {exchangeRate
? `1 ${inputSymbol} = ${amountFormatter(exchangeRate, 18, 4, false)} ${outputSymbol}` ? `1 ${outputSymbol} = ${amountFormatter(exchangeRateInverted, 18, 4, false)} ${inputSymbol}`
: ' - '} : ' - '}
</span> </span>
)} )}
</ExchangeRateWrapper> </ExchangeRateWrapper>
</OversizedPanel> </OversizedPanel>
{renderSummary()} <TransactionDetails
account={account}
setRawSlippage={setRawSlippage}
setRawTokenSlippage={setRawTokenSlippage}
rawSlippage={rawSlippage}
slippageWarning={slippageWarning}
highSlippageWarning={highSlippageWarning}
inputError={inputError}
independentError={independentError}
inputCurrency={inputCurrency}
outputCurrency={outputCurrency}
independentValue={independentValue}
independentValueParsed={independentValueParsed}
independentField={independentField}
INPUT={INPUT}
inputValueParsed={inputValueParsed}
outputValueParsed={outputValueParsed}
inputSymbol={inputSymbol}
outputSymbol={outputSymbol}
dependentValueMinumum={dependentValueMinumum}
dependentValueMaximum={dependentValueMaximum}
dependentDecimals={dependentDecimals}
independentDecimals={independentDecimals}
percentSlippageFormatted={percentSlippageFormatted}
setcustomSlippageError={setcustomSlippageError}
/>
<Flex> <Flex>
<Button disabled={!isValid} onClick={onSwap} warning={highSlippageWarning}> <Button
{highSlippageWarning ? t('swapAnyway') : t('swap')} disabled={!isValid || customSlippageError === 'invalid'}
onClick={onSwap}
warning={highSlippageWarning || customSlippageError === 'warning'}
>
{highSlippageWarning || customSlippageError === 'warning' ? t('swapAnyway') : t('swap')}
</Button> </Button>
</Flex> </Flex>
</> </>
......
...@@ -38,6 +38,9 @@ const theme = { ...@@ -38,6 +38,9 @@ const theme = {
chaliceGray: '#AEAEAE', chaliceGray: '#AEAEAE',
doveGray: '#737373', doveGray: '#737373',
mineshaftGray: '#2B2B2B', mineshaftGray: '#2B2B2B',
buttonOutlineGrey: '#f2f2f2',
//blacks
charcoalBlack: '#404040',
// blues // blues
zumthorBlue: '#EBF4FF', zumthorBlue: '#EBF4FF',
malibuBlue: '#5CA2FF', malibuBlue: '#5CA2FF',
...@@ -53,6 +56,7 @@ const theme = { ...@@ -53,6 +56,7 @@ const theme = {
// pink // pink
uniswapPink: '#DC6BE5', uniswapPink: '#DC6BE5',
connectedGreen: '#27AE60', connectedGreen: '#27AE60',
// media queries // media queries
mediaWidth: mediaWidthTemplates, mediaWidth: mediaWidthTemplates,
// css snippets // css snippets
......
This diff is collapsed.
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