Compare commits

...

16 Commits

Author SHA1 Message Date
Antonio Savage
8a845ee0e9 fix(discord invite link): working discord invite link (#929) 2020-07-06 22:59:14 -04:00
Moody Salem
f5229ca838 linter error 2020-07-06 21:31:08 -04:00
Moody Salem
875203f0ef fix(responsiveness): small tweaks for mobile 2020-07-06 21:26:38 -04:00
Moody Salem
91a8202737 fix(send page): support swap + send query parameters on send page (#921)
* support swap + send query parameters on send page

* revert the unfinished portis logic

Co-authored-by: ianlapham <ianlapham@gmail.com>
2020-07-05 22:32:54 -04:00
Moody Salem
0b4819d165 fix(#899): Add PieDAO USD++ 2020-07-05 22:29:49 -04:00
Jonathan Diep
e7d3289754 improvement(token warning card): link to the token page on etherscan instead of the address page (#914) 2020-07-02 08:27:19 -04:00
Moody Salem
0698e0f82a Update README.md 2020-07-01 13:09:37 -04:00
Micah Zoltu
0350cc4701 fix(REP token): renames REP to REPv1 (#915)
https://www.augur.net/blog/v2-launch/

TL;DR: Augur v2 launch is coming up and will introduce a new REP token.  FF has requested all exchanges rename REP to REPv1 to avoid confusion.

Going forward, REP tokens will contain versioning in their name/symbol on chain so this should be a one-time "fix" for Augur v1 REP.
2020-07-01 10:19:28 -04:00
Moody Salem
997052869d fix(lint): linter error 2020-06-30 16:50:19 -04:00
Moody Salem
9ec16c2ba8 actually add the inter-ui dependency 2020-06-30 16:47:16 -04:00
Moody Salem
e2cf8f1642 fix(font): do not load font from remote 2020-06-30 16:43:21 -04:00
Moody Salem
ed6952d1f7 readme cleanup 2020-06-30 14:13:27 -04:00
Moody Salem
3277d70e93 fix all tests 2020-06-30 14:02:09 -04:00
Moody Salem
d1a31fe763 old link 2020-06-30 13:53:18 -04:00
Moody Salem
f88af029ae chore(tests): fix integration tests 2020-06-30 13:51:20 -04:00
Moody Salem
9f3e49b4d8 chore(ipfs migration): point at master branch instead of v2 branch 2020-06-30 13:49:38 -04:00
20 changed files with 94 additions and 60 deletions

View File

@@ -7,7 +7,7 @@ on:
# releases are triggered on changes to this file # releases are triggered on changes to this file
push: push:
branches: branches:
- v2 - master
paths: paths:
- '.github/workflows/release.yaml' - '.github/workflows/release.yaml'
- '.env.production' - '.env.production'

View File

@@ -2,10 +2,10 @@ name: Tests
on: on:
push: push:
branches: branches:
- v2 - master
pull_request: pull_request:
branches: branches:
- v2 - master
jobs: jobs:
integration-tests: integration-tests:
name: Integration tests name: Integration tests

1
.yarnrc Normal file
View File

@@ -0,0 +1 @@
ignore-scripts true

View File

@@ -1,4 +1,4 @@
# Uniswap Frontend # Uniswap Interface
[![Tests](https://github.com/Uniswap/uniswap-interface/workflows/Tests/badge.svg)](https://github.com/Uniswap/uniswap-interface/actions?query=workflow%3ATests) [![Tests](https://github.com/Uniswap/uniswap-interface/workflows/Tests/badge.svg)](https://github.com/Uniswap/uniswap-interface/actions?query=workflow%3ATests)
[![Styled With Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://prettier.io/) [![Styled With Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://prettier.io/)
@@ -6,6 +6,7 @@
An open source interface for Uniswap -- a protocol for decentralized exchange of Ethereum tokens. An open source interface for Uniswap -- a protocol for decentralized exchange of Ethereum tokens.
- Website: [uniswap.org](https://uniswap.org/) - Website: [uniswap.org](https://uniswap.org/)
- Interface: [app.uniswap.org](https://app.uniswap.org)
- Docs: [uniswap.org/docs/](https://uniswap.org/docs/) - Docs: [uniswap.org/docs/](https://uniswap.org/docs/)
- Twitter: [@UniswapProtocol](https://twitter.com/UniswapProtocol) - Twitter: [@UniswapProtocol](https://twitter.com/UniswapProtocol)
- Reddit: [/r/Uniswap](https://www.reddit.com/r/Uniswap/) - Reddit: [/r/Uniswap](https://www.reddit.com/r/Uniswap/)
@@ -13,11 +14,11 @@ An open source interface for Uniswap -- a protocol for decentralized exchange of
- Discord: [Uniswap](https://discord.gg/Y7TF6QA) - Discord: [Uniswap](https://discord.gg/Y7TF6QA)
- Whitepaper: [Link](https://hackmd.io/C-DvwDSfSxuh-Gd4WKE_ig) - Whitepaper: [Link](https://hackmd.io/C-DvwDSfSxuh-Gd4WKE_ig)
## Accessing the frontend ## Accessing the Uniswap Interface
To access the front end, use an IPFS gateway link from the To access the Uniswap Interface, use an IPFS gateway link from the
[latest release](https://github.com/Uniswap/uniswap-interface/releases/latest) [latest release](https://github.com/Uniswap/uniswap-interface/releases/latest),
or visit [uniswap.exchange](https://uniswap.exchange). or visit [app.uniswap.org](https://app.uniswap.org).
## Development ## Development
@@ -27,31 +28,32 @@ or visit [uniswap.exchange](https://uniswap.exchange).
yarn yarn
``` ```
### Configure Environment (optional)
Copy `.env` to `.env.local` and change the appropriate variables.
### Run ### Run
```bash ```bash
yarn start yarn start
``` ```
To have the frontend default to a different network, make a copy of `.env` named `.env.local`, ### Configuring the environment (optional)
change `REACT_APP_NETWORK_ID` to `"{yourNetworkId}"`, and change `REACT_APP_NETWORK_URL` to e.g.
`"https://{yourNetwork}.infura.io/v3/{yourKey}"`.
Note that the front end only works properly on testnets where both To have the interface default to a different network when a wallet is not connected:
1. Make a copy of `.env` named `.env.local`
2. Change `REACT_APP_NETWORK_ID` to `"{YOUR_NETWORK_ID}"`
3. Change `REACT_APP_NETWORK_URL` to e.g. `"https://{YOUR_NETWORK_ID}.infura.io/v3/{YOUR_INFURA_KEY}"`
Note that the interface only works on testnets where both
[Uniswap V2](https://uniswap.org/docs/v2/smart-contracts/factory/) and [Uniswap V2](https://uniswap.org/docs/v2/smart-contracts/factory/) and
[multicall](https://github.com/makerdao/multicall) are deployed. [multicall](https://github.com/makerdao/multicall) are deployed.
The frontend will not work on other networks. The interface will not work on other networks.
## Contributions ## Contributions
**Please open all pull requests against the `v2` branch.** **Please open all pull requests against the `master` branch.**
CI checks will run against all PRs. CI checks will run against all PRs.
## Accessing Uniswap V1 interface ## Accessing Uniswap Interface V1
The Uniswap V1 interface for mainnet and testnets is accessible via IPFS gateways linked The Uniswap Interface supports swapping against, and migrating or removing liquidity from Uniswap V1. However,
from the [v1.0.0 release](https://github.com/Uniswap/uniswap-interface/releases/tag/v1.0.0). if you would like to use Uniswap V1, the Uniswap V1 interface for mainnet and testnets is accessible via IPFS gateways
linked from the [v1.0.0 release](https://github.com/Uniswap/uniswap-interface/releases/tag/v1.0.0).

View File

@@ -69,13 +69,13 @@ class CustomizedBridge extends _Eip1193Bridge {
// sets up the injected provider to be a mock ethereum provider with the given mnemonic/index // sets up the injected provider to be a mock ethereum provider with the given mnemonic/index
Cypress.Commands.overwrite('visit', (original, url, options) => { Cypress.Commands.overwrite('visit', (original, url, options) => {
return original(url, { return original(url.startsWith('/') && url.length > 2 && !url.startsWith('/#') ? `/#${url}` : url, {
...options, ...options,
onBeforeLoad(win) { onBeforeLoad(win) {
options && options.onBeforeLoad && options.onBeforeLoad(win) options && options.onBeforeLoad && options.onBeforeLoad(win)
const provider = new JsonRpcProvider('https://rinkeby.infura.io/v3/acb7e55995d04c49bfb52b7141599467', 4) const provider = new JsonRpcProvider('https://rinkeby.infura.io/v3/acb7e55995d04c49bfb52b7141599467', 4)
const signer = new Wallet(PRIVATE_KEY_TEST_NEVER_USE, provider) const signer = new Wallet(PRIVATE_KEY_TEST_NEVER_USE, provider)
win.ethereum = new CustomizedBridge(signer, provider) win.ethereum = new CustomizedBridge(signer, provider)
} },
}) })
}) })

View File

@@ -13,7 +13,7 @@
"@ethersproject/strings": "^5.0.0-beta.136", "@ethersproject/strings": "^5.0.0-beta.136",
"@ethersproject/units": "^5.0.0-beta.132", "@ethersproject/units": "^5.0.0-beta.132",
"@ethersproject/wallet": "^5.0.0-beta.141", "@ethersproject/wallet": "^5.0.0-beta.141",
"@popperjs/core": "^2.4.0", "@popperjs/core": "^2.4.4",
"@reach/dialog": "^0.10.3", "@reach/dialog": "^0.10.3",
"@reach/portal": "^0.10.3", "@reach/portal": "^0.10.3",
"@reduxjs/toolkit": "^1.3.5", "@reduxjs/toolkit": "^1.3.5",
@@ -51,6 +51,7 @@
"i18next": "^15.0.9", "i18next": "^15.0.9",
"i18next-browser-languagedetector": "^3.0.1", "i18next-browser-languagedetector": "^3.0.1",
"i18next-xhr-backend": "^2.0.1", "i18next-xhr-backend": "^2.0.1",
"inter-ui": "^3.13.1",
"jazzicon": "^1.5.0", "jazzicon": "^1.5.0",
"lodash.flatmap": "^4.5.0", "lodash.flatmap": "^4.5.0",
"polished": "^3.3.2", "polished": "^3.3.2",

View File

@@ -11,7 +11,7 @@ const VersionLabel = styled.span<{ enabled: boolean }>`
background: ${({ theme, enabled }) => (enabled ? theme.primary1 : 'none')}; background: ${({ theme, enabled }) => (enabled ? theme.primary1 : 'none')};
color: ${({ theme, enabled }) => (enabled ? theme.white : theme.text1)}; color: ${({ theme, enabled }) => (enabled ? theme.white : theme.text1)};
font-size: 1rem; font-size: 1rem;
font-weight: ${({ theme, enabled }) => (enabled ? '500' : '400')}; font-weight: ${({ enabled }) => (enabled ? '500' : '400')};
:hover { :hover {
user-select: ${({ enabled }) => (enabled ? 'none' : 'initial')}; user-select: ${({ enabled }) => (enabled ? 'none' : 'initial')};
background: ${({ theme, enabled }) => (enabled ? theme.primary1 : 'none')}; background: ${({ theme, enabled }) => (enabled ? theme.primary1 : 'none')};

View File

@@ -121,7 +121,7 @@ export default function Menu() {
<Code size={14} /> <Code size={14} />
Code Code
</MenuItem> </MenuItem>
<MenuItem id="link" href="https://discord.gg/vXCdddD"> <MenuItem id="link" href="https://discord.gg/EwFs3Pp">
<MessageCircle size={14} /> <MessageCircle size={14} />
Discord Discord
</MenuItem> </MenuItem>

View File

@@ -7,6 +7,7 @@ import { ThemeContext } from 'styled-components'
import Card from '../../components/Card' import Card from '../../components/Card'
import { useActiveWeb3React } from '../../hooks' import { useActiveWeb3React } from '../../hooks'
import { useAllTokens, useToken } from '../../hooks/Tokens' import { useAllTokens, useToken } from '../../hooks/Tokens'
import useInterval from '../../hooks/useInterval'
import { useAllTokenBalancesTreatingWETHasETH, useTokenBalanceTreatingWETHasETH } from '../../state/wallet/hooks' import { useAllTokenBalancesTreatingWETHasETH, useTokenBalanceTreatingWETHasETH } from '../../state/wallet/hooks'
import { CloseIcon, LinkStyledButton } from '../../theme/components' import { CloseIcon, LinkStyledButton } from '../../theme/components'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
@@ -110,10 +111,17 @@ export default function TokenSearchModal({
const openTooltip = useCallback(() => { const openTooltip = useCallback(() => {
setTooltipOpen(true) setTooltipOpen(true)
inputRef.current?.focus()
}, [setTooltipOpen]) }, [setTooltipOpen])
const closeTooltip = useCallback(() => setTooltipOpen(false), [setTooltipOpen]) const closeTooltip = useCallback(() => setTooltipOpen(false), [setTooltipOpen])
useInterval(
() => {
setTooltipOpen(false)
},
tooltipOpen ? 4000 : null,
false
)
return ( return (
<Modal <Modal
isOpen={isOpen} isOpen={isOpen}
@@ -146,6 +154,7 @@ export default function TokenSearchModal({
value={searchQuery} value={searchQuery}
ref={inputRef} ref={inputRef}
onChange={handleInput} onChange={handleInput}
onFocus={closeTooltip}
onBlur={closeTooltip} onBlur={closeTooltip}
/> />
</Tooltip> </Tooltip>

View File

@@ -49,8 +49,8 @@ const Option = styled(FancyButton)<{ active: boolean }>`
const Input = styled.input` const Input = styled.input`
background: ${({ theme }) => theme.bg1}; background: ${({ theme }) => theme.bg1};
flex-grow: 1; flex-grow: 1;
font-size: 12px; font-size: 16px;
min-width: 20px; min-width: 60px;
outline: none; outline: none;
&::-webkit-outer-spin-button, &::-webkit-outer-spin-button,
&::-webkit-inner-spin-button { &::-webkit-inner-spin-button {

View File

@@ -109,7 +109,7 @@ export default function TokenWarningCard({ token, ...rest }: TokenWarningCardPro
? `${token.name} (${token.symbol})` ? `${token.name} (${token.symbol})`
: token.name || token.symbol} : token.name || token.symbol}
</div> </div>
<ExternalLink style={{ fontWeight: 400 }} href={getEtherscanLink(chainId, token.address, 'address')}> <ExternalLink style={{ fontWeight: 400 }} href={getEtherscanLink(chainId, token.address, 'token')}>
(View on Etherscan) (View on Etherscan)
</ExternalLink> </ExternalLink>
</Row> </Row>

View File

@@ -91,7 +91,7 @@ export default [
new Token(ChainId.MAINNET, '0x459086F2376525BdCebA5bDDA135e4E9d3FeF5bf', 8, 'renBCH', 'renBCH'), new Token(ChainId.MAINNET, '0x459086F2376525BdCebA5bDDA135e4E9d3FeF5bf', 8, 'renBCH', 'renBCH'),
new Token(ChainId.MAINNET, '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D', 8, 'renBTC', 'renBTC'), new Token(ChainId.MAINNET, '0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D', 8, 'renBTC', 'renBTC'),
new Token(ChainId.MAINNET, '0x1C5db575E2Ff833E46a2E9864C22F4B22E0B37C2', 8, 'renZEC', 'renZEC'), new Token(ChainId.MAINNET, '0x1C5db575E2Ff833E46a2E9864C22F4B22E0B37C2', 8, 'renZEC', 'renZEC'),
new Token(ChainId.MAINNET, '0x1985365e9f78359a9B6AD760e32412f4a445E862', 18, 'REP', 'Reputation'), new Token(ChainId.MAINNET, '0x1985365e9f78359a9B6AD760e32412f4a445E862', 18, 'REPv1', 'Augur v1 Reputation'),
new Token(ChainId.MAINNET, '0x9469D013805bFfB7D3DEBe5E7839237e535ec483', 18, 'RING', 'Darwinia Network Native Token'), new Token(ChainId.MAINNET, '0x9469D013805bFfB7D3DEBe5E7839237e535ec483', 18, 'RING', 'Darwinia Network Native Token'),
new Token(ChainId.MAINNET, '0x607F4C5BB672230e8672085532f7e901544a7375', 9, 'RLC', 'iEx.ec Network Token'), new Token(ChainId.MAINNET, '0x607F4C5BB672230e8672085532f7e901544a7375', 9, 'RLC', 'iEx.ec Network Token'),
new Token(ChainId.MAINNET, '0xB4EFd85c19999D84251304bDA99E90B92300Bd93', 18, 'RPL', 'Rocket Pool'), new Token(ChainId.MAINNET, '0xB4EFd85c19999D84251304bDA99E90B92300Bd93', 18, 'RPL', 'Rocket Pool'),
@@ -123,6 +123,7 @@ export default [
new Token(ChainId.MAINNET, '0xA4Bdb11dc0a2bEC88d24A3aa1E6Bb17201112eBe', 6, 'USDS', 'StableUSD'), new Token(ChainId.MAINNET, '0xA4Bdb11dc0a2bEC88d24A3aa1E6Bb17201112eBe', 6, 'USDS', 'StableUSD'),
USDT, USDT,
new Token(ChainId.MAINNET, '0xeb269732ab75A6fD61Ea60b06fE994cD32a83549', 18, 'USDx', 'dForce'), new Token(ChainId.MAINNET, '0xeb269732ab75A6fD61Ea60b06fE994cD32a83549', 18, 'USDx', 'dForce'),
new Token(ChainId.MAINNET, '0x9A48BD0EC040ea4f1D3147C025cd4076A2e71e3e', 18, 'USD++', 'PieDAO USD++'),
new Token(ChainId.MAINNET, '0x8f3470A7388c05eE4e7AF3d01D8C722b0FF52374', 18, 'VERI', 'Veritaseum'), new Token(ChainId.MAINNET, '0x8f3470A7388c05eE4e7AF3d01D8C722b0FF52374', 18, 'VERI', 'Veritaseum'),
new Token(ChainId.MAINNET, '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 8, 'WBTC', 'Wrapped BTC'), new Token(ChainId.MAINNET, '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 8, 'WBTC', 'Wrapped BTC'),
new Token(ChainId.MAINNET, '0x09fE5f0236F0Ea5D930197DCE254d77B04128075', 18, 'WCK', 'Wrapped CryptoKitties'), new Token(ChainId.MAINNET, '0x09fE5f0236F0Ea5D930197DCE254d77B04128075', 18, 'WCK', 'Wrapped CryptoKitties'),

View File

@@ -1,6 +1,6 @@
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
export default function useInterval(callback: () => void, delay: null | number) { export default function useInterval(callback: () => void, delay: null | number, leading = true) {
const savedCallback = useRef<() => void>() const savedCallback = useRef<() => void>()
// Remember the latest callback. // Remember the latest callback.
@@ -16,10 +16,10 @@ export default function useInterval(callback: () => void, delay: null | number)
} }
if (delay !== null) { if (delay !== null) {
tick() if (leading) tick()
const id = setInterval(tick, delay) const id = setInterval(tick, delay)
return () => clearInterval(id) return () => clearInterval(id)
} }
return return
}, [delay]) }, [delay, leading])
} }

View File

@@ -6,6 +6,7 @@ import ReactDOM from 'react-dom'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
import { Provider } from 'react-redux' import { Provider } from 'react-redux'
import { NetworkContextName } from './constants' import { NetworkContextName } from './constants'
import 'inter-ui'
import './i18n' import './i18n'
import App from './pages/App' import App from './pages/App'
import store from './state' import store from './state'

View File

@@ -43,7 +43,8 @@ import { useUserSlippageTolerance, useUserDeadline, useExpertModeManager } from
import { ClickableText } from '../Pool/styleds' import { ClickableText } from '../Pool/styleds'
export default function Send() { export default function Send() {
useDefaultsFromURLSearch() // override auto ETH populate to allow for single inputs or swap and send
useDefaultsFromURLSearch(true)
// text translation // text translation
// const { t } = useTranslation() // const { t } = useTranslation()
@@ -64,7 +65,19 @@ export default function Send() {
const [recipientError, setRecipientError] = useState<string | null>('Enter a Recipient') const [recipientError, setRecipientError] = useState<string | null>('Enter a Recipient')
// trade details, check query params for initial state // trade details, check query params for initial state
const { independentField, typedValue } = useSwapState() const {
independentField,
typedValue,
[Field.OUTPUT]: { address: output }
} = useSwapState()
// if output is valid set to sending view (will reset to undefined on remove swap)
useEffect(() => {
if (output) {
setSendingWithSwap(true)
}
}, [output])
const { const {
parsedAmount, parsedAmount,
bestTrade: bestTradeV2, bestTrade: bestTradeV2,
@@ -134,13 +147,6 @@ export default function Send() {
const { onSwitchTokens, onTokenSelection, onUserInput } = useSwapActionHandlers() const { onSwitchTokens, onTokenSelection, onUserInput } = useSwapActionHandlers()
// reset field if sending with with swap is cancled
useEffect(() => {
if (!sendingWithSwap) {
onTokenSelection(Field.OUTPUT, null)
}
}, [onTokenSelection, sendingWithSwap])
const maxAmountInput: TokenAmount = const maxAmountInput: TokenAmount =
!!tokenBalances[Field.INPUT] && !!tokenBalances[Field.INPUT] &&
!!tokens[Field.INPUT] && !!tokens[Field.INPUT] &&
@@ -419,7 +425,10 @@ export default function Send() {
<ArrowDown size="16" color={theme.text2} onClick={onSwitchTokens} /> <ArrowDown size="16" color={theme.text2} onClick={onSwitchTokens} />
</ArrowWrapper> </ArrowWrapper>
<ButtonSecondary <ButtonSecondary
onClick={() => setSendingWithSwap(false)} onClick={() => {
setSendingWithSwap(false)
onTokenSelection(Field.OUTPUT, null)
}}
style={{ marginRight: '0px', width: 'auto', fontSize: '14px' }} style={{ marginRight: '0px', width: 'auto', fontSize: '14px' }}
padding={'4px 6px'} padding={'4px 6px'}
> >

View File

@@ -172,15 +172,14 @@ export function useDerivedSwapInfo(): {
} }
} }
function parseCurrencyFromURLParameter(urlParam: any, chainId: number): string { function parseCurrencyFromURLParameter(urlParam: any, chainId: number, overrideWETH: boolean): string {
if (typeof urlParam === 'string') { if (typeof urlParam === 'string') {
const valid = isAddress(urlParam) const valid = isAddress(urlParam)
if (valid) return valid if (valid) return valid
if (urlParam.toLowerCase() === 'eth') return WETH[chainId as ChainId]?.address ?? '' if (urlParam.toLowerCase() === 'eth') return WETH[chainId as ChainId]?.address ?? ''
if (valid === false) return WETH[chainId as ChainId]?.address ?? '' if (valid === false) return WETH[chainId as ChainId]?.address ?? ''
} }
return overrideWETH ? '' : WETH[chainId as ChainId]?.address ?? ''
return WETH[chainId as ChainId]?.address
} }
function parseTokenAmountURLParameter(urlParam: any): string { function parseTokenAmountURLParameter(urlParam: any): string {
@@ -191,9 +190,9 @@ function parseIndependentFieldURLParameter(urlParam: any): Field {
return typeof urlParam === 'string' && urlParam.toLowerCase() === 'output' ? Field.OUTPUT : Field.INPUT return typeof urlParam === 'string' && urlParam.toLowerCase() === 'output' ? Field.OUTPUT : Field.INPUT
} }
export function queryParametersToSwapState(parsedQs: ParsedQs, chainId: ChainId): SwapState { export function queryParametersToSwapState(parsedQs: ParsedQs, chainId: ChainId, overrideETH: boolean): SwapState {
let inputCurrency = parseCurrencyFromURLParameter(parsedQs.inputCurrency, chainId) let inputCurrency = parseCurrencyFromURLParameter(parsedQs.inputCurrency, chainId, overrideETH)
let outputCurrency = parseCurrencyFromURLParameter(parsedQs.outputCurrency, chainId) let outputCurrency = parseCurrencyFromURLParameter(parsedQs.outputCurrency, chainId, overrideETH)
if (inputCurrency === outputCurrency) { if (inputCurrency === outputCurrency) {
if (typeof parsedQs.outputCurrency === 'string') { if (typeof parsedQs.outputCurrency === 'string') {
inputCurrency = '' inputCurrency = ''
@@ -215,14 +214,16 @@ export function queryParametersToSwapState(parsedQs: ParsedQs, chainId: ChainId)
} }
// updates the swap state to use the defaults for a given network // updates the swap state to use the defaults for a given network
export function useDefaultsFromURLSearch() { // set overrideETH to true if dont want to autopopulate ETH
export function useDefaultsFromURLSearch(overrideWETH = false) {
const { chainId } = useActiveWeb3React() const { chainId } = useActiveWeb3React()
const dispatch = useDispatch<AppDispatch>() const dispatch = useDispatch<AppDispatch>()
const parsedQs = useParsedQueryString() const parsedQs = useParsedQueryString()
useEffect(() => { useEffect(() => {
if (!chainId) return if (!chainId) return
const parsed = queryParametersToSwapState(parsedQs, chainId) const parsed = queryParametersToSwapState(parsedQs, chainId, overrideWETH)
dispatch( dispatch(
replaceSwapState({ replaceSwapState({
typedValue: parsed.typedValue, typedValue: parsed.typedValue,

View File

@@ -168,8 +168,6 @@ export const TYPE = {
} }
export const FixedGlobalStyle = createGlobalStyle` export const FixedGlobalStyle = createGlobalStyle`
@import url('https://rsms.me/inter/inter.css');
html, input, textarea, button { html, input, textarea, button {
font-family: 'Inter', sans-serif; font-family: 'Inter', sans-serif;
letter-spacing: -0.018em; letter-spacing: -0.018em;

View File

@@ -16,6 +16,9 @@ describe('utils', () => {
it('correct for tx', () => { it('correct for tx', () => {
expect(getEtherscanLink(1, 'abc', 'transaction')).toEqual('https://etherscan.io/tx/abc') expect(getEtherscanLink(1, 'abc', 'transaction')).toEqual('https://etherscan.io/tx/abc')
}) })
it('correct for token', () => {
expect(getEtherscanLink(1, 'abc', 'token')).toEqual('https://etherscan.io/token/abc')
})
it('correct for address', () => { it('correct for address', () => {
expect(getEtherscanLink(1, 'abc', 'address')).toEqual('https://etherscan.io/address/abc') expect(getEtherscanLink(1, 'abc', 'address')).toEqual('https://etherscan.io/address/abc')
}) })

View File

@@ -25,13 +25,16 @@ const ETHERSCAN_PREFIXES: { [chainId in ChainId]: string } = {
42: 'kovan.' 42: 'kovan.'
} }
export function getEtherscanLink(chainId: ChainId, data: string, type: 'transaction' | 'address'): string { export function getEtherscanLink(chainId: ChainId, data: string, type: 'transaction' | 'token' | 'address'): string {
const prefix = `https://${ETHERSCAN_PREFIXES[chainId] || ETHERSCAN_PREFIXES[1]}etherscan.io` const prefix = `https://${ETHERSCAN_PREFIXES[chainId] || ETHERSCAN_PREFIXES[1]}etherscan.io`
switch (type) { switch (type) {
case 'transaction': { case 'transaction': {
return `${prefix}/tx/${data}` return `${prefix}/tx/${data}`
} }
case 'token': {
return `${prefix}/token/${data}`
}
case 'address': case 'address':
default: { default: {
return `${prefix}/address/${data}` return `${prefix}/address/${data}`

View File

@@ -2046,10 +2046,10 @@
resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b"
integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==
"@popperjs/core@^2.4.0": "@popperjs/core@^2.4.4":
version "2.4.0" version "2.4.4"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.4.0.tgz#0e1bdf8d021e7ea58affade33d9d607e11365915" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.4.4.tgz#11d5db19bd178936ec89cd84519c4de439574398"
integrity sha512-NMrDy6EWh9TPdSRiHmHH2ye1v5U0gBD7pRYwSwJvomx7Bm4GG04vu63dYiVzebLOx2obPpJugew06xVP0Nk7hA== integrity sha512-1oO6+dN5kdIA3sKPZhRGJTfGVP4SWV6KqlMOwry4J3HfyD68sl/3KmG7DeYUzvN+RbhXDnv/D8vNNB8168tAMg==
"@portis/eth-json-rpc-middleware@^4.1.2": "@portis/eth-json-rpc-middleware@^4.1.2":
version "4.1.2" version "4.1.2"
@@ -8419,6 +8419,11 @@ inquirer@^7.0.0:
strip-ansi "^6.0.0" strip-ansi "^6.0.0"
through "^2.3.6" through "^2.3.6"
inter-ui@^3.13.1:
version "3.13.1"
resolved "https://registry.yarnpkg.com/inter-ui/-/inter-ui-3.13.1.tgz#3b3841c1ab425035d0146b38c7ee7a640d3da3d8"
integrity sha512-A+gHBm9WXZZmIYHdQci9ZoIrsPkzwYvWqG2+DyrwOuxjZVnRyz3b73ridPUWI/JvZ1nGf2j0VdJ+vxh0/bKBwg==
internal-ip@^4.3.0: internal-ip@^4.3.0:
version "4.3.0" version "4.3.0"
resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907"