Skip to content

Commit

Permalink
feat(v1-support): Enable executing swaps on v1 or v2 (#883)
Browse files Browse the repository at this point in the history
* swap-v1

* toggle the version switch based on the search query parameter

* rework some of the query parameter stuff in send/swap

* hide the url when they click it

* allow switching back to v2 via the toggle

* represent the v1 trade in the UI if they toggle it on

* show trade link in both directions (5% threshold for v1 link)

* input amounts should reflect v1/v2

* perform the approve on v1 exchange for v1 trades

* get swap on v1 working

* move some code around to reduce duplication

* fix ts error

* correct input allowance

* fix exact token to token on v1

* fix pending approvals to be specific to the spender

* google analytics for swap version

* disable the version switch on pages other than swap and send
  • Loading branch information
moodysalem authored Jun 11, 2020
1 parent 29db0a5 commit bafd3f3
Show file tree
Hide file tree
Showing 24 changed files with 656 additions and 383 deletions.
64 changes: 64 additions & 0 deletions src/components/Header/VersionSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { stringify } from 'qs'
import React, { useCallback, useMemo } from 'react'
import { Link, useLocation } from 'react-router-dom'
import styled from 'styled-components'
import useParsedQueryString from '../../hooks/useParsedQueryString'
import useToggledVersion, { Version } from '../../hooks/useToggledVersion'

const VersionLabel = styled.span<{ enabled: boolean }>`
padding: ${({ enabled }) => (enabled ? '0.15rem 0.5rem 0.16rem 0.45rem' : '0.15rem 0.5rem 0.16rem 0.35rem')};
border-radius: 14px;
background: ${({ theme, enabled }) => (enabled ? theme.primary1 : 'none')};
color: ${({ theme, enabled }) => (enabled ? theme.white : theme.primary1)};
font-size: 0.825rem;
font-weight: 400;
:hover {
user-select: ${({ enabled }) => (enabled ? 'none' : 'initial')};
background: ${({ theme, enabled }) => (enabled ? theme.primary1 : 'none')};
color: ${({ theme, enabled }) => (enabled ? theme.white : theme.primary3)};
}
`
const VersionToggle = styled(Link)<{ enabled: boolean }>`
border-radius: 16px;
opacity: ${({ enabled }) => (enabled ? 1 : 0.5)};
cursor: ${({ enabled }) => (enabled ? 'pointer' : 'default')};
background: ${({ theme }) => theme.primary5};
border: 1px solid ${({ theme }) => theme.primary4};
color: ${({ theme }) => theme.primary1};
display: flex;
width: fit-content;
text-decoration: none;
:hover {
text-decoration: none;
}
`

export function VersionSwitch() {
const version = useToggledVersion()
const location = useLocation()
const query = useParsedQueryString()
const versionSwitchAvailable = location.pathname === '/swap' || location.pathname === '/send'

const toggleDest = useMemo(() => {
return versionSwitchAvailable
? {
...location,
search: `?${stringify({ ...query, use: version === Version.v1 ? undefined : Version.v1 })}`
}
: location
}, [location, query, version, versionSwitchAvailable])

const handleClick = useCallback(
e => {
if (!versionSwitchAvailable) e.preventDefault()
},
[versionSwitchAvailable]
)

return (
<VersionToggle enabled={versionSwitchAvailable} to={toggleDest} onClick={handleClick}>
<VersionLabel enabled={version === Version.v2 || !versionSwitchAvailable}>V2</VersionLabel>
<VersionLabel enabled={version === Version.v1 && versionSwitchAvailable}>V1</VersionLabel>
</VersionToggle>
)
}
78 changes: 24 additions & 54 deletions src/components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { ChainId, WETH } from '@uniswap/sdk'
import React from 'react'
import { isMobile } from 'react-device-detect'
import { Link as HistoryLink } from 'react-router-dom'
import { Text } from 'rebass'

import styled from 'styled-components'
import { useTokenBalanceTreatingWETHasETH } from '../../state/wallet/hooks'

import Row from '../Row'
import Menu from '../Menu'
import Web3Status from '../Web3Status'

import { ExternalLink, StyledInternalLink } from '../../theme'
import { Text } from 'rebass'
import { WETH, ChainId } from '@uniswap/sdk'
import { isMobile } from 'react-device-detect'
import { YellowCard } from '../Card'
import { useActiveWeb3React } from '../../hooks'
import { useDarkModeManager } from '../../state/user/hooks'

import Logo from '../../assets/svg/logo.svg'
import Wordmark from '../../assets/svg/wordmark.svg'
import LogoDark from '../../assets/svg/logo_white.svg'
import Wordmark from '../../assets/svg/wordmark.svg'
import WordmarkDark from '../../assets/svg/wordmark_white.svg'
import { useActiveWeb3React } from '../../hooks'
import { useDarkModeManager } from '../../state/user/hooks'
import { useTokenBalanceTreatingWETHasETH } from '../../state/wallet/hooks'

import { ExternalLink, StyledInternalLink } from '../../theme'
import { YellowCard } from '../Card'
import { AutoColumn } from '../Column'
import { RowBetween } from '../Row'
import Menu from '../Menu'

import Row, { RowBetween } from '../Row'
import Web3Status from '../Web3Status'
import { VersionSwitch } from './VersionSwitch'

const HeaderFrame = styled.div`
display: flex;
Expand Down Expand Up @@ -122,33 +122,13 @@ const MigrateBanner = styled(AutoColumn)`
`};
`

const VersionLabel = styled.span<{ isV2?: boolean }>`
padding: ${({ isV2 }) => (isV2 ? '0.15rem 0.5rem 0.16rem 0.45rem' : '0.15rem 0.5rem 0.16rem 0.35rem')};
border-radius: 14px;
background: ${({ theme, isV2 }) => (isV2 ? theme.primary1 : 'none')};
color: ${({ theme, isV2 }) => (isV2 ? theme.white : theme.primary1)};
font-size: 0.825rem;
font-weight: 400;
:hover {
user-select: ${({ isV2 }) => (isV2 ? 'none' : 'initial')};
background: ${({ theme, isV2 }) => (isV2 ? theme.primary1 : 'none')};
color: ${({ theme, isV2 }) => (isV2 ? theme.white : theme.primary3)};
}
`

const VersionToggle = styled.a`
border-radius: 16px;
background: ${({ theme }) => theme.primary5};
border: 1px solid ${({ theme }) => theme.primary4};
color: ${({ theme }) => theme.primary1};
display: flex;
width: fit-content;
cursor: pointer;
text-decoration: none;
:hover {
text-decoration: none;
}
`
const NETWORK_LABELS: { [chainId in ChainId]: string | null } = {
[ChainId.MAINNET]: null,
[ChainId.RINKEBY]: 'Rinkeby',
[ChainId.ROPSTEN]: 'Ropsten',
[ChainId.GÖRLI]: 'Görli',
[ChainId.KOVAN]: 'Kovan'
}

export default function Header() {
const { account, chainId } = useActiveWeb3React()
Expand Down Expand Up @@ -187,21 +167,11 @@ export default function Header() {
</TitleText>
)}
</Title>
<TestnetWrapper style={{ pointerEvents: 'auto' }}>
{!isMobile && (
<VersionToggle target="_self" href="https://v1.uniswap.exchange">
<VersionLabel isV2={true}>V2</VersionLabel>
<VersionLabel isV2={false}>V1</VersionLabel>
</VersionToggle>
)}
</TestnetWrapper>
<TestnetWrapper style={{ pointerEvents: 'auto' }}>{!isMobile && <VersionSwitch />}</TestnetWrapper>
</HeaderElement>
<HeaderElement>
<TestnetWrapper>
{!isMobile && chainId === ChainId.ROPSTEN && <NetworkCard>Ropsten</NetworkCard>}
{!isMobile && chainId === ChainId.RINKEBY && <NetworkCard>Rinkeby</NetworkCard>}
{!isMobile && chainId === ChainId.GÖRLI && <NetworkCard>Görli</NetworkCard>}
{!isMobile && chainId === ChainId.KOVAN && <NetworkCard>Kovan</NetworkCard>}
{!isMobile && NETWORK_LABELS[chainId] && <NetworkCard>{NETWORK_LABELS[chainId]}</NetworkCard>}
</TestnetWrapper>
<AccountElement active={!!account} style={{ pointerEvents: 'auto' }}>
{account && userEthBalance ? (
Expand Down
19 changes: 11 additions & 8 deletions src/components/TxnPopup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useCallback, useState } from 'react'
import React, { useCallback, useContext, useState } from 'react'
import { AlertCircle, CheckCircle } from 'react-feather'

import styled from 'styled-components'
import styled, { ThemeContext } from 'styled-components'

import { useActiveWeb3React } from '../../hooks'
import useInterval from '../../hooks/useInterval'
Expand Down Expand Up @@ -51,13 +51,16 @@ export default function TxnPopup({
isRunning ? delay : null
)

const handleMouseEnter = useCallback(() => setIsRunning(false), [])
const handleMouseLeave = useCallback(() => setIsRunning(true), [])

const theme = useContext(ThemeContext)

return (
<AutoRow onMouseEnter={() => setIsRunning(false)} onMouseLeave={() => setIsRunning(true)}>
{success ? (
<CheckCircle color={'#27AE60'} size={24} style={{ paddingRight: '24px' }} />
) : (
<AlertCircle color={'#FF6871'} size={24} style={{ paddingRight: '24px' }} />
)}
<AutoRow onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
<div style={{ paddingRight: 16 }}>
{success ? <CheckCircle color={theme.green1} size={24} /> : <AlertCircle color={theme.red1} size={24} />}
</div>
<AutoColumn gap="8px">
<TYPE.body fontWeight={500}>
{summary ? summary : 'Hash: ' + hash.slice(0, 8) + '...' + hash.slice(58, 65)}
Expand Down
40 changes: 40 additions & 0 deletions src/components/swap/BetterTradeLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { stringify } from 'qs'
import React, { useContext, useMemo } from 'react'
import { useLocation } from 'react-router'
import { Text } from 'rebass'
import { ThemeContext } from 'styled-components'
import useParsedQueryString from '../../hooks/useParsedQueryString'
import { Version } from '../../hooks/useToggledVersion'

import { StyledInternalLink } from '../../theme'
import { YellowCard } from '../Card'
import { AutoColumn } from '../Column'

export default function BetterTradeLink({ version }: { version: Version }) {
const theme = useContext(ThemeContext)
const location = useLocation()
const search = useParsedQueryString()

const linkDestination = useMemo(() => {
return {
...location,
search: `?${stringify({
...search,
use: version
})}`
}
}, [location, search, version])

return (
<YellowCard style={{ marginTop: '12px', padding: '8px 4px' }}>
<AutoColumn gap="sm" justify="center" style={{ alignItems: 'center', textAlign: 'center' }}>
<Text lineHeight="145.23%;" fontSize={14} fontWeight={400} color={theme.text1}>
There is a better price for this trade on{' '}
<StyledInternalLink to={linkDestination}>
<b>Uniswap {version.toUpperCase()}</b>
</StyledInternalLink>
</Text>
</AutoColumn>
</YellowCard>
)
}
23 changes: 0 additions & 23 deletions src/components/swap/V1TradeLink.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,4 @@ export const PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN: Percent = new Percent(JSBI.Bi

// used to ensure the user doesn't send so much ETH so they end up with <.01
export const MIN_ETH: JSBI = JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(16)) // .01 ETH
export const V1_TRADE_LINK_THRESHOLD = new Percent(JSBI.BigInt(75), JSBI.BigInt(10000))
export const BETTER_TRADE_LINK_THRESHOLD = new Percent(JSBI.BigInt(75), JSBI.BigInt(10000))
Loading

1 comment on commit bafd3f3

@vercel
Copy link

@vercel vercel bot commented on bafd3f3 Jun 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.