Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af6098bfe5 | ||
|
|
fce29bb36f | ||
|
|
4517af39ba | ||
|
|
b40163ce05 | ||
|
|
809902efec | ||
|
|
70be9894fa | ||
|
|
698ad5bac9 | ||
|
|
cd37b7533d | ||
|
|
c0cd6a1c8d | ||
|
|
f6245d1093 | ||
|
|
83c784f7c0 | ||
|
|
3d95b1a33b | ||
|
|
5c96942922 | ||
|
|
d27c83b382 | ||
|
|
b2f88965a9 | ||
|
|
95db44e0fc | ||
|
|
7d45ff5ca8 | ||
|
|
8964cf86aa | ||
|
|
0e9f23ed56 | ||
|
|
e08e597655 | ||
|
|
744db49803 | ||
|
|
54f59e02fd | ||
|
|
7950e5c083 | ||
|
|
dd33205bf6 | ||
|
|
397a20b9ec | ||
|
|
0aac0b43aa | ||
|
|
702500794d | ||
|
|
8bea95fab2 | ||
|
|
27094c87f2 | ||
|
|
bede9171c3 | ||
|
|
251d7c0bc2 | ||
|
|
285e4f28f5 | ||
|
|
3aa045303a | ||
|
|
e0a7c3794e | ||
|
|
f5fc5da341 | ||
|
|
bea5c0484b | ||
|
|
27960532ca | ||
|
|
37a4e2f6e3 | ||
|
|
19a3b12ca8 | ||
|
|
22c1ddf393 | ||
|
|
b44ae1a267 | ||
|
|
418dcf0cb2 | ||
|
|
58a508c9d6 | ||
|
|
3198129af2 | ||
|
|
89d484d882 | ||
|
|
fa4688d96c | ||
|
|
7ee761a59e | ||
|
|
78e95f6073 | ||
|
|
c67e57505a | ||
|
|
30f7385db7 | ||
|
|
c0f58ae810 | ||
|
|
54dd5476ca | ||
|
|
57786335df | ||
|
|
948e01a196 | ||
|
|
abf127c596 | ||
|
|
4d3f870b93 | ||
|
|
452f2dc3c0 | ||
|
|
b6bd59f2b1 | ||
|
|
0190b5a408 | ||
|
|
d6030dcd45 | ||
|
|
f0e2a491dc | ||
|
|
021aab6547 | ||
|
|
81af31eec1 |
3
.env
3
.env
@@ -1,5 +1,4 @@
|
|||||||
REACT_APP_CHAIN_ID="1"
|
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
|
||||||
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847"
|
|
||||||
REACT_APP_WALLETCONNECT_BRIDGE_URL="https://uniswap.bridge.walletconnect.org"
|
REACT_APP_WALLETCONNECT_BRIDGE_URL="https://uniswap.bridge.walletconnect.org"
|
||||||
# Because we use storybook which has its own babel-loader dependency @ 8.2.2, where react-scripts uses 8.1.0
|
# Because we use storybook which has its own babel-loader dependency @ 8.2.2, where react-scripts uses 8.1.0
|
||||||
SKIP_PREFLIGHT_CHECK=true
|
SKIP_PREFLIGHT_CHECK=true
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
REACT_APP_CHAIN_ID="1"
|
REACT_APP_INFURA_KEY="099fc58e0de9451d80b18d7c74caa7c1"
|
||||||
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/099fc58e0de9451d80b18d7c74caa7c1"
|
|
||||||
REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236"
|
REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236"
|
||||||
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
|
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
|
||||||
REACT_APP_GOOGLE_ANALYTICS_ID="UA-128182339-4"
|
REACT_APP_GOOGLE_ANALYTICS_ID="UA-128182339-4"
|
||||||
|
|||||||
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: true
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Support
|
- name: Support
|
||||||
url: https://discord.gg/FCfyBSbCU5
|
url: https://discord.gg/FCfyBSbCU5
|
||||||
|
|||||||
14
.github/workflows/release.yaml
vendored
14
.github/workflows/release.yaml
vendored
@@ -94,19 +94,13 @@ jobs:
|
|||||||
The latest release is always accessible via our alias to the Cloudflare IPFS gateway at [app.uniswap.org](https://app.uniswap.org).
|
The latest release is always accessible via our alias to the Cloudflare IPFS gateway at [app.uniswap.org](https://app.uniswap.org).
|
||||||
|
|
||||||
You can also access the Uniswap Interface directly from an IPFS gateway.
|
You can also access the Uniswap Interface directly from an IPFS gateway.
|
||||||
The Uniswap interface uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to store your settings.
|
**BEWARE**: The Uniswap interface uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to remember your settings, such as which tokens you have imported.
|
||||||
**Beware** that other sites you access via the _same_ IPFS gateway can read and modify your settings on the Uniswap interface without your permission.
|
**You should always use an IPFS gateway that enforces origin separation**, or our alias to the latest release at [app.uniswap.org](https://app.uniswap.org).
|
||||||
You can avoid this issue by using a subdomain IPFS gateway, or our alias to the latest release at [app.uniswap.org](https://app.uniswap.org).
|
Your Uniswap settings are never remembered across different URLs.
|
||||||
The preferred URLs below are safe to use to access this specific release.
|
|
||||||
|
|
||||||
Preferred URLs:
|
IPFS gateways:
|
||||||
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.dweb.link/
|
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.dweb.link/
|
||||||
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.cf-ipfs.com/
|
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.cf-ipfs.com/
|
||||||
- [ipfs://${{ steps.upload.outputs.hash }}/](ipfs://${{ steps.upload.outputs.hash }}/)
|
- [ipfs://${{ steps.upload.outputs.hash }}/](ipfs://${{ steps.upload.outputs.hash }}/)
|
||||||
|
|
||||||
Other IPFS gateways:
|
|
||||||
- https://cloudflare-ipfs.com/ipfs/${{ steps.upload.outputs.hash }}/
|
|
||||||
- https://ipfs.infura.io/ipfs/${{ steps.upload.outputs.hash }}/
|
|
||||||
- https://ipfs.io/ipfs/${{ steps.upload.outputs.hash }}/
|
|
||||||
|
|
||||||
${{ needs.bump_version.outputs.changelog }}
|
${{ needs.bump_version.outputs.changelog }}
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -22,18 +22,12 @@ 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 [app.uniswap.org](https://app.uniswap.org).
|
or visit [app.uniswap.org](https://app.uniswap.org).
|
||||||
|
|
||||||
## Listing a token
|
|
||||||
|
|
||||||
Please see the
|
|
||||||
[@uniswap/default-token-list](https://github.com/uniswap/default-token-list)
|
|
||||||
repository.
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
### Install Dependencies
|
### Install Dependencies
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn
|
yarn install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run
|
### Run
|
||||||
@@ -42,19 +36,6 @@ yarn
|
|||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuring the environment (optional)
|
|
||||||
|
|
||||||
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
|
|
||||||
[multicall](https://github.com/makerdao/multicall) are deployed.
|
|
||||||
The interface will not work on other networks.
|
|
||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
**Please open all pull requests against the `main` branch.**
|
**Please open all pull requests against the `main` branch.**
|
||||||
|
|||||||
8
babel-plugin-macros.config.js
Normal file
8
babel-plugin-macros.config.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
const isDev = process.env.NODE_ENV !== 'production'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
styledComponents: {
|
||||||
|
fileName: isDev,
|
||||||
|
displayName: isDev,
|
||||||
|
},
|
||||||
|
}
|
||||||
19
package.json
19
package.json
@@ -9,6 +9,7 @@
|
|||||||
"@popperjs/core": "^2.4.4",
|
"@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",
|
||||||
|
"@react-hook/window-scroll": "^1.3.0",
|
||||||
"@reduxjs/toolkit": "^1.3.5",
|
"@reduxjs/toolkit": "^1.3.5",
|
||||||
"@storybook/addon-actions": "^6.1.17",
|
"@storybook/addon-actions": "^6.1.17",
|
||||||
"@storybook/addon-essentials": "^6.1.17",
|
"@storybook/addon-essentials": "^6.1.17",
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
"@storybook/react": "^6.1.17",
|
"@storybook/react": "^6.1.17",
|
||||||
"@storybook/theming": "^6.1.17",
|
"@storybook/theming": "^6.1.17",
|
||||||
"@styled-system/css": "^5.1.5",
|
"@styled-system/css": "^5.1.5",
|
||||||
"@typechain/ethers-v5": "^6.0.5",
|
"@typechain/ethers-v5": "^7.0.0",
|
||||||
"@types/jest": "^25.2.1",
|
"@types/jest": "^25.2.1",
|
||||||
"@types/lodash.flatmap": "^4.5.6",
|
"@types/lodash.flatmap": "^4.5.6",
|
||||||
"@types/luxon": "^1.24.4",
|
"@types/luxon": "^1.24.4",
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
"@types/rebass": "^4.0.7",
|
"@types/rebass": "^4.0.7",
|
||||||
"@types/styled-components": "^5.1.0",
|
"@types/styled-components": "^5.1.0",
|
||||||
"@types/testing-library__cypress": "^5.0.5",
|
"@types/testing-library__cypress": "^5.0.5",
|
||||||
|
"@types/ua-parser-js": "^0.7.35",
|
||||||
"@types/wcag-contrast": "^3.0.0",
|
"@types/wcag-contrast": "^3.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.1.0",
|
"@typescript-eslint/eslint-plugin": "^4.1.0",
|
||||||
"@typescript-eslint/parser": "^4.1.0",
|
"@typescript-eslint/parser": "^4.1.0",
|
||||||
@@ -46,16 +48,16 @@
|
|||||||
"@uniswap/token-lists": "^1.0.0-beta.19",
|
"@uniswap/token-lists": "^1.0.0-beta.19",
|
||||||
"@uniswap/v2-core": "1.0.0",
|
"@uniswap/v2-core": "1.0.0",
|
||||||
"@uniswap/v2-periphery": "^1.1.0-beta.0",
|
"@uniswap/v2-periphery": "^1.1.0-beta.0",
|
||||||
"@uniswap/v2-sdk": "^1.0.9",
|
"@uniswap/v2-sdk": "^3.0.0-alpha.0",
|
||||||
"@uniswap/v3-core": "1.0.0",
|
"@uniswap/v3-core": "1.0.0",
|
||||||
"@uniswap/v3-periphery": "1.0.0",
|
"@uniswap/v3-periphery": "1.0.0",
|
||||||
"@uniswap/v3-sdk": "^1.0.3",
|
"@uniswap/v3-sdk": "^3.0.0-alpha.2",
|
||||||
"@web3-react/core": "^6.0.9",
|
"@web3-react/core": "^6.0.9",
|
||||||
"@web3-react/fortmatic-connector": "^6.0.9",
|
"@web3-react/fortmatic-connector": "^6.0.9",
|
||||||
"@web3-react/injected-connector": "^6.0.7",
|
"@web3-react/injected-connector": "^6.0.7",
|
||||||
"@web3-react/portis-connector": "^6.0.9",
|
"@web3-react/portis-connector": "^6.0.9",
|
||||||
"@web3-react/walletconnect-connector": "^6.1.1",
|
"@web3-react/walletconnect-connector": "^6.2.0",
|
||||||
"@web3-react/walletlink-connector": "^6.0.9",
|
"@web3-react/walletlink-connector": "^6.2.0",
|
||||||
"ajv": "^6.12.3",
|
"ajv": "^6.12.3",
|
||||||
"cids": "^1.0.0",
|
"cids": "^1.0.0",
|
||||||
"copy-to-clipboard": "^3.2.0",
|
"copy-to-clipboard": "^3.2.0",
|
||||||
@@ -103,8 +105,9 @@
|
|||||||
"start-server-and-test": "^1.11.0",
|
"start-server-and-test": "^1.11.0",
|
||||||
"styled-components": "^4.2.0",
|
"styled-components": "^4.2.0",
|
||||||
"styled-system": "^5.1.5",
|
"styled-system": "^5.1.5",
|
||||||
"typechain": "^4.0.3",
|
"typechain": "^5.0.0",
|
||||||
"typescript": "^4.2.3",
|
"typescript": "^4.2.3",
|
||||||
|
"ua-parser-js": "^0.7.28",
|
||||||
"use-count-up": "^2.2.5",
|
"use-count-up": "^2.2.5",
|
||||||
"wcag-contrast": "^3.0.0",
|
"wcag-contrast": "^3.0.0",
|
||||||
"workbox-core": "^6.1.0",
|
"workbox-core": "^6.1.0",
|
||||||
@@ -115,8 +118,8 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile-contract-types": "yarn compile-external-abi-types && yarn compile-v3-contract-types",
|
"compile-contract-types": "yarn compile-external-abi-types && yarn compile-v3-contract-types",
|
||||||
"compile-external-abi-types": "npx typechain --target ethers-v5 --outDir src/abis/types './src/abis/**/*.json'",
|
"compile-external-abi-types": "npx typechain --target ethers-v5 --out-dir src/abis/types './src/abis/**/*.json'",
|
||||||
"compile-v3-contract-types": "npx typechain --target ethers-v5 --outDir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
|
"compile-v3-contract-types": "npx typechain --target ethers-v5 --out-dir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
|
||||||
"build": "yarn compile-contract-types && react-scripts build",
|
"build": "yarn compile-contract-types && react-scripts build",
|
||||||
"integration-test": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run'",
|
"integration-test": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run'",
|
||||||
"postinstall": "yarn compile-contract-types",
|
"postinstall": "yarn compile-contract-types",
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 MiB |
BIN
src/assets/images/sandtexture.webp
Normal file
BIN
src/assets/images/sandtexture.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 235 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 2.2 MiB |
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import useCopyClipboard from '../../hooks/useCopyClipboard'
|
import useCopyClipboard from '../../hooks/useCopyClipboard'
|
||||||
|
|
||||||
import { LinkStyledButton } from '../../theme'
|
import { LinkStyledButton } from '../../theme'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { CheckCircle, Triangle } from 'react-feather'
|
import { CheckCircle, Triangle } from 'react-feather'
|
||||||
|
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ const AccountGroupingRow = styled.div`
|
|||||||
`
|
`
|
||||||
|
|
||||||
const AccountSection = styled.div`
|
const AccountSection = styled.div`
|
||||||
background-color: ${({ theme }) => theme.bg1};
|
|
||||||
padding: 0rem 1rem;
|
padding: 0rem 1rem;
|
||||||
${({ theme }) => theme.mediaWidth.upToMedium`padding: 0rem 1rem 1.5rem 1rem;`};
|
${({ theme }) => theme.mediaWidth.upToMedium`padding: 0rem 1rem 1.5rem 1rem;`};
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import Badge, { BadgeVariant } from 'components/Badge'
|
import Badge, { BadgeVariant } from 'components/Badge'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
import { MouseoverTooltip } from '../../components/Tooltip'
|
import { MouseoverTooltip } from '../../components/Tooltip'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@@ -46,7 +46,7 @@ export default function RangeBadge({
|
|||||||
<BadgeWrapper>
|
<BadgeWrapper>
|
||||||
{removed ? (
|
{removed ? (
|
||||||
<MouseoverTooltip text={`Your position has 0 liquidity, and is not earning fees.`}>
|
<MouseoverTooltip text={`Your position has 0 liquidity, and is not earning fees.`}>
|
||||||
<Badge variant={BadgeVariant.WARNING_OUTLINE}>
|
<Badge variant={BadgeVariant.DEFAULT}>
|
||||||
<AlertCircle width={14} height={14} />
|
<AlertCircle width={14} height={14} />
|
||||||
|
|
||||||
<BadgeText>{t('Inactive')}</BadgeText>
|
<BadgeText>{t('Inactive')}</BadgeText>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Story } from '@storybook/react/types-6-0'
|
import { Story } from '@storybook/react/types-6-0'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {
|
import {
|
||||||
ButtonConfirmed,
|
ButtonConfirmed,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
|
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { Box } from 'rebass/styled-components'
|
import { Box } from 'rebass/styled-components'
|
||||||
|
|
||||||
const Card = styled(Box)<{ width?: string; padding?: string; border?: string; borderRadius?: string }>`
|
const Card = styled(Box)<{ width?: string; padding?: string; border?: string; borderRadius?: string }>`
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
const Column = styled.div`
|
const Column = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import { CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||||
import React, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import useTheme from '../../hooks/useTheme'
|
import useTheme from '../../hooks/useTheme'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
import { warningSeverity } from '../../utils/prices'
|
import { warningSeverity } from '../../utils/prices'
|
||||||
|
import HoverInlineText from 'components/HoverInlineText'
|
||||||
|
|
||||||
export function FiatValue({
|
export function FiatValue({
|
||||||
fiatValue,
|
fiatValue,
|
||||||
priceImpact,
|
priceImpact,
|
||||||
}: {
|
}: {
|
||||||
fiatValue: CurrencyAmount | null | undefined
|
fiatValue: CurrencyAmount<Currency> | null | undefined
|
||||||
priceImpact?: Percent
|
priceImpact?: Percent
|
||||||
}) {
|
}) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
@@ -23,9 +24,10 @@ export function FiatValue({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TYPE.body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
|
<TYPE.body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
|
||||||
{fiatValue ? '~' : ''}${fiatValue ? Number(fiatValue?.toSignificant(6)).toLocaleString('en') : '-'}
|
{fiatValue ? '~' : ''}$
|
||||||
|
<HoverInlineText text={fiatValue ? fiatValue?.toSignificant(6, { groupSeparator: ',' }) : '-'} />{' '}
|
||||||
{priceImpact ? (
|
{priceImpact ? (
|
||||||
<span style={{ color: priceImpactColor }}> ({priceImpact.multiply(-100).toSignificant(3)}%)</span>
|
<span style={{ color: priceImpactColor }}> ({priceImpact.multiply(-1).toSignificant(3)}%)</span>
|
||||||
) : null}
|
) : null}
|
||||||
</TYPE.body>
|
</TYPE.body>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Pair } from '@uniswap/v2-sdk'
|
import { Pair } from '@uniswap/v2-sdk'
|
||||||
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
|
||||||
import React, { useState, useCallback } from 'react'
|
import React, { useState, useCallback } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
import { useCurrencyBalance } from '../../state/wallet/hooks'
|
import { useCurrencyBalance } from '../../state/wallet/hooks'
|
||||||
import CurrencySearchModal from '../SearchModal/CurrencySearchModal'
|
import CurrencySearchModal from '../SearchModal/CurrencySearchModal'
|
||||||
@@ -18,6 +18,7 @@ import useTheme from '../../hooks/useTheme'
|
|||||||
import { Lock } from 'react-feather'
|
import { Lock } from 'react-feather'
|
||||||
import { AutoColumn } from 'components/Column'
|
import { AutoColumn } from 'components/Column'
|
||||||
import { FiatValue } from './FiatValue'
|
import { FiatValue } from './FiatValue'
|
||||||
|
import { formatTokenAmount } from 'utils/formatTokenAmount'
|
||||||
|
|
||||||
const InputPanel = styled.div<{ hideInput?: boolean }>`
|
const InputPanel = styled.div<{ hideInput?: boolean }>`
|
||||||
${({ theme }) => theme.flexColumnNoWrap}
|
${({ theme }) => theme.flexColumnNoWrap}
|
||||||
@@ -134,11 +135,7 @@ const StyledBalanceMax = styled.button<{ disabled?: boolean }>`
|
|||||||
pointer-events: ${({ disabled }) => (!disabled ? 'initial' : 'none')};
|
pointer-events: ${({ disabled }) => (!disabled ? 'initial' : 'none')};
|
||||||
margin-left: 0.25rem;
|
margin-left: 0.25rem;
|
||||||
|
|
||||||
:hover {
|
|
||||||
/* border: 1px solid ${({ theme }) => theme.primary1}; */
|
|
||||||
}
|
|
||||||
:focus {
|
:focus {
|
||||||
/* border: 1px solid ${({ theme }) => theme.primary1}; */
|
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +156,7 @@ interface CurrencyInputPanelProps {
|
|||||||
pair?: Pair | null
|
pair?: Pair | null
|
||||||
hideInput?: boolean
|
hideInput?: boolean
|
||||||
otherCurrency?: Currency | null
|
otherCurrency?: Currency | null
|
||||||
fiatValue?: CurrencyAmount | null
|
fiatValue?: CurrencyAmount<Token> | null
|
||||||
priceImpact?: Percent
|
priceImpact?: Percent
|
||||||
id: string
|
id: string
|
||||||
showCommonBases?: boolean
|
showCommonBases?: boolean
|
||||||
@@ -273,7 +270,7 @@ export default function CurrencyInputPanel({
|
|||||||
>
|
>
|
||||||
{!hideBalance && !!currency && selectedCurrencyBalance
|
{!hideBalance && !!currency && selectedCurrencyBalance
|
||||||
? (customBalanceText ?? 'Balance: ') +
|
? (customBalanceText ?? 'Balance: ') +
|
||||||
selectedCurrencyBalance?.toSignificant(4) +
|
formatTokenAmount(selectedCurrencyBalance, 4) +
|
||||||
' ' +
|
' ' +
|
||||||
currency.symbol
|
currency.symbol
|
||||||
: '-'}
|
: '-'}
|
||||||
@@ -285,7 +282,6 @@ export default function CurrencyInputPanel({
|
|||||||
) : (
|
) : (
|
||||||
'-'
|
'-'
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
|
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
</FiatRow>
|
</FiatRow>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { ChainId, Currency, ETHER, Token } from '@uniswap/sdk-core'
|
import { ChainId, Currency } from '@uniswap/sdk-core'
|
||||||
import React, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import EthereumLogo from '../../assets/images/ethereum-logo.png'
|
import EthereumLogo from '../../assets/images/ethereum-logo.png'
|
||||||
import useHttpLocations from '../../hooks/useHttpLocations'
|
import useHttpLocations from '../../hooks/useHttpLocations'
|
||||||
import { WrappedTokenInfo } from '../../state/lists/hooks'
|
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
|
||||||
import Logo from '../Logo'
|
import Logo from '../Logo'
|
||||||
|
|
||||||
export const getTokenLogoURL = (address: string) =>
|
export const getTokenLogoURL = (address: string) =>
|
||||||
@@ -37,9 +37,9 @@ export default function CurrencyLogo({
|
|||||||
const uriLocations = useHttpLocations(currency instanceof WrappedTokenInfo ? currency.logoURI : undefined)
|
const uriLocations = useHttpLocations(currency instanceof WrappedTokenInfo ? currency.logoURI : undefined)
|
||||||
|
|
||||||
const srcs: string[] = useMemo(() => {
|
const srcs: string[] = useMemo(() => {
|
||||||
if (currency === ETHER) return []
|
if (!currency || currency.isEther) return []
|
||||||
|
|
||||||
if (currency instanceof Token) {
|
if (currency.isToken) {
|
||||||
const defaultUrls = currency.chainId === ChainId.MAINNET ? [getTokenLogoURL(currency.address)] : []
|
const defaultUrls = currency.chainId === ChainId.MAINNET ? [getTokenLogoURL(currency.address)] : []
|
||||||
if (currency instanceof WrappedTokenInfo) {
|
if (currency instanceof WrappedTokenInfo) {
|
||||||
return [...uriLocations, ...defaultUrls]
|
return [...uriLocations, ...defaultUrls]
|
||||||
@@ -49,7 +49,7 @@ export default function CurrencyLogo({
|
|||||||
return []
|
return []
|
||||||
}, [currency, uriLocations])
|
}, [currency, uriLocations])
|
||||||
|
|
||||||
if (currency === ETHER) {
|
if (currency?.isEther) {
|
||||||
return <StyledEthereumLogo src={EthereumLogo} size={size} style={style} {...rest} />
|
return <StyledEthereumLogo src={EthereumLogo} size={size} style={style} {...rest} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Currency } from '@uniswap/sdk-core'
|
import { Currency } from '@uniswap/sdk-core'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import CurrencyLogo from '../CurrencyLogo'
|
import CurrencyLogo from '../CurrencyLogo'
|
||||||
|
|
||||||
const Wrapper = styled.div<{ margin: boolean; sizeraw: number }>`
|
const Wrapper = styled.div<{ margin: boolean; sizeraw: number }>`
|
||||||
|
|||||||
182
src/components/ErrorBoundary/index.tsx
Normal file
182
src/components/ErrorBoundary/index.tsx
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
import React, { ErrorInfo } from 'react'
|
||||||
|
import store, { AppState } from '../../state'
|
||||||
|
import { ExternalLink, ThemedBackground, TYPE } from '../../theme'
|
||||||
|
import { AutoColumn } from '../Column'
|
||||||
|
import styled from 'styled-components/macro'
|
||||||
|
import ReactGA from 'react-ga'
|
||||||
|
import { getUserAgent } from '../../utils/getUserAgent'
|
||||||
|
import { AutoRow } from '../Row'
|
||||||
|
|
||||||
|
const FallbackWrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1;
|
||||||
|
`
|
||||||
|
|
||||||
|
const BodyWrapper = styled.div<{ margin?: string }>`
|
||||||
|
padding: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
white-space: ;
|
||||||
|
`
|
||||||
|
|
||||||
|
const CodeBlockWrapper = styled.div`
|
||||||
|
background: ${({ theme }) => theme.bg0};
|
||||||
|
overflow: auto;
|
||||||
|
white-space: pre;
|
||||||
|
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
|
||||||
|
0px 24px 32px rgba(0, 0, 0, 0.01);
|
||||||
|
border-radius: 24px;
|
||||||
|
padding: 18px 24px;
|
||||||
|
color: ${({ theme }) => theme.text1};
|
||||||
|
`
|
||||||
|
|
||||||
|
const LinkWrapper = styled.div`
|
||||||
|
color: ${({ theme }) => theme.blue1};
|
||||||
|
padding: 6px 24px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const SomethingWentWrongWrapper = styled.div`
|
||||||
|
padding: 6px 24px;
|
||||||
|
`
|
||||||
|
|
||||||
|
type ErrorBoundaryState = {
|
||||||
|
error: Error | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ErrorBoundary extends React.Component<unknown, ErrorBoundaryState> {
|
||||||
|
constructor(props: unknown) {
|
||||||
|
super(props)
|
||||||
|
this.state = { error: null }
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
|
||||||
|
return { error }
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
||||||
|
ReactGA.exception({
|
||||||
|
...error,
|
||||||
|
...errorInfo,
|
||||||
|
fatal: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { error } = this.state
|
||||||
|
if (error !== null) {
|
||||||
|
const encodedBody = encodeURIComponent(issueBody(error))
|
||||||
|
return (
|
||||||
|
<FallbackWrapper>
|
||||||
|
<ThemedBackground />
|
||||||
|
<BodyWrapper>
|
||||||
|
<AutoColumn gap={'md'}>
|
||||||
|
<SomethingWentWrongWrapper>
|
||||||
|
<TYPE.label fontSize={24} fontWeight={600}>
|
||||||
|
Something went wrong
|
||||||
|
</TYPE.label>
|
||||||
|
</SomethingWentWrongWrapper>
|
||||||
|
<CodeBlockWrapper>
|
||||||
|
<code>
|
||||||
|
<TYPE.main fontSize={10}>{error.stack}</TYPE.main>
|
||||||
|
</code>
|
||||||
|
</CodeBlockWrapper>
|
||||||
|
<AutoRow>
|
||||||
|
<LinkWrapper>
|
||||||
|
<ExternalLink
|
||||||
|
id="create-github-issue-link"
|
||||||
|
href={`https://github.com/Uniswap/uniswap-interface/issues/new?assignees=&labels=bug&body=${encodedBody}&title=${encodeURIComponent(
|
||||||
|
`Crash report: \`${error.name}${error.message && `: ${error.message}`}\``
|
||||||
|
)}`}
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<TYPE.link fontSize={16}>
|
||||||
|
Create an issue on GitHub
|
||||||
|
<span>↗</span>
|
||||||
|
</TYPE.link>
|
||||||
|
</ExternalLink>
|
||||||
|
</LinkWrapper>
|
||||||
|
<LinkWrapper>
|
||||||
|
<ExternalLink id="get-support-on-discord" href="https://discord.gg/FCfyBSbCU5" target="_blank">
|
||||||
|
<TYPE.link fontSize={16}>
|
||||||
|
Get support on Discord
|
||||||
|
<span>↗</span>
|
||||||
|
</TYPE.link>
|
||||||
|
</ExternalLink>
|
||||||
|
</LinkWrapper>
|
||||||
|
</AutoRow>
|
||||||
|
</AutoColumn>
|
||||||
|
</BodyWrapper>
|
||||||
|
</FallbackWrapper>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return this.props.children
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRelevantState(): null | keyof AppState {
|
||||||
|
const path = window.location.hash
|
||||||
|
if (!path.startsWith('#/')) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const pieces = path.substring(2).split(/[\/\\?]/)
|
||||||
|
switch (pieces[0]) {
|
||||||
|
case 'swap':
|
||||||
|
return 'swap'
|
||||||
|
case 'add':
|
||||||
|
if (pieces[1] === 'v2') return 'mint'
|
||||||
|
else return 'mintV3'
|
||||||
|
case 'remove':
|
||||||
|
if (pieces[1] === 'v2') return 'burn'
|
||||||
|
else return 'burnV3'
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
function issueBody(error: Error): string {
|
||||||
|
const relevantState = getRelevantState()
|
||||||
|
const deviceData = getUserAgent()
|
||||||
|
return `## URL
|
||||||
|
|
||||||
|
${window.location.href}
|
||||||
|
|
||||||
|
${
|
||||||
|
relevantState
|
||||||
|
? `## \`${relevantState}\` state
|
||||||
|
|
||||||
|
\`\`\`json
|
||||||
|
${JSON.stringify(store.getState()[relevantState], null, 2)}
|
||||||
|
\`\`\`
|
||||||
|
`
|
||||||
|
: ''
|
||||||
|
}
|
||||||
|
${
|
||||||
|
error.name &&
|
||||||
|
`## Error
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
${error.name}${error.message && `: ${error.message}`}
|
||||||
|
\`\`\`
|
||||||
|
`
|
||||||
|
}
|
||||||
|
${
|
||||||
|
error.stack &&
|
||||||
|
`## Stacktrace
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
${error.stack}
|
||||||
|
\`\`\`
|
||||||
|
`
|
||||||
|
}
|
||||||
|
${
|
||||||
|
deviceData &&
|
||||||
|
`## Device data
|
||||||
|
|
||||||
|
\`\`\`json
|
||||||
|
${JSON.stringify(deviceData, null, 2)}
|
||||||
|
\`\`\`
|
||||||
|
`
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ import { DynamicSection } from 'pages/AddLiquidity/styled'
|
|||||||
import { TYPE } from 'theme'
|
import { TYPE } from 'theme'
|
||||||
import { RowBetween } from 'components/Row'
|
import { RowBetween } from 'components/Row'
|
||||||
import { ButtonRadioChecked } from 'components/Button'
|
import { ButtonRadioChecked } from 'components/Button'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
const ResponsiveText = styled(TYPE.label)`
|
const ResponsiveText = styled(TYPE.label)`
|
||||||
${({ theme }) => theme.mediaWidth.upToSmall`
|
${({ theme }) => theme.mediaWidth.upToSmall`
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import JSBI from 'jsbi'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { CurrencyAmount, Fraction } from '@uniswap/sdk-core'
|
import { Currency, CurrencyAmount, Fraction } from '@uniswap/sdk-core'
|
||||||
import { JSBI } from '@uniswap/v2-sdk'
|
|
||||||
|
|
||||||
const CURRENCY_AMOUNT_MIN = new Fraction(JSBI.BigInt(1), JSBI.BigInt(1000000))
|
const CURRENCY_AMOUNT_MIN = new Fraction(JSBI.BigInt(1), JSBI.BigInt(1000000))
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ export default function FormattedCurrencyAmount({
|
|||||||
currencyAmount,
|
currencyAmount,
|
||||||
significantDigits = 4,
|
significantDigits = 4,
|
||||||
}: {
|
}: {
|
||||||
currencyAmount: CurrencyAmount
|
currencyAmount: CurrencyAmount<Currency>
|
||||||
significantDigits?: number
|
significantDigits?: number
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
import { AlertTriangle, X } from 'react-feather'
|
import { AlertTriangle, X } from 'react-feather'
|
||||||
import { useURLWarningToggle, useURLWarningVisible } from '../../state/user/hooks'
|
import { useURLWarningToggle, useURLWarningVisible } from '../../state/user/hooks'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ChainId, TokenAmount } from '@uniswap/sdk-core'
|
import { ChainId, CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
import React, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import { X } from 'react-feather'
|
import { X } from 'react-feather'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import tokenLogo from '../../assets/images/token-logo.png'
|
import tokenLogo from '../../assets/images/token-logo.png'
|
||||||
import { UNI } from '../../constants'
|
import { UNI } from '../../constants'
|
||||||
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||||
@@ -45,14 +45,14 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
|
|||||||
const uni = chainId ? UNI[chainId] : undefined
|
const uni = chainId ? UNI[chainId] : undefined
|
||||||
|
|
||||||
const total = useAggregateUniBalance()
|
const total = useAggregateUniBalance()
|
||||||
const uniBalance: TokenAmount | undefined = useTokenBalance(account ?? undefined, uni)
|
const uniBalance: CurrencyAmount<Token> | undefined = useTokenBalance(account ?? undefined, uni)
|
||||||
const uniToClaim: TokenAmount | undefined = useTotalUniEarned()
|
const uniToClaim: CurrencyAmount<Token> | undefined = useTotalUniEarned()
|
||||||
|
|
||||||
const totalSupply: TokenAmount | undefined = useTotalSupply(uni)
|
const totalSupply: CurrencyAmount<Token> | undefined = useTotalSupply(uni)
|
||||||
const uniPrice = useUSDCPrice(uni)
|
const uniPrice = useUSDCPrice(uni)
|
||||||
const blockTimestamp = useCurrentBlockTimestamp()
|
const blockTimestamp = useCurrentBlockTimestamp()
|
||||||
const unclaimedUni = useTokenBalance(useMerkleDistributorContract()?.address, uni)
|
const unclaimedUni = useTokenBalance(useMerkleDistributorContract()?.address, uni)
|
||||||
const circulation: TokenAmount | undefined = useMemo(
|
const circulation: CurrencyAmount<Token> | undefined = useMemo(
|
||||||
() =>
|
() =>
|
||||||
blockTimestamp && uni && chainId === ChainId.MAINNET
|
blockTimestamp && uni && chainId === ChainId.MAINNET
|
||||||
? computeUniCirculation(uni, blockTimestamp, unclaimedUni)
|
? computeUniCirculation(uni, blockTimestamp, unclaimedUni)
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { ChainId } from '@uniswap/sdk-core'
|
import { ChainId } from '@uniswap/sdk-core'
|
||||||
|
import useScrollPosition from '@react-hook/window-scroll'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Moon, Sun } from 'react-feather'
|
import { Moon, Sun } from 'react-feather'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
import Logo from '../../assets/svg/logo.svg'
|
import Logo from '../../assets/svg/logo.svg'
|
||||||
import LogoDark from '../../assets/svg/logo_white.svg'
|
import LogoDark from '../../assets/svg/logo_white.svg'
|
||||||
@@ -29,7 +30,7 @@ import { Dots } from '../swap/styleds'
|
|||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import UniBalanceContent from './UniBalanceContent'
|
import UniBalanceContent from './UniBalanceContent'
|
||||||
|
|
||||||
const HeaderFrame = styled.div`
|
const HeaderFrame = styled.div<{ showBackground: boolean }>`
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 120px 1fr 120px;
|
grid-template-columns: 120px 1fr 120px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -39,12 +40,17 @@ const HeaderFrame = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
top: 0;
|
top: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
/* border-bottom: 1px solid ${({ theme }) => theme.bg2}; */
|
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
z-index: 21;
|
z-index: 21;
|
||||||
/* background-color: ${({ theme }) => theme.bg1}; */
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
/* Background slide effect on scroll. */
|
||||||
|
background-image: ${({ theme }) => `linear-gradient(to bottom, transparent 50%, ${theme.bg0} 50% )}}`}
|
||||||
|
background-position: ${({ showBackground }) => (showBackground ? '0 -100%' : '0 0')};
|
||||||
|
background-size: 100% 200%;
|
||||||
|
box-shadow: 0px 0px 0px 1px ${({ theme, showBackground }) => (showBackground ? theme.bg2 : 'transparent;')};
|
||||||
|
transition: background-position .1s, box-shadow .1s;
|
||||||
|
|
||||||
${({ theme }) => theme.mediaWidth.upToMedium`
|
${({ theme }) => theme.mediaWidth.upToMedium`
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
grid-template-columns: 120px 1fr;
|
grid-template-columns: 120px 1fr;
|
||||||
@@ -90,7 +96,7 @@ const HeaderElement = styled.div`
|
|||||||
}
|
}
|
||||||
|
|
||||||
${({ theme }) => theme.mediaWidth.upToMedium`
|
${({ theme }) => theme.mediaWidth.upToMedium`
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
`};
|
`};
|
||||||
`
|
`
|
||||||
@@ -116,6 +122,9 @@ const HeaderLinks = styled(Row)`
|
|||||||
grid-auto-flow: column;
|
grid-auto-flow: column;
|
||||||
grid-gap: 10px;
|
grid-gap: 10px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
${({ theme }) => theme.mediaWidth.upToMedium`
|
||||||
|
justify-self: flex-end;
|
||||||
|
`};
|
||||||
`
|
`
|
||||||
|
|
||||||
const AccountElement = styled.div<{ active: boolean }>`
|
const AccountElement = styled.div<{ active: boolean }>`
|
||||||
@@ -316,8 +325,10 @@ export default function Header() {
|
|||||||
const [showUniBalanceModal, setShowUniBalanceModal] = useState(false)
|
const [showUniBalanceModal, setShowUniBalanceModal] = useState(false)
|
||||||
const showClaimPopup = useShowClaimPopup()
|
const showClaimPopup = useShowClaimPopup()
|
||||||
|
|
||||||
|
const scrollY = useScrollPosition()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HeaderFrame>
|
<HeaderFrame showBackground={scrollY > 45}>
|
||||||
<ClaimModal />
|
<ClaimModal />
|
||||||
<Modal isOpen={showUniBalanceModal} onDismiss={() => setShowUniBalanceModal(false)}>
|
<Modal isOpen={showUniBalanceModal} onDismiss={() => setShowUniBalanceModal(false)}>
|
||||||
<UniBalanceContent setShowUniBalanceModal={setShowUniBalanceModal} />
|
<UniBalanceContent setShowUniBalanceModal={setShowUniBalanceModal} />
|
||||||
|
|||||||
63
src/components/HoverInlineText/index.tsx
Normal file
63
src/components/HoverInlineText/index.tsx
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import Tooltip from 'components/Tooltip'
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
|
const TextWrapper = styled.span<{ margin: boolean; link?: boolean; fontSize?: string; adjustSize?: boolean }>`
|
||||||
|
cursor: auto;
|
||||||
|
margin-left: ${({ margin }) => margin && '4px'};
|
||||||
|
color: ${({ theme, link }) => (link ? theme.blue1 : theme.text1)};
|
||||||
|
font-size: ${({ fontSize }) => fontSize ?? 'inherit'};
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
font-size: ${({ adjustSize }) => adjustSize && '12px'};
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const HoverInlineText = ({
|
||||||
|
text,
|
||||||
|
maxCharacters = 20,
|
||||||
|
margin = false,
|
||||||
|
adjustSize = false,
|
||||||
|
fontSize,
|
||||||
|
link,
|
||||||
|
...rest
|
||||||
|
}: {
|
||||||
|
text: string
|
||||||
|
maxCharacters?: number
|
||||||
|
margin?: boolean
|
||||||
|
adjustSize?: boolean
|
||||||
|
fontSize?: string
|
||||||
|
link?: boolean
|
||||||
|
}) => {
|
||||||
|
const [showHover, setShowHover] = useState(false)
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
return <span />
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.length > maxCharacters) {
|
||||||
|
return (
|
||||||
|
<Tooltip text={text} show={showHover}>
|
||||||
|
<TextWrapper
|
||||||
|
onMouseEnter={() => setShowHover(true)}
|
||||||
|
onMouseLeave={() => setShowHover(false)}
|
||||||
|
margin={margin}
|
||||||
|
adjustSize={adjustSize}
|
||||||
|
link={link}
|
||||||
|
fontSize={fontSize}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{' ' + text.slice(0, maxCharacters - 1) + '...'}
|
||||||
|
</TextWrapper>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TextWrapper margin={margin} adjustSize={adjustSize} link={link} fontSize={fontSize} {...rest}>
|
||||||
|
{text}
|
||||||
|
</TextWrapper>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HoverInlineText
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useEffect, useRef } from 'react'
|
import React, { useEffect, useRef } from 'react'
|
||||||
|
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
import Jazzicon from 'jazzicon'
|
import Jazzicon from 'jazzicon'
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ const StepCounter = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<InputTitle fontSize={12} textAlign="center">
|
<InputTitle fontSize={12} textAlign="center">
|
||||||
{tokenB + ' / ' + tokenA}
|
{tokenB + ' per ' + tokenA}
|
||||||
</InputTitle>
|
</InputTitle>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
{!locked ? (
|
{!locked ? (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Story } from '@storybook/react/types-6-0'
|
import { Story } from '@storybook/react/types-6-0'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
// import Row, { RowFixed } from 'components/Row'
|
// import Row, { RowFixed } from 'components/Row'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import Component, { LineChartProps } from './'
|
import Component, { LineChartProps } from './'
|
||||||
import { dummyData } from './data'
|
import { dummyData } from './data'
|
||||||
// import { AutoColumn } from 'components/Column'
|
// import { AutoColumn } from 'components/Column'
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { createChart, IChartApi } from 'lightweight-charts'
|
|||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
import { RowBetween } from 'components/Row'
|
import { RowBetween } from 'components/Row'
|
||||||
import Card from '../Card'
|
import Card from '../Card'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import useTheme from 'hooks/useTheme'
|
import useTheme from 'hooks/useTheme'
|
||||||
|
|
||||||
const Wrapper = styled(Card)`
|
const Wrapper = styled(Card)`
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import useHttpLocations from '../../hooks/useHttpLocations'
|
import useHttpLocations from '../../hooks/useHttpLocations'
|
||||||
|
|
||||||
import Logo from '../Logo'
|
import Logo from '../Logo'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Story } from '@storybook/react/types-6-0'
|
import { Story } from '@storybook/react/types-6-0'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import Component from './index'
|
import Component from './index'
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { NavLink, Link as HistoryLink } from 'react-router-dom'
|
import { NavLink, Link as HistoryLink } from 'react-router-dom'
|
||||||
|
import { Percent } from '@uniswap/sdk-core'
|
||||||
|
|
||||||
import { ArrowLeft } from 'react-feather'
|
import { ArrowLeft } from 'react-feather'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
import Settings from '../Settings'
|
import SettingsTab from '../Settings'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
import { AppDispatch } from 'state'
|
import { AppDispatch } from 'state'
|
||||||
import { resetMintState } from 'state/mint/actions'
|
import { resetMintState } from 'state/mint/actions'
|
||||||
@@ -80,7 +81,6 @@ export function FindPoolTabs({ origin }: { origin: string }) {
|
|||||||
<StyledArrowLeft />
|
<StyledArrowLeft />
|
||||||
</HistoryLink>
|
</HistoryLink>
|
||||||
<ActiveText>Import Pool</ActiveText>
|
<ActiveText>Import Pool</ActiveText>
|
||||||
<Settings />
|
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
)
|
)
|
||||||
@@ -90,10 +90,12 @@ export function AddRemoveTabs({
|
|||||||
adding,
|
adding,
|
||||||
creating,
|
creating,
|
||||||
positionID,
|
positionID,
|
||||||
|
defaultSlippage,
|
||||||
}: {
|
}: {
|
||||||
adding: boolean
|
adding: boolean
|
||||||
creating: boolean
|
creating: boolean
|
||||||
positionID?: string | undefined
|
positionID?: string | undefined
|
||||||
|
defaultSlippage: Percent
|
||||||
}) {
|
}) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
@@ -118,7 +120,7 @@ export function AddRemoveTabs({
|
|||||||
<TYPE.mediumHeader fontWeight={500} fontSize={20}>
|
<TYPE.mediumHeader fontWeight={500} fontSize={20}>
|
||||||
{creating ? 'Create a pair' : adding ? 'Add Liquidity' : 'Remove Liquidity'}
|
{creating ? 'Create a pair' : adding ? 'Add Liquidity' : 'Remove Liquidity'}
|
||||||
</TYPE.mediumHeader>
|
</TYPE.mediumHeader>
|
||||||
<Settings />
|
<SettingsTab placeholderSlippage={defaultSlippage} />
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { escapeRegExp } from '../../utils'
|
import { escapeRegExp } from '../../utils'
|
||||||
|
|
||||||
const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: string }>`
|
const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: string }>`
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Placement } from '@popperjs/core'
|
|||||||
import { transparentize } from 'polished'
|
import { transparentize } from 'polished'
|
||||||
import React, { useCallback, useState } from 'react'
|
import React, { useCallback, useState } from 'react'
|
||||||
import { usePopper } from 'react-popper'
|
import { usePopper } from 'react-popper'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import useInterval from '../../hooks/useInterval'
|
import useInterval from '../../hooks/useInterval'
|
||||||
import Portal from '@reach/portal'
|
import Portal from '@reach/portal'
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { TokenAmount } from '@uniswap/sdk-core'
|
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { X } from 'react-feather'
|
import { X } from 'react-feather'
|
||||||
import styled, { keyframes } from 'styled-components'
|
import styled, { keyframes } from 'styled-components'
|
||||||
@@ -65,7 +65,7 @@ export default function ClaimPopup() {
|
|||||||
|
|
||||||
// const userHasAvailableclaim = useUserHasAvailableClaim()
|
// const userHasAvailableclaim = useUserHasAvailableClaim()
|
||||||
const userHasAvailableclaim: boolean = useUserHasAvailableClaim(account)
|
const userHasAvailableclaim: boolean = useUserHasAvailableClaim(account)
|
||||||
const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
|
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(account)
|
||||||
|
|
||||||
// listen for available claim and show popup if needed
|
// listen for available claim and show popup if needed
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { useCallback, useMemo } from 'react'
|
|||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { AppDispatch } from '../../state'
|
import { AppDispatch } from '../../state'
|
||||||
import { useRemovePopup } from '../../state/application/hooks'
|
import { useRemovePopup } from '../../state/application/hooks'
|
||||||
import { acceptListUpdate } from '../../state/lists/actions'
|
import { acceptListUpdate } from '../../state/lists/actions'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { useActivePopups } from '../../state/application/hooks'
|
import { useActivePopups } from '../../state/application/hooks'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import PopupItem from './PopupItem'
|
import PopupItem from './PopupItem'
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React from 'react'
|
|||||||
import { Token } from '@uniswap/sdk-core'
|
import { Token } from '@uniswap/sdk-core'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
import { unwrappedToken } from '../../utils/wrappedCurrency'
|
import { unwrappedToken } from '../../utils/wrappedCurrency'
|
||||||
import { ButtonEmpty } from '../Button'
|
import { ButtonEmpty } from '../Button'
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
import JSBI from 'jsbi'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Percent, TokenAmount } from '@uniswap/sdk-core'
|
import { Percent, CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
import { JSBI, Pair } from '@uniswap/v2-sdk'
|
import { Pair } from '@uniswap/v2-sdk'
|
||||||
import { ChevronDown, ChevronUp } from 'react-feather'
|
import { ChevronDown, ChevronUp } from 'react-feather'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||||
|
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
@@ -38,7 +39,7 @@ interface PositionCardProps {
|
|||||||
pair: Pair
|
pair: Pair
|
||||||
showUnwrapped?: boolean
|
showUnwrapped?: boolean
|
||||||
border?: string
|
border?: string
|
||||||
stakedBalance?: TokenAmount // optional balance to indicate that liquidity is deposited in mining pool
|
stakedBalance?: CurrencyAmount<Token> // optional balance to indicate that liquidity is deposited in mining pool
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function V2PositionCard({ pair, border, stakedBalance }: PositionCardProps) {
|
export default function V2PositionCard({ pair, border, stakedBalance }: PositionCardProps) {
|
||||||
@@ -56,8 +57,10 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
|
|||||||
const userPoolBalance = stakedBalance ? userDefaultPoolBalance?.add(stakedBalance) : userDefaultPoolBalance
|
const userPoolBalance = stakedBalance ? userDefaultPoolBalance?.add(stakedBalance) : userDefaultPoolBalance
|
||||||
|
|
||||||
const poolTokenPercentage =
|
const poolTokenPercentage =
|
||||||
!!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
|
!!userPoolBalance &&
|
||||||
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
|
!!totalPoolTokens &&
|
||||||
|
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
|
||||||
|
? new Percent(userPoolBalance.quotient, totalPoolTokens.quotient)
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
const [token0Deposited, token1Deposited] =
|
const [token0Deposited, token1Deposited] =
|
||||||
@@ -65,7 +68,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
|
|||||||
!!totalPoolTokens &&
|
!!totalPoolTokens &&
|
||||||
!!userPoolBalance &&
|
!!userPoolBalance &&
|
||||||
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
|
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
|
||||||
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
|
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
|
||||||
? [
|
? [
|
||||||
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
|
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
|
||||||
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
|
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
|
||||||
@@ -174,7 +177,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
|
|||||||
</Text>
|
</Text>
|
||||||
</FixedHeightRow>
|
</FixedHeightRow>
|
||||||
|
|
||||||
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.raw, BIG_INT_ZERO) && (
|
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.quotient, BIG_INT_ZERO) && (
|
||||||
<RowBetween marginTop="10px">
|
<RowBetween marginTop="10px">
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
padding="8px"
|
padding="8px"
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { Percent, TokenAmount } from '@uniswap/sdk-core'
|
import JSBI from 'jsbi'
|
||||||
import { JSBI, Pair } from '@uniswap/v2-sdk'
|
import { Percent, CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
|
import { Pair } from '@uniswap/v2-sdk'
|
||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { ChevronDown, ChevronUp } from 'react-feather'
|
import { ChevronDown, ChevronUp } from 'react-feather'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
import { useTotalSupply } from '../../hooks/useTotalSupply'
|
||||||
|
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
@@ -49,7 +50,7 @@ interface PositionCardProps {
|
|||||||
pair: Pair
|
pair: Pair
|
||||||
showUnwrapped?: boolean
|
showUnwrapped?: boolean
|
||||||
border?: string
|
border?: string
|
||||||
stakedBalance?: TokenAmount // optional balance to indicate that liquidity is deposited in mining pool
|
stakedBalance?: CurrencyAmount<Token> // optional balance to indicate that liquidity is deposited in mining pool
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MinimalPositionCard({ pair, showUnwrapped = false, border }: PositionCardProps) {
|
export function MinimalPositionCard({ pair, showUnwrapped = false, border }: PositionCardProps) {
|
||||||
@@ -64,8 +65,10 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
|
|||||||
const totalPoolTokens = useTotalSupply(pair.liquidityToken)
|
const totalPoolTokens = useTotalSupply(pair.liquidityToken)
|
||||||
|
|
||||||
const poolTokenPercentage =
|
const poolTokenPercentage =
|
||||||
!!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
|
!!userPoolBalance &&
|
||||||
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
|
!!totalPoolTokens &&
|
||||||
|
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
|
||||||
|
? new Percent(userPoolBalance.quotient, totalPoolTokens.quotient)
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
const [token0Deposited, token1Deposited] =
|
const [token0Deposited, token1Deposited] =
|
||||||
@@ -73,7 +76,7 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
|
|||||||
!!totalPoolTokens &&
|
!!totalPoolTokens &&
|
||||||
!!userPoolBalance &&
|
!!userPoolBalance &&
|
||||||
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
|
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
|
||||||
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
|
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
|
||||||
? [
|
? [
|
||||||
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
|
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
|
||||||
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
|
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
|
||||||
@@ -82,7 +85,7 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{userPoolBalance && JSBI.greaterThan(userPoolBalance.raw, JSBI.BigInt(0)) ? (
|
{userPoolBalance && JSBI.greaterThan(userPoolBalance.quotient, JSBI.BigInt(0)) ? (
|
||||||
<GreyCard border={border}>
|
<GreyCard border={border}>
|
||||||
<AutoColumn gap="12px">
|
<AutoColumn gap="12px">
|
||||||
<FixedHeightRow>
|
<FixedHeightRow>
|
||||||
@@ -175,8 +178,10 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
|
|||||||
const userPoolBalance = stakedBalance ? userDefaultPoolBalance?.add(stakedBalance) : userDefaultPoolBalance
|
const userPoolBalance = stakedBalance ? userDefaultPoolBalance?.add(stakedBalance) : userDefaultPoolBalance
|
||||||
|
|
||||||
const poolTokenPercentage =
|
const poolTokenPercentage =
|
||||||
!!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
|
!!userPoolBalance &&
|
||||||
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
|
!!totalPoolTokens &&
|
||||||
|
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
|
||||||
|
? new Percent(userPoolBalance.quotient, totalPoolTokens.quotient)
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
const [token0Deposited, token1Deposited] =
|
const [token0Deposited, token1Deposited] =
|
||||||
@@ -184,7 +189,7 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
|
|||||||
!!totalPoolTokens &&
|
!!totalPoolTokens &&
|
||||||
!!userPoolBalance &&
|
!!userPoolBalance &&
|
||||||
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
|
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
|
||||||
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
|
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
|
||||||
? [
|
? [
|
||||||
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
|
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
|
||||||
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
|
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
|
||||||
@@ -198,28 +203,23 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
|
|||||||
<CardNoise />
|
<CardNoise />
|
||||||
<AutoColumn gap="12px">
|
<AutoColumn gap="12px">
|
||||||
<FixedHeightRow>
|
<FixedHeightRow>
|
||||||
<AutoRow gap="8px">
|
<AutoRow gap="8px" style={{ marginLeft: '8px' }}>
|
||||||
<DoubleCurrencyLogo currency0={currency0} currency1={currency1} size={20} />
|
<DoubleCurrencyLogo currency0={currency0} currency1={currency1} size={20} />
|
||||||
<Text fontWeight={500} fontSize={20}>
|
<Text fontWeight={500} fontSize={20}>
|
||||||
{!currency0 || !currency1 ? <Dots>Loading</Dots> : `${currency0.symbol}/${currency1.symbol}`}
|
{!currency0 || !currency1 ? <Dots>Loading</Dots> : `${currency0.symbol}/${currency1.symbol}`}
|
||||||
</Text>
|
</Text>
|
||||||
</AutoRow>
|
</AutoRow>
|
||||||
<RowFixed gap="8px">
|
<RowFixed gap="8px" style={{ marginRight: '4px' }}>
|
||||||
<ButtonEmpty
|
<ButtonEmpty padding="6px 8px" borderRadius="12px" width="100%" onClick={() => setShowMore(!showMore)}>
|
||||||
padding="6px 8px"
|
|
||||||
borderRadius="12px"
|
|
||||||
width="fit-content"
|
|
||||||
onClick={() => setShowMore(!showMore)}
|
|
||||||
>
|
|
||||||
{showMore ? (
|
{showMore ? (
|
||||||
<>
|
<>
|
||||||
Manage
|
Manage
|
||||||
<ChevronUp size="20" style={{ marginLeft: '10px' }} />
|
<ChevronUp size="20" style={{ marginLeft: '8px', height: '20px', minWidth: '20px' }} />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
Manage
|
Manage
|
||||||
<ChevronDown size="20" style={{ marginLeft: '10px' }} />
|
<ChevronDown size="20" style={{ marginLeft: '8px', height: '20px', minWidth: '20px' }} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</ButtonEmpty>
|
</ButtonEmpty>
|
||||||
@@ -301,14 +301,23 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
|
|||||||
View accrued fees and analytics<span style={{ fontSize: '11px' }}>↗</span>
|
View accrued fees and analytics<span style={{ fontSize: '11px' }}>↗</span>
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
</ButtonSecondary>
|
</ButtonSecondary>
|
||||||
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.raw, BIG_INT_ZERO) && (
|
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.quotient, BIG_INT_ZERO) && (
|
||||||
<RowBetween marginTop="10px">
|
<RowBetween marginTop="10px">
|
||||||
|
<ButtonPrimary
|
||||||
|
padding="8px"
|
||||||
|
borderRadius="8px"
|
||||||
|
as={Link}
|
||||||
|
to={`/migrate/v2/${pair.liquidityToken.address}`}
|
||||||
|
width="32%"
|
||||||
|
>
|
||||||
|
Migrate
|
||||||
|
</ButtonPrimary>
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
padding="8px"
|
padding="8px"
|
||||||
borderRadius="8px"
|
borderRadius="8px"
|
||||||
as={Link}
|
as={Link}
|
||||||
to={`/add/v2/${currencyId(currency0)}/${currencyId(currency1)}`}
|
to={`/add/v2/${currencyId(currency0)}/${currencyId(currency1)}`}
|
||||||
width="48%"
|
width="32%"
|
||||||
>
|
>
|
||||||
Add
|
Add
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
@@ -316,14 +325,14 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
|
|||||||
padding="8px"
|
padding="8px"
|
||||||
borderRadius="8px"
|
borderRadius="8px"
|
||||||
as={Link}
|
as={Link}
|
||||||
width="48%"
|
width="32%"
|
||||||
to={`/remove/v2/${currencyId(currency0)}/${currencyId(currency1)}`}
|
to={`/remove/v2/${currencyId(currency0)}/${currencyId(currency1)}`}
|
||||||
>
|
>
|
||||||
Remove
|
Remove
|
||||||
</ButtonPrimary>
|
</ButtonPrimary>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
)}
|
)}
|
||||||
{stakedBalance && JSBI.greaterThan(stakedBalance.raw, BIG_INT_ZERO) && (
|
{stakedBalance && JSBI.greaterThan(stakedBalance.quotient, BIG_INT_ZERO) && (
|
||||||
<ButtonPrimary
|
<ButtonPrimary
|
||||||
padding="8px"
|
padding="8px"
|
||||||
borderRadius="8px"
|
borderRadius="8px"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// import { basisPointsToPercent } from 'utils'
|
// import { basisPointsToPercent } from 'utils'
|
||||||
// import { DAI, WBTC } from '../../constants'
|
// import { DAI, WBTC } from '../../constants'
|
||||||
// import Component, { PositionListProps } from './index'
|
// import Component, { PositionListProps } from './index'
|
||||||
// import { TokenAmount } from '@uniswap/sdk-core'
|
// import { CurrencyAmount } from '@uniswap/sdk-core'
|
||||||
// import JSBI from 'jsbi'
|
// import JSBI from 'jsbi'
|
||||||
|
|
||||||
// const FEE_BIPS = {
|
// const FEE_BIPS = {
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
// THIRTY: basisPointsToPercent(30),
|
// THIRTY: basisPointsToPercent(30),
|
||||||
// ONE_HUNDRED: basisPointsToPercent(100),
|
// ONE_HUNDRED: basisPointsToPercent(100),
|
||||||
// }
|
// }
|
||||||
// const daiAmount = new TokenAmount(DAI, JSBI.BigInt(500 * 10 ** 18))
|
// const daiAmount = CurrencyAmount.fromRawAmount(DAI, JSBI.BigInt(500 * 10 ** 18))
|
||||||
// const wbtcAmount = new TokenAmount(WBTC, JSBI.BigInt(10 ** 7))
|
// const wbtcAmount = CurrencyAmount.fromRawAmount(WBTC, JSBI.BigInt(10 ** 7))
|
||||||
// const positions = [
|
// const positions = [
|
||||||
// {
|
// {
|
||||||
// feesEarned: {
|
// feesEarned: {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import PositionListItem from 'components/PositionListItem'
|
import PositionListItem from 'components/PositionListItem'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { MEDIA_WIDTHS } from 'theme'
|
import { MEDIA_WIDTHS } from 'theme'
|
||||||
import { PositionDetails } from 'types/position'
|
import { PositionDetails } from 'types/position'
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import DoubleCurrencyLogo from 'components/DoubleLogo'
|
|||||||
import { usePool } from 'hooks/usePools'
|
import { usePool } from 'hooks/usePools'
|
||||||
import { useToken } from 'hooks/Tokens'
|
import { useToken } from 'hooks/Tokens'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { HideSmall, MEDIA_WIDTHS, SmallOnly } from 'theme'
|
import { HideSmall, MEDIA_WIDTHS, SmallOnly } from 'theme'
|
||||||
import { PositionDetails } from 'types/position'
|
import { PositionDetails } from 'types/position'
|
||||||
import { WETH9, Price, Token, Percent } from '@uniswap/sdk-core'
|
import { WETH9, Price, Token, Percent } from '@uniswap/sdk-core'
|
||||||
@@ -15,6 +15,7 @@ import { unwrappedToken } from 'utils/wrappedCurrency'
|
|||||||
import { DAI, USDC, USDT, WBTC } from '../../constants'
|
import { DAI, USDC, USDT, WBTC } from '../../constants'
|
||||||
import RangeBadge from 'components/Badge/RangeBadge'
|
import RangeBadge from 'components/Badge/RangeBadge'
|
||||||
import { RowFixed } from 'components/Row'
|
import { RowFixed } from 'components/Row'
|
||||||
|
import HoverInlineText from 'components/HoverInlineText'
|
||||||
|
|
||||||
const Row = styled(Link)`
|
const Row = styled(Link)`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -120,8 +121,8 @@ export interface PositionListItemProps {
|
|||||||
export function getPriceOrderingFromPositionForUI(
|
export function getPriceOrderingFromPositionForUI(
|
||||||
position?: Position
|
position?: Position
|
||||||
): {
|
): {
|
||||||
priceLower?: Price
|
priceLower?: Price<Token, Token>
|
||||||
priceUpper?: Price
|
priceUpper?: Price<Token, Token>
|
||||||
quote?: Token
|
quote?: Token
|
||||||
base?: Token
|
base?: Token
|
||||||
} {
|
} {
|
||||||
@@ -129,8 +130,8 @@ export function getPriceOrderingFromPositionForUI(
|
|||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const token0 = position.amount0.token
|
const token0 = position.amount0.currency
|
||||||
const token1 = position.amount1.token
|
const token1 = position.amount1.currency
|
||||||
|
|
||||||
// if token0 is a dollar-stable asset, set it as the quote token
|
// if token0 is a dollar-stable asset, set it as the quote token
|
||||||
const stables = [DAI, USDC, USDT]
|
const stables = [DAI, USDC, USDT]
|
||||||
@@ -244,8 +245,10 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
|
|||||||
>
|
>
|
||||||
<RangeText>
|
<RangeText>
|
||||||
<ExtentsText>Min: </ExtentsText>
|
<ExtentsText>Min: </ExtentsText>
|
||||||
{formatPrice(priceLower, 4)} {manuallyInverted ? currencyQuote?.symbol : currencyBase?.symbol} {' / '}{' '}
|
{formatPrice(priceLower, 5)}{' '}
|
||||||
{manuallyInverted ? currencyBase?.symbol : currencyQuote?.symbol}
|
<HoverInlineText text={manuallyInverted ? currencyQuote?.symbol ?? '' : currencyBase?.symbol ?? ''} />{' '}
|
||||||
|
{' per '}{' '}
|
||||||
|
<HoverInlineText text={manuallyInverted ? currencyBase?.symbol ?? '' : currencyQuote?.symbol ?? ''} />
|
||||||
</RangeText>{' '}
|
</RangeText>{' '}
|
||||||
<HideSmall>
|
<HideSmall>
|
||||||
<DoubleArrow>⟷</DoubleArrow>{' '}
|
<DoubleArrow>⟷</DoubleArrow>{' '}
|
||||||
@@ -255,8 +258,13 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
|
|||||||
</SmallOnly>
|
</SmallOnly>
|
||||||
<RangeText>
|
<RangeText>
|
||||||
<ExtentsText>Max:</ExtentsText>
|
<ExtentsText>Max:</ExtentsText>
|
||||||
{formatPrice(priceUpper, 4)} {manuallyInverted ? currencyQuote?.symbol : currencyBase?.symbol} {' / '}{' '}
|
{formatPrice(priceUpper, 5)}{' '}
|
||||||
{manuallyInverted ? currencyBase?.symbol : currencyQuote?.symbol}
|
<HoverInlineText text={manuallyInverted ? currencyQuote?.symbol ?? '' : currencyBase?.symbol ?? ''} />{' '}
|
||||||
|
{' per '}{' '}
|
||||||
|
<HoverInlineText
|
||||||
|
maxCharacters={10}
|
||||||
|
text={manuallyInverted ? currencyBase?.symbol ?? '' : currencyQuote?.symbol ?? ''}
|
||||||
|
/>
|
||||||
</RangeText>{' '}
|
</RangeText>{' '}
|
||||||
</RangeLineItem>
|
</RangeLineItem>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import RateToggle from 'components/RateToggle'
|
|||||||
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
import DoubleCurrencyLogo from 'components/DoubleLogo'
|
||||||
import RangeBadge from 'components/Badge/RangeBadge'
|
import RangeBadge from 'components/Badge/RangeBadge'
|
||||||
import { ThemeContext } from 'styled-components'
|
import { ThemeContext } from 'styled-components'
|
||||||
import { JSBI } from '@uniswap/v2-sdk'
|
import JSBI from 'jsbi'
|
||||||
|
|
||||||
export const PositionPreview = ({
|
export const PositionPreview = ({
|
||||||
position,
|
position,
|
||||||
@@ -135,7 +135,7 @@ export const PositionPreview = ({
|
|||||||
<TYPE.main
|
<TYPE.main
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
fontSize="12px"
|
fontSize="12px"
|
||||||
>{` ${quoteCurrency.symbol}/${baseCurrency.symbol}`}</TYPE.main>
|
>{` ${quoteCurrency.symbol} per ${baseCurrency.symbol}`}</TYPE.main>
|
||||||
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
|
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
|
||||||
Your position will be 100% composed of {quoteCurrency?.symbol} at this price
|
Your position will be 100% composed of {quoteCurrency?.symbol} at this price
|
||||||
</TYPE.small>
|
</TYPE.small>
|
||||||
@@ -145,11 +145,11 @@ export const PositionPreview = ({
|
|||||||
<LightCard padding="12px ">
|
<LightCard padding="12px ">
|
||||||
<AutoColumn gap="4px" justify="center">
|
<AutoColumn gap="4px" justify="center">
|
||||||
<TYPE.main fontSize="12px">Current price</TYPE.main>
|
<TYPE.main fontSize="12px">Current price</TYPE.main>
|
||||||
<TYPE.mediumHeader>{`${price.toSignificant(6)} `}</TYPE.mediumHeader>
|
<TYPE.mediumHeader>{`${price.toSignificant(5)} `}</TYPE.mediumHeader>
|
||||||
<TYPE.main
|
<TYPE.main
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
fontSize="12px"
|
fontSize="12px"
|
||||||
>{` ${quoteCurrency.symbol}/${baseCurrency.symbol}`}</TYPE.main>
|
>{` ${quoteCurrency.symbol} per ${baseCurrency.symbol}`}</TYPE.main>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</LightCard>
|
</LightCard>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import { ThemeContext } from 'styled-components'
|
import { ThemeContext } from 'styled-components'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useCallback, useState } from 'react'
|
import React, { useCallback, useState } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import Tooltip from '../Tooltip'
|
import Tooltip from '../Tooltip'
|
||||||
|
|
||||||
const QuestionWrapper = styled.div`
|
const QuestionWrapper = styled.div`
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Currency, Price } from '@uniswap/sdk-core'
|
import { Currency, Price, Token } from '@uniswap/sdk-core'
|
||||||
import StepCounter from 'components/InputStepCounter/InputStepCounter'
|
import StepCounter from 'components/InputStepCounter/InputStepCounter'
|
||||||
import { RowBetween } from 'components/Row'
|
import { RowBetween } from 'components/Row'
|
||||||
import { useActiveWeb3React } from 'hooks'
|
import { useActiveWeb3React } from 'hooks'
|
||||||
@@ -19,8 +19,8 @@ export default function RangeSelector({
|
|||||||
currencyB,
|
currencyB,
|
||||||
feeAmount,
|
feeAmount,
|
||||||
}: {
|
}: {
|
||||||
priceLower?: Price
|
priceLower?: Price<Token, Token>
|
||||||
priceUpper?: Price
|
priceUpper?: Price<Token, Token>
|
||||||
getDecrementLower: () => string
|
getDecrementLower: () => string
|
||||||
getIncrementLower: () => string
|
getIncrementLower: () => string
|
||||||
getDecrementUpper: () => string
|
getDecrementUpper: () => string
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ export default function RateToggle({
|
|||||||
<div style={{ width: 'fit-content', display: 'flex', alignItems: 'center' }}>
|
<div style={{ width: 'fit-content', display: 'flex', alignItems: 'center' }}>
|
||||||
<ToggleWrapper width="fit-content">
|
<ToggleWrapper width="fit-content">
|
||||||
<ToggleElement isActive={isSorted} fontSize="12px" onClick={handleRateToggle}>
|
<ToggleElement isActive={isSorted} fontSize="12px" onClick={handleRateToggle}>
|
||||||
{isSorted ? currencyB.symbol + ' / ' + currencyA.symbol : currencyA.symbol + ' / ' + currencyB.symbol}{' '}
|
{isSorted ? currencyA.symbol + ' price ' : currencyB.symbol + ' price '}
|
||||||
</ToggleElement>
|
</ToggleElement>
|
||||||
<ToggleElement isActive={!isSorted} fontSize="12px" onClick={handleRateToggle}>
|
<ToggleElement isActive={!isSorted} fontSize="12px" onClick={handleRateToggle}>
|
||||||
{isSorted ? currencyA.symbol + ' / ' + currencyB.symbol : currencyB.symbol + ' / ' + currencyA.symbol}
|
{isSorted ? currencyB.symbol + ' price ' : currencyA.symbol + ' price '}
|
||||||
</ToggleElement>
|
</ToggleElement>
|
||||||
</ToggleWrapper>
|
</ToggleWrapper>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { Box } from 'rebass/styled-components'
|
import { Box } from 'rebass/styled-components'
|
||||||
|
|
||||||
const Row = styled(Box)<{
|
const Row = styled(Box)<{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { ChainId, Currency, currencyEquals, Token, ETHER } from '@uniswap/sdk-core'
|
import { ChainId, Currency, currencyEquals, Token, ETHER } from '@uniswap/sdk-core'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
import { SUGGESTED_BASES } from '../../constants'
|
import { SUGGESTED_BASES } from '../../constants'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
@@ -49,7 +49,7 @@ export default function CommonBases({
|
|||||||
onSelect(ETHER)
|
onSelect(ETHER)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
disable={selectedCurrency === ETHER}
|
disable={selectedCurrency?.isEther}
|
||||||
>
|
>
|
||||||
<CurrencyLogo currency={ETHER} style={{ marginRight: 8 }} />
|
<CurrencyLogo currency={ETHER} style={{ marginRight: 8 }} />
|
||||||
<Text fontWeight={500} fontSize={16}>
|
<Text fontWeight={500} fontSize={16}>
|
||||||
@@ -57,7 +57,7 @@ export default function CommonBases({
|
|||||||
</Text>
|
</Text>
|
||||||
</BaseWrapper>
|
</BaseWrapper>
|
||||||
{(typeof chainId === 'number' ? SUGGESTED_BASES[chainId] ?? [] : []).map((token: Token) => {
|
{(typeof chainId === 'number' ? SUGGESTED_BASES[chainId] ?? [] : []).map((token: Token) => {
|
||||||
const selected = selectedCurrency instanceof Token && selectedCurrency.address === token.address
|
const selected = selectedCurrency?.isToken && selectedCurrency.address === token.address
|
||||||
return (
|
return (
|
||||||
<BaseWrapper onClick={() => !selected && onSelect(token)} disable={selected} key={token.address}>
|
<BaseWrapper onClick={() => !selected && onSelect(token)} disable={selected} key={token.address}>
|
||||||
<CurrencyLogo currency={token} style={{ marginRight: 8 }} />
|
<CurrencyLogo currency={token} style={{ marginRight: 8 }} />
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import { Currency, CurrencyAmount, currencyEquals, ETHER, Token } from '@uniswap/sdk-core'
|
import { Currency, CurrencyAmount, currencyEquals, Token } from '@uniswap/sdk-core'
|
||||||
import React, { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react'
|
import React, { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react'
|
||||||
import { FixedSizeList } from 'react-window'
|
import { FixedSizeList } from 'react-window'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
import { WrappedTokenInfo, useCombinedActiveList } from '../../state/lists/hooks'
|
import { useCombinedActiveList } from '../../state/lists/hooks'
|
||||||
|
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
|
||||||
import { useCurrencyBalance } from '../../state/wallet/hooks'
|
import { useCurrencyBalance } from '../../state/wallet/hooks'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
import { useIsUserAddedToken, useAllInactiveTokens } from '../../hooks/Tokens'
|
import { useIsUserAddedToken } from '../../hooks/Tokens'
|
||||||
import Column from '../Column'
|
import Column from '../Column'
|
||||||
import { RowFixed, RowBetween } from '../Row'
|
import { RowFixed, RowBetween } from '../Row'
|
||||||
import CurrencyLogo from '../CurrencyLogo'
|
import CurrencyLogo from '../CurrencyLogo'
|
||||||
@@ -23,7 +24,7 @@ import QuestionHelper from 'components/QuestionHelper'
|
|||||||
import useTheme from 'hooks/useTheme'
|
import useTheme from 'hooks/useTheme'
|
||||||
|
|
||||||
function currencyKey(currency: Currency): string {
|
function currencyKey(currency: Currency): string {
|
||||||
return currency instanceof Token ? currency.address : currency === ETHER ? 'ETHER' : ''
|
return currency.isToken ? currency.address : 'ETHER'
|
||||||
}
|
}
|
||||||
|
|
||||||
const StyledBalanceText = styled(Text)`
|
const StyledBalanceText = styled(Text)`
|
||||||
@@ -55,7 +56,7 @@ const FixedContentRow = styled.div`
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
`
|
`
|
||||||
|
|
||||||
function Balance({ balance }: { balance: CurrencyAmount }) {
|
function Balance({ balance }: { balance: CurrencyAmount<Currency> }) {
|
||||||
return <StyledBalanceText title={balance.toExact()}>{balance.toSignificant(4)}</StyledBalanceText>
|
return <StyledBalanceText title={balance.toExact()}>{balance.toSignificant(4)}</StyledBalanceText>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ function CurrencyRow({
|
|||||||
const { account } = useActiveWeb3React()
|
const { account } = useActiveWeb3React()
|
||||||
const key = currencyKey(currency)
|
const key = currencyKey(currency)
|
||||||
const selectedTokenList = useCombinedActiveList()
|
const selectedTokenList = useCombinedActiveList()
|
||||||
const isOnSelectedList = isTokenOnList(selectedTokenList, currency)
|
const isOnSelectedList = isTokenOnList(selectedTokenList, currency.isToken ? currency : undefined)
|
||||||
const customAdded = useIsUserAddedToken(currency)
|
const customAdded = useIsUserAddedToken(currency)
|
||||||
const balance = useCurrencyBalance(account ?? undefined, currency)
|
const balance = useCurrencyBalance(account ?? undefined, currency)
|
||||||
|
|
||||||
@@ -132,7 +133,7 @@ function CurrencyRow({
|
|||||||
{currency.symbol}
|
{currency.symbol}
|
||||||
</Text>
|
</Text>
|
||||||
<TYPE.darkGray ml="0px" fontSize={'12px'} fontWeight={300}>
|
<TYPE.darkGray ml="0px" fontSize={'12px'} fontWeight={300}>
|
||||||
{currency.name} {!isOnSelectedList && customAdded && '• Added by user'}
|
{currency.name} {!currency.isEther && !isOnSelectedList && customAdded && '• Added by user'}
|
||||||
</TYPE.darkGray>
|
</TYPE.darkGray>
|
||||||
</Column>
|
</Column>
|
||||||
<TokenTags currency={currency} />
|
<TokenTags currency={currency} />
|
||||||
@@ -143,84 +144,84 @@ function CurrencyRow({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BREAK_LINE = 'BREAK'
|
||||||
|
type BreakLine = typeof BREAK_LINE
|
||||||
|
function isBreakLine(x: unknown): x is BreakLine {
|
||||||
|
return x === BREAK_LINE
|
||||||
|
}
|
||||||
|
|
||||||
|
function BreakLineComponent({ style }: { style: CSSProperties }) {
|
||||||
|
const theme = useTheme()
|
||||||
|
return (
|
||||||
|
<FixedContentRow style={style}>
|
||||||
|
<LightGreyCard padding="8px 12px" borderRadius="8px">
|
||||||
|
<RowBetween>
|
||||||
|
<RowFixed>
|
||||||
|
<TokenListLogoWrapper src={TokenListLogo} />
|
||||||
|
<TYPE.main ml="6px" fontSize="12px" color={theme.text1}>
|
||||||
|
Expanded results from inactive Token Lists
|
||||||
|
</TYPE.main>
|
||||||
|
</RowFixed>
|
||||||
|
<QuestionHelper text="Tokens from inactive lists. Import specific tokens below or click 'Manage' to activate more lists." />
|
||||||
|
</RowBetween>
|
||||||
|
</LightGreyCard>
|
||||||
|
</FixedContentRow>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export default function CurrencyList({
|
export default function CurrencyList({
|
||||||
height,
|
height,
|
||||||
currencies,
|
currencies,
|
||||||
|
otherListTokens,
|
||||||
selectedCurrency,
|
selectedCurrency,
|
||||||
onCurrencySelect,
|
onCurrencySelect,
|
||||||
otherCurrency,
|
otherCurrency,
|
||||||
fixedListRef,
|
fixedListRef,
|
||||||
showETH,
|
|
||||||
showImportView,
|
showImportView,
|
||||||
setImportToken,
|
setImportToken,
|
||||||
breakIndex,
|
|
||||||
}: {
|
}: {
|
||||||
height: number
|
height: number
|
||||||
currencies: Currency[]
|
currencies: Currency[]
|
||||||
|
otherListTokens?: WrappedTokenInfo[]
|
||||||
selectedCurrency?: Currency | null
|
selectedCurrency?: Currency | null
|
||||||
onCurrencySelect: (currency: Currency) => void
|
onCurrencySelect: (currency: Currency) => void
|
||||||
otherCurrency?: Currency | null
|
otherCurrency?: Currency | null
|
||||||
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
|
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
|
||||||
showETH: boolean
|
|
||||||
showImportView: () => void
|
showImportView: () => void
|
||||||
setImportToken: (token: Token) => void
|
setImportToken: (token: Token) => void
|
||||||
breakIndex: number | undefined
|
|
||||||
}) {
|
}) {
|
||||||
const itemData: (Currency | undefined)[] = useMemo(() => {
|
const itemData: (Currency | BreakLine)[] = useMemo(() => {
|
||||||
let formatted: (Currency | undefined)[] = showETH ? [Currency.ETHER, ...currencies] : currencies
|
if (otherListTokens && otherListTokens?.length > 0) {
|
||||||
if (breakIndex !== undefined) {
|
return [...currencies, BREAK_LINE, ...otherListTokens]
|
||||||
formatted = [...formatted.slice(0, breakIndex), undefined, ...formatted.slice(breakIndex, formatted.length)]
|
|
||||||
}
|
}
|
||||||
return formatted
|
return currencies
|
||||||
}, [breakIndex, currencies, showETH])
|
}, [currencies, otherListTokens])
|
||||||
|
|
||||||
const { chainId } = useActiveWeb3React()
|
const { chainId } = useActiveWeb3React()
|
||||||
const theme = useTheme()
|
|
||||||
|
|
||||||
const inactiveTokens: {
|
|
||||||
[address: string]: Token
|
|
||||||
} = useAllInactiveTokens()
|
|
||||||
|
|
||||||
const Row = useCallback(
|
const Row = useCallback(
|
||||||
({ data, index, style }) => {
|
function TokenRow({ data, index, style }) {
|
||||||
const currency: Currency = data[index]
|
const row: Currency | BreakLine = data[index]
|
||||||
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
|
|
||||||
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
|
if (isBreakLine(row)) {
|
||||||
const handleSelect = () => onCurrencySelect(currency)
|
return <BreakLineComponent style={style} />
|
||||||
|
}
|
||||||
|
|
||||||
|
const currency = row
|
||||||
|
|
||||||
|
const isSelected = Boolean(currency && selectedCurrency && currencyEquals(selectedCurrency, currency))
|
||||||
|
const otherSelected = Boolean(currency && otherCurrency && currencyEquals(otherCurrency, currency))
|
||||||
|
const handleSelect = () => currency && onCurrencySelect(currency)
|
||||||
|
|
||||||
const token = wrappedCurrency(currency, chainId)
|
const token = wrappedCurrency(currency, chainId)
|
||||||
|
|
||||||
const showImport = inactiveTokens && token && Object.keys(inactiveTokens).includes(token.address)
|
const showImport = index > currencies.length
|
||||||
|
|
||||||
if (index === breakIndex || !data) {
|
|
||||||
return (
|
|
||||||
<FixedContentRow style={style}>
|
|
||||||
<LightGreyCard padding="8px 12px" borderRadius="8px">
|
|
||||||
<RowBetween>
|
|
||||||
<RowFixed>
|
|
||||||
<TokenListLogoWrapper src={TokenListLogo} />
|
|
||||||
<TYPE.main ml="6px" fontSize="12px" color={theme.text1}>
|
|
||||||
Expanded results from inactive Token Lists
|
|
||||||
</TYPE.main>
|
|
||||||
</RowFixed>
|
|
||||||
<QuestionHelper text="Tokens from inactive lists. Import specific tokens below or click 'Manage' to activate more lists." />
|
|
||||||
</RowBetween>
|
|
||||||
</LightGreyCard>
|
|
||||||
</FixedContentRow>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showImport && token) {
|
if (showImport && token) {
|
||||||
return (
|
return (
|
||||||
<ImportRow
|
<ImportRow style={style} token={token} showImportView={showImportView} setImportToken={setImportToken} dim />
|
||||||
style={style}
|
|
||||||
token={token}
|
|
||||||
showImportView={showImportView}
|
|
||||||
setImportToken={setImportToken}
|
|
||||||
dim={true}
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
} else {
|
} else if (currency) {
|
||||||
return (
|
return (
|
||||||
<CurrencyRow
|
<CurrencyRow
|
||||||
style={style}
|
style={style}
|
||||||
@@ -230,22 +231,18 @@ export default function CurrencyList({
|
|||||||
otherSelected={otherSelected}
|
otherSelected={otherSelected}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[chainId, currencies.length, onCurrencySelect, otherCurrency, selectedCurrency, setImportToken, showImportView]
|
||||||
chainId,
|
|
||||||
inactiveTokens,
|
|
||||||
onCurrencySelect,
|
|
||||||
otherCurrency,
|
|
||||||
selectedCurrency,
|
|
||||||
setImportToken,
|
|
||||||
showImportView,
|
|
||||||
breakIndex,
|
|
||||||
theme.text1,
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
|
const itemKey = useCallback((index: number, data: typeof itemData) => {
|
||||||
|
const currency = data[index]
|
||||||
|
if (isBreakLine(currency)) return BREAK_LINE
|
||||||
|
return currencyKey(currency)
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FixedSizeList
|
<FixedSizeList
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import { FixedSizeList } from 'react-window'
|
import { FixedSizeList } from 'react-window'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
import { useAllTokens, useToken, useIsUserAddedToken, useFoundOnInactiveList } from '../../hooks/Tokens'
|
import { useAllTokens, useToken, useIsUserAddedToken, useSearchInactiveTokenLists } from '../../hooks/Tokens'
|
||||||
import { CloseIcon, TYPE, ButtonText, IconWrapper } from '../../theme'
|
import { CloseIcon, TYPE, ButtonText, IconWrapper } from '../../theme'
|
||||||
import { isAddress } from '../../utils'
|
import { isAddress } from '../../utils'
|
||||||
import Column from '../Column'
|
import Column from '../Column'
|
||||||
@@ -16,7 +16,7 @@ import { filterTokens, useSortedTokensByQuery } from './filtering'
|
|||||||
import { useTokenComparator } from './sorting'
|
import { useTokenComparator } from './sorting'
|
||||||
import { PaddedColumn, SearchInput, Separator } from './styleds'
|
import { PaddedColumn, SearchInput, Separator } from './styleds'
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer'
|
import AutoSizer from 'react-virtualized-auto-sizer'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import useToggle from 'hooks/useToggle'
|
import useToggle from 'hooks/useToggle'
|
||||||
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
||||||
import useTheme from 'hooks/useTheme'
|
import useTheme from 'hooks/useTheme'
|
||||||
@@ -94,11 +94,6 @@ export function CurrencySearch({
|
|||||||
}
|
}
|
||||||
}, [isAddressSearch])
|
}, [isAddressSearch])
|
||||||
|
|
||||||
const showETH: boolean = useMemo(() => {
|
|
||||||
const s = debouncedQuery.toLowerCase().trim()
|
|
||||||
return s === '' || s === 'e' || s === 'et' || s === 'eth'
|
|
||||||
}, [debouncedQuery])
|
|
||||||
|
|
||||||
const tokenComparator = useTokenComparator(invertSearchOrder)
|
const tokenComparator = useTokenComparator(invertSearchOrder)
|
||||||
|
|
||||||
const filteredTokens: Token[] = useMemo(() => {
|
const filteredTokens: Token[] = useMemo(() => {
|
||||||
@@ -111,6 +106,14 @@ export function CurrencySearch({
|
|||||||
|
|
||||||
const filteredSortedTokens = useSortedTokensByQuery(sortedTokens, debouncedQuery)
|
const filteredSortedTokens = useSortedTokensByQuery(sortedTokens, debouncedQuery)
|
||||||
|
|
||||||
|
const filteredSortedTokensWithETH: Currency[] = useMemo(() => {
|
||||||
|
const s = debouncedQuery.toLowerCase().trim()
|
||||||
|
if (s === '' || s === 'e' || s === 'et' || s === 'eth') {
|
||||||
|
return [ETHER, ...filteredSortedTokens]
|
||||||
|
}
|
||||||
|
return filteredSortedTokens
|
||||||
|
}, [debouncedQuery, filteredSortedTokens])
|
||||||
|
|
||||||
const handleCurrencySelect = useCallback(
|
const handleCurrencySelect = useCallback(
|
||||||
(currency: Currency) => {
|
(currency: Currency) => {
|
||||||
onCurrencySelect(currency)
|
onCurrencySelect(currency)
|
||||||
@@ -139,17 +142,17 @@ export function CurrencySearch({
|
|||||||
const s = debouncedQuery.toLowerCase().trim()
|
const s = debouncedQuery.toLowerCase().trim()
|
||||||
if (s === 'eth') {
|
if (s === 'eth') {
|
||||||
handleCurrencySelect(ETHER)
|
handleCurrencySelect(ETHER)
|
||||||
} else if (filteredSortedTokens.length > 0) {
|
} else if (filteredSortedTokensWithETH.length > 0) {
|
||||||
if (
|
if (
|
||||||
filteredSortedTokens[0].symbol?.toLowerCase() === debouncedQuery.trim().toLowerCase() ||
|
filteredSortedTokensWithETH[0].symbol?.toLowerCase() === debouncedQuery.trim().toLowerCase() ||
|
||||||
filteredSortedTokens.length === 1
|
filteredSortedTokensWithETH.length === 1
|
||||||
) {
|
) {
|
||||||
handleCurrencySelect(filteredSortedTokens[0])
|
handleCurrencySelect(filteredSortedTokensWithETH[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[filteredSortedTokens, handleCurrencySelect, debouncedQuery]
|
[filteredSortedTokensWithETH, handleCurrencySelect, debouncedQuery]
|
||||||
)
|
)
|
||||||
|
|
||||||
// menu ui
|
// menu ui
|
||||||
@@ -158,8 +161,9 @@ export function CurrencySearch({
|
|||||||
useOnClickOutside(node, open ? toggle : undefined)
|
useOnClickOutside(node, open ? toggle : undefined)
|
||||||
|
|
||||||
// if no results on main list, show option to expand into inactive
|
// if no results on main list, show option to expand into inactive
|
||||||
const inactiveTokens = useFoundOnInactiveList(debouncedQuery)
|
const filteredInactiveTokens = useSearchInactiveTokenLists(
|
||||||
const filteredInactiveTokens: Token[] = useSortedTokensByQuery(inactiveTokens, debouncedQuery)
|
filteredTokens.length === 0 || (debouncedQuery.length > 2 && !isAddressSearch) ? debouncedQuery : undefined
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContentWrapper>
|
<ContentWrapper>
|
||||||
@@ -197,11 +201,8 @@ export function CurrencySearch({
|
|||||||
{({ height }) => (
|
{({ height }) => (
|
||||||
<CurrencyList
|
<CurrencyList
|
||||||
height={height}
|
height={height}
|
||||||
showETH={showETH}
|
currencies={filteredSortedTokensWithETH}
|
||||||
currencies={
|
otherListTokens={filteredInactiveTokens}
|
||||||
filteredInactiveTokens ? filteredSortedTokens.concat(filteredInactiveTokens) : filteredSortedTokens
|
|
||||||
}
|
|
||||||
breakIndex={inactiveTokens && filteredSortedTokens ? filteredSortedTokens.length : undefined}
|
|
||||||
onCurrencySelect={handleCurrencySelect}
|
onCurrencySelect={handleCurrencySelect}
|
||||||
otherCurrency={otherSelectedCurrency}
|
otherCurrency={otherSelectedCurrency}
|
||||||
selectedCurrency={selectedCurrency}
|
selectedCurrency={selectedCurrency}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Currency, Token } from '@uniswap/sdk-core'
|
import { Currency, Token } from '@uniswap/sdk-core'
|
||||||
import React, { useCallback, useEffect, useState } from 'react'
|
import React, { useCallback, useEffect, useState } from 'react'
|
||||||
import useLast from '../../hooks/useLast'
|
import useLast from '../../hooks/useLast'
|
||||||
|
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import { CurrencySearch } from './CurrencySearch'
|
import { CurrencySearch } from './CurrencySearch'
|
||||||
import { ImportToken } from './ImportToken'
|
import { ImportToken } from './ImportToken'
|
||||||
@@ -81,6 +82,7 @@ export default function CurrencySearchModal({
|
|||||||
<ImportToken
|
<ImportToken
|
||||||
tokens={[importToken]}
|
tokens={[importToken]}
|
||||||
onDismiss={onDismiss}
|
onDismiss={onDismiss}
|
||||||
|
list={importToken instanceof WrappedTokenInfo ? importToken.list : undefined}
|
||||||
onBack={() =>
|
onBack={() =>
|
||||||
setModalView(prevView && prevView !== CurrencyModalView.importToken ? prevView : CurrencyModalView.search)
|
setModalView(prevView && prevView !== CurrencyModalView.importToken ? prevView : CurrencyModalView.search)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useCallback } from 'react'
|
import React, { useState, useCallback } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
import { TYPE, CloseIcon } from 'theme'
|
import { TYPE, CloseIcon } from 'theme'
|
||||||
import Card from 'components/Card'
|
import Card from 'components/Card'
|
||||||
|
|||||||
@@ -5,13 +5,12 @@ import { AutoColumn } from 'components/Column'
|
|||||||
import CurrencyLogo from 'components/CurrencyLogo'
|
import CurrencyLogo from 'components/CurrencyLogo'
|
||||||
import { TYPE } from 'theme'
|
import { TYPE } from 'theme'
|
||||||
import ListLogo from 'components/ListLogo'
|
import ListLogo from 'components/ListLogo'
|
||||||
import { useActiveWeb3React } from 'hooks'
|
|
||||||
import { useCombinedInactiveList } from 'state/lists/hooks'
|
|
||||||
import useTheme from 'hooks/useTheme'
|
import useTheme from 'hooks/useTheme'
|
||||||
import { ButtonPrimary } from 'components/Button'
|
import { ButtonPrimary } from 'components/Button'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { useIsUserAddedToken, useIsTokenActive } from 'hooks/Tokens'
|
import { useIsUserAddedToken, useIsTokenActive } from 'hooks/Tokens'
|
||||||
import { CheckCircle } from 'react-feather'
|
import { CheckCircle } from 'react-feather'
|
||||||
|
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
|
||||||
|
|
||||||
const TokenSection = styled.div<{ dim?: boolean }>`
|
const TokenSection = styled.div<{ dim?: boolean }>`
|
||||||
padding: 4px 20px;
|
padding: 4px 20px;
|
||||||
@@ -53,18 +52,14 @@ export default function ImportRow({
|
|||||||
showImportView: () => void
|
showImportView: () => void
|
||||||
setImportToken: (token: Token) => void
|
setImportToken: (token: Token) => void
|
||||||
}) {
|
}) {
|
||||||
// gloabls
|
|
||||||
const { chainId } = useActiveWeb3React()
|
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
// check if token comes from list
|
|
||||||
const inactiveTokenList = useCombinedInactiveList()
|
|
||||||
const list = chainId && inactiveTokenList?.[chainId]?.[token.address]?.list
|
|
||||||
|
|
||||||
// check if already active on list or local storage tokens
|
// check if already active on list or local storage tokens
|
||||||
const isAdded = useIsUserAddedToken(token)
|
const isAdded = useIsUserAddedToken(token)
|
||||||
const isActive = useIsTokenActive(token)
|
const isActive = useIsTokenActive(token)
|
||||||
|
|
||||||
|
const list = token instanceof WrappedTokenInfo ? token.list : undefined
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TokenSection style={style}>
|
<TokenSection style={style}>
|
||||||
<CurrencyLogo currency={token} size={'24px'} style={{ opacity: dim ? '0.6' : '1' }} />
|
<CurrencyLogo currency={token} size={'24px'} style={{ opacity: dim ? '0.6' : '1' }} />
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import { TokenList } from '@uniswap/token-lists/dist/types'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Token, Currency } from '@uniswap/sdk-core'
|
import { Token, Currency } from '@uniswap/sdk-core'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { TYPE, CloseIcon } from 'theme'
|
import { TYPE, CloseIcon } from 'theme'
|
||||||
import Card from 'components/Card'
|
import Card from 'components/Card'
|
||||||
import { AutoColumn } from 'components/Column'
|
import { AutoColumn } from 'components/Column'
|
||||||
@@ -15,7 +16,6 @@ import { useAddUserToken } from 'state/user/hooks'
|
|||||||
import { getEtherscanLink } from 'utils'
|
import { getEtherscanLink } from 'utils'
|
||||||
import { useActiveWeb3React } from 'hooks'
|
import { useActiveWeb3React } from 'hooks'
|
||||||
import { ExternalLink } from '../../theme/components'
|
import { ExternalLink } from '../../theme/components'
|
||||||
import { useCombinedInactiveList } from 'state/lists/hooks'
|
|
||||||
import ListLogo from 'components/ListLogo'
|
import ListLogo from 'components/ListLogo'
|
||||||
import { PaddedColumn } from './styleds'
|
import { PaddedColumn } from './styleds'
|
||||||
|
|
||||||
@@ -41,28 +41,26 @@ const AddressText = styled(TYPE.blue)`
|
|||||||
|
|
||||||
interface ImportProps {
|
interface ImportProps {
|
||||||
tokens: Token[]
|
tokens: Token[]
|
||||||
|
list?: TokenList
|
||||||
onBack?: () => void
|
onBack?: () => void
|
||||||
onDismiss?: () => void
|
onDismiss?: () => void
|
||||||
handleCurrencySelect?: (currency: Currency) => void
|
handleCurrencySelect?: (currency: Currency) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ImportToken({ tokens, onBack, onDismiss, handleCurrencySelect }: ImportProps) {
|
export function ImportToken({ tokens, list, onBack, onDismiss, handleCurrencySelect }: ImportProps) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
const { chainId } = useActiveWeb3React()
|
const { chainId } = useActiveWeb3React()
|
||||||
|
|
||||||
const addToken = useAddUserToken()
|
const addToken = useAddUserToken()
|
||||||
|
|
||||||
// use for showing import source on inactive tokens
|
|
||||||
const inactiveTokenList = useCombinedInactiveList()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
|
<PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div></div>}
|
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div />}
|
||||||
<TYPE.mediumHeader>Import {tokens.length > 1 ? 'Tokens' : 'Token'}</TYPE.mediumHeader>
|
<TYPE.mediumHeader>Import {tokens.length > 1 ? 'Tokens' : 'Token'}</TYPE.mediumHeader>
|
||||||
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div></div>}
|
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div />}
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
</PaddedColumn>
|
</PaddedColumn>
|
||||||
<SectionBreak />
|
<SectionBreak />
|
||||||
@@ -76,7 +74,6 @@ export function ImportToken({ tokens, onBack, onDismiss, handleCurrencySelect }:
|
|||||||
</TYPE.body>
|
</TYPE.body>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
{tokens.map((token) => {
|
{tokens.map((token) => {
|
||||||
const list = chainId && inactiveTokenList?.[chainId]?.[token.address]?.list
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
backgroundColor={theme.bg2}
|
backgroundColor={theme.bg2}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { RowBetween } from 'components/Row'
|
|||||||
import { ArrowLeft } from 'react-feather'
|
import { ArrowLeft } from 'react-feather'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { CloseIcon } from 'theme'
|
import { CloseIcon } from 'theme'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { Token } from '@uniswap/sdk-core'
|
import { Token } from '@uniswap/sdk-core'
|
||||||
import { ManageLists } from './ManageLists'
|
import { ManageLists } from './ManageLists'
|
||||||
import ManageTokens from './ManageTokens'
|
import ManageTokens from './ManageTokens'
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Settings, CheckCircle } from 'react-feather'
|
|||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
import { usePopper } from 'react-popper'
|
import { usePopper } from 'react-popper'
|
||||||
import { useDispatch, useSelector } from 'react-redux'
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { useFetchListCallback } from '../../hooks/useFetchListCallback'
|
import { useFetchListCallback } from '../../hooks/useFetchListCallback'
|
||||||
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
|
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
|
||||||
import { TokenList } from '@uniswap/token-lists'
|
import { TokenList } from '@uniswap/token-lists'
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { PaddedColumn, Separator, SearchInput } from './styleds'
|
|||||||
import Row, { RowBetween, RowFixed } from 'components/Row'
|
import Row, { RowBetween, RowFixed } from 'components/Row'
|
||||||
import { TYPE, ExternalLinkIcon, TrashIcon, ButtonText, ExternalLink } from 'theme'
|
import { TYPE, ExternalLinkIcon, TrashIcon, ButtonText, ExternalLink } from 'theme'
|
||||||
import { useToken } from 'hooks/Tokens'
|
import { useToken } from 'hooks/Tokens'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { useUserAddedTokens, useRemoveUserAddedToken } from 'state/user/hooks'
|
import { useUserAddedTokens, useRemoveUserAddedToken } from 'state/user/hooks'
|
||||||
import { Token } from '@uniswap/sdk-core'
|
import { Token } from '@uniswap/sdk-core'
|
||||||
import CurrencyLogo from 'components/CurrencyLogo'
|
import CurrencyLogo from 'components/CurrencyLogo'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { RowFixed } from '../Row'
|
import { RowFixed } from '../Row'
|
||||||
|
|
||||||
export const FilterWrapper = styled(RowFixed)`
|
export const FilterWrapper = styled(RowFixed)`
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
|
import { TokenInfo } from '@uniswap/token-lists'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { isAddress } from '../../utils'
|
import { isAddress } from '../../utils'
|
||||||
import { Token } from '@uniswap/sdk-core'
|
import { Token } from '@uniswap/sdk-core'
|
||||||
|
|
||||||
export function filterTokens(tokens: Token[], search: string): Token[] {
|
const alwaysTrue = () => true
|
||||||
if (search.length === 0) return tokens
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a filter function to apply to a token for whether it matches a particular search query
|
||||||
|
* @param search the search query to apply to the token
|
||||||
|
*/
|
||||||
|
export function createTokenFilterFunction<T extends Token | TokenInfo>(search: string): (tokens: T) => boolean {
|
||||||
const searchingAddress = isAddress(search)
|
const searchingAddress = isAddress(search)
|
||||||
|
|
||||||
if (searchingAddress) {
|
if (searchingAddress) {
|
||||||
return tokens.filter((token) => token.address === searchingAddress)
|
const lower = searchingAddress.toLowerCase()
|
||||||
|
return (t: T) => ('isToken' in t ? searchingAddress === t.address : lower === t.address.toLowerCase())
|
||||||
}
|
}
|
||||||
|
|
||||||
const lowerSearchParts = search
|
const lowerSearchParts = search
|
||||||
@@ -16,9 +22,7 @@ export function filterTokens(tokens: Token[], search: string): Token[] {
|
|||||||
.split(/\s+/)
|
.split(/\s+/)
|
||||||
.filter((s) => s.length > 0)
|
.filter((s) => s.length > 0)
|
||||||
|
|
||||||
if (lowerSearchParts.length === 0) {
|
if (lowerSearchParts.length === 0) return alwaysTrue
|
||||||
return tokens
|
|
||||||
}
|
|
||||||
|
|
||||||
const matchesSearch = (s: string): boolean => {
|
const matchesSearch = (s: string): boolean => {
|
||||||
const sParts = s
|
const sParts = s
|
||||||
@@ -29,10 +33,11 @@ export function filterTokens(tokens: Token[], search: string): Token[] {
|
|||||||
return lowerSearchParts.every((p) => p.length === 0 || sParts.some((sp) => sp.startsWith(p) || sp.endsWith(p)))
|
return lowerSearchParts.every((p) => p.length === 0 || sParts.some((sp) => sp.startsWith(p) || sp.endsWith(p)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokens.filter((token) => {
|
return ({ name, symbol }: T): boolean => Boolean((symbol && matchesSearch(symbol)) || (name && matchesSearch(name)))
|
||||||
const { symbol, name } = token
|
}
|
||||||
return (symbol && matchesSearch(symbol)) || (name && matchesSearch(name))
|
|
||||||
})
|
export function filterTokens<T extends Token | TokenInfo>(tokens: T[], search: string): T[] {
|
||||||
|
return tokens.filter(createTokenFilterFunction(search))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useSortedTokensByQuery(tokens: Token[] | undefined, searchQuery: string): Token[] {
|
export function useSortedTokensByQuery(tokens: Token[] | undefined, searchQuery: string): Token[] {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Token, TokenAmount } from '@uniswap/sdk-core'
|
import { Token, CurrencyAmount, Currency } from '@uniswap/sdk-core'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { useAllTokenBalances } from '../../state/wallet/hooks'
|
import { useAllTokenBalances } from '../../state/wallet/hooks'
|
||||||
|
|
||||||
// compare two token amounts with highest one coming first
|
// compare two token amounts with highest one coming first
|
||||||
function balanceComparator(balanceA?: TokenAmount, balanceB?: TokenAmount) {
|
function balanceComparator(balanceA?: CurrencyAmount<Currency>, balanceB?: CurrencyAmount<Currency>) {
|
||||||
if (balanceA && balanceB) {
|
if (balanceA && balanceB) {
|
||||||
return balanceA.greaterThan(balanceB) ? -1 : balanceA.equalTo(balanceB) ? 0 : 1
|
return balanceA.greaterThan(balanceB) ? -1 : balanceA.equalTo(balanceB) ? 0 : 1
|
||||||
} else if (balanceA && balanceA.greaterThan('0')) {
|
} else if (balanceA && balanceA.greaterThan('0')) {
|
||||||
@@ -15,7 +15,7 @@ function balanceComparator(balanceA?: TokenAmount, balanceB?: TokenAmount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getTokenComparator(balances: {
|
function getTokenComparator(balances: {
|
||||||
[tokenAddress: string]: TokenAmount | undefined
|
[tokenAddress: string]: CurrencyAmount<Currency> | undefined
|
||||||
}): (tokenA: Token, tokenB: Token) => number {
|
}): (tokenA: Token, tokenB: Token) => number {
|
||||||
return function sortTokens(tokenA: Token, tokenB: Token): number {
|
return function sortTokens(tokenA: Token, tokenB: Token): number {
|
||||||
// -1 = a is first
|
// -1 = a is first
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import { RowBetween, RowFixed } from '../Row'
|
import { RowBetween, RowFixed } from '../Row'
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import JSBI from 'jsbi'
|
|
||||||
import React, { useContext, useRef, useState } from 'react'
|
import React, { useContext, useRef, useState } from 'react'
|
||||||
import { Settings, X } from 'react-feather'
|
import { Settings, X } from 'react-feather'
|
||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
@@ -7,12 +6,7 @@ import styled, { ThemeContext } from 'styled-components'
|
|||||||
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
|
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
|
||||||
import { ApplicationModal } from '../../state/application/actions'
|
import { ApplicationModal } from '../../state/application/actions'
|
||||||
import { useModalOpen, useToggleSettingsMenu } from '../../state/application/hooks'
|
import { useModalOpen, useToggleSettingsMenu } from '../../state/application/hooks'
|
||||||
import {
|
import { useExpertModeManager, useUserSingleHopOnly } from '../../state/user/hooks'
|
||||||
useExpertModeManager,
|
|
||||||
useUserTransactionTTL,
|
|
||||||
useUserSlippageTolerance,
|
|
||||||
useUserSingleHopOnly,
|
|
||||||
} from '../../state/user/hooks'
|
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
import { ButtonError } from '../Button'
|
import { ButtonError } from '../Button'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
@@ -21,6 +15,7 @@ import QuestionHelper from '../QuestionHelper'
|
|||||||
import { RowBetween, RowFixed } from '../Row'
|
import { RowBetween, RowFixed } from '../Row'
|
||||||
import Toggle from '../Toggle'
|
import Toggle from '../Toggle'
|
||||||
import TransactionSettings from '../TransactionSettings'
|
import TransactionSettings from '../TransactionSettings'
|
||||||
|
import { Percent } from '@uniswap/sdk-core'
|
||||||
|
|
||||||
const StyledMenuIcon = styled(Settings)`
|
const StyledMenuIcon = styled(Settings)`
|
||||||
height: 20px;
|
height: 20px;
|
||||||
@@ -99,6 +94,8 @@ const MenuFlyout = styled.span`
|
|||||||
${({ theme }) => theme.mediaWidth.upToMedium`
|
${({ theme }) => theme.mediaWidth.upToMedium`
|
||||||
min-width: 18.125rem;
|
min-width: 18.125rem;
|
||||||
`};
|
`};
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
`
|
`
|
||||||
|
|
||||||
const Break = styled.div`
|
const Break = styled.div`
|
||||||
@@ -116,15 +113,12 @@ const ModalContentWrapper = styled.div`
|
|||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
`
|
`
|
||||||
|
|
||||||
export default function SettingsTab() {
|
export default function SettingsTab({ placeholderSlippage }: { placeholderSlippage: Percent }) {
|
||||||
const node = useRef<HTMLDivElement>()
|
const node = useRef<HTMLDivElement>()
|
||||||
const open = useModalOpen(ApplicationModal.SETTINGS)
|
const open = useModalOpen(ApplicationModal.SETTINGS)
|
||||||
const toggle = useToggleSettingsMenu()
|
const toggle = useToggleSettingsMenu()
|
||||||
|
|
||||||
const theme = useContext(ThemeContext)
|
const theme = useContext(ThemeContext)
|
||||||
const [userSlippageTolerance, setUserslippageTolerance] = useUserSlippageTolerance()
|
|
||||||
|
|
||||||
const [ttl, setTtl] = useUserTransactionTTL()
|
|
||||||
|
|
||||||
const [expertMode, toggleExpertMode] = useExpertModeManager()
|
const [expertMode, toggleExpertMode] = useExpertModeManager()
|
||||||
|
|
||||||
@@ -191,12 +185,7 @@ export default function SettingsTab() {
|
|||||||
<Text fontWeight={600} fontSize={14}>
|
<Text fontWeight={600} fontSize={14}>
|
||||||
Transaction Settings
|
Transaction Settings
|
||||||
</Text>
|
</Text>
|
||||||
<TransactionSettings
|
<TransactionSettings placeholderSlippage={placeholderSlippage} />
|
||||||
rawSlippage={JSBI.toNumber(userSlippageTolerance.numerator)}
|
|
||||||
setRawSlippage={setUserslippageTolerance}
|
|
||||||
deadline={ttl}
|
|
||||||
setDeadline={setTtl}
|
|
||||||
/>
|
|
||||||
<Text fontWeight={600} fontSize={14}>
|
<Text fontWeight={600} fontSize={14}>
|
||||||
Interface Settings
|
Interface Settings
|
||||||
</Text>
|
</Text>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useCallback } from 'react'
|
import React, { useCallback } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
const StyledRangeInput = styled.input<{ size: number }>`
|
const StyledRangeInput = styled.input<{ size: number }>`
|
||||||
-webkit-appearance: none; /* Hides the slider so that custom slider can be made */
|
-webkit-appearance: none; /* Hides the slider so that custom slider can be made */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { readableColor } from 'polished'
|
import { readableColor } from 'polished'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { colors } from 'theme'
|
import { colors } from 'theme'
|
||||||
|
|
||||||
const Swatch = styled.div`
|
const Swatch = styled.div`
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
|
|
||||||
const Wrapper = styled.button<{ isActive?: boolean; activeElement?: boolean }>`
|
const Wrapper = styled.button<{ isActive?: boolean; activeElement?: boolean }>`
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Story } from '@storybook/react/types-6-0'
|
import { Story } from '@storybook/react/types-6-0'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import MultiToggle from './MultiToggle'
|
import MultiToggle from './MultiToggle'
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
export const ToggleWrapper = styled.button<{ width?: string }>`
|
export const ToggleWrapper = styled.button<{ width?: string }>`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
|
|
||||||
const ToggleElement = styled.span<{ isActive?: boolean; isOnSwitch?: boolean }>`
|
const ToggleElement = styled.span<{ isActive?: boolean; isOnSwitch?: boolean }>`
|
||||||
padding: 0.25rem 0.5rem;
|
padding: 0.25rem 0.5rem;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import React, { useCallback, useState } from 'react'
|
import React, { useCallback, useState } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import Popover, { PopoverProps } from '../Popover'
|
import Popover, { PopoverProps } from '../Popover'
|
||||||
|
|
||||||
const TooltipContainer = styled.div`
|
const TooltipContainer = styled.div`
|
||||||
width: 256px;
|
width: 256px;
|
||||||
padding: 0.6rem 1rem;
|
padding: 0.6rem 1rem;
|
||||||
/* line-height: 150%; */
|
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
word-break: break-word;
|
||||||
`
|
`
|
||||||
|
|
||||||
interface TooltipProps extends Omit<PopoverProps, 'content'> {
|
interface TooltipProps extends Omit<PopoverProps, 'content'> {
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import React, { useState, useRef, useContext } from 'react'
|
import React, { useState, useContext } from 'react'
|
||||||
|
import { Percent } from '@uniswap/sdk-core'
|
||||||
import styled, { ThemeContext } from 'styled-components'
|
import styled, { ThemeContext } from 'styled-components'
|
||||||
|
|
||||||
import QuestionHelper from '../QuestionHelper'
|
import QuestionHelper from '../QuestionHelper'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import { RowBetween, RowFixed } from '../Row'
|
import { RowBetween, RowFixed } from '../Row'
|
||||||
|
import { DEFAULT_DEADLINE_FROM_NOW } from 'constants/index'
|
||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
|
import { useSetUserSlippageTolerance, useUserSlippageTolerance, useUserTransactionTTL } from 'state/user/hooks'
|
||||||
|
|
||||||
enum SlippageError {
|
enum SlippageError {
|
||||||
InvalidInput = 'InvalidInput',
|
InvalidInput = 'InvalidInput',
|
||||||
RiskyLow = 'RiskyLow',
|
|
||||||
RiskyHigh = 'RiskyHigh',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DeadlineError {
|
enum DeadlineError {
|
||||||
@@ -64,7 +64,8 @@ const OptionCustom = styled(FancyButton)<{ active?: boolean; warning?: boolean }
|
|||||||
position: relative;
|
position: relative;
|
||||||
padding: 0 0.75rem;
|
padding: 0 0.75rem;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
border: ${({ theme, active, warning }) => active && `1px solid ${warning ? theme.red1 : theme.primary1}`};
|
border: ${({ theme, active, warning }) =>
|
||||||
|
active ? `1px solid ${warning ? theme.red1 : theme.primary1}` : warning && `1px solid ${theme.red1}`};
|
||||||
:hover {
|
:hover {
|
||||||
border: ${({ theme, active, warning }) =>
|
border: ${({ theme, active, warning }) =>
|
||||||
active && `1px solid ${warning ? darken(0.1, theme.red1) : darken(0.1, theme.primary1)}`};
|
active && `1px solid ${warning ? darken(0.1, theme.red1) : darken(0.1, theme.primary1)}`};
|
||||||
@@ -85,63 +86,68 @@ const SlippageEmojiContainer = styled.span`
|
|||||||
`}
|
`}
|
||||||
`
|
`
|
||||||
|
|
||||||
export interface SlippageTabsProps {
|
export interface TransactionSettingsProps {
|
||||||
rawSlippage: number
|
placeholderSlippage: Percent // varies according to the context in which the settings dialog is placed
|
||||||
setRawSlippage: (rawSlippage: number) => void
|
|
||||||
deadline: number
|
|
||||||
setDeadline: (deadline: number) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SlippageTabs({ rawSlippage, setRawSlippage, deadline, setDeadline }: SlippageTabsProps) {
|
export default function TransactionSettings({ placeholderSlippage }: TransactionSettingsProps) {
|
||||||
const theme = useContext(ThemeContext)
|
const theme = useContext(ThemeContext)
|
||||||
|
|
||||||
const inputRef = useRef<HTMLInputElement>()
|
const userSlippageTolerance = useUserSlippageTolerance()
|
||||||
|
const setUserSlippageTolerance = useSetUserSlippageTolerance()
|
||||||
|
|
||||||
|
const [deadline, setDeadline] = useUserTransactionTTL()
|
||||||
|
|
||||||
const [slippageInput, setSlippageInput] = useState('')
|
const [slippageInput, setSlippageInput] = useState('')
|
||||||
|
const [slippageError, setSlippageError] = useState<SlippageError | false>(false)
|
||||||
|
|
||||||
const [deadlineInput, setDeadlineInput] = useState('')
|
const [deadlineInput, setDeadlineInput] = useState('')
|
||||||
|
const [deadlineError, setDeadlineError] = useState<DeadlineError | false>(false)
|
||||||
|
|
||||||
const slippageInputIsValid =
|
function parseSlippageInput(value: string) {
|
||||||
slippageInput === '' || (rawSlippage / 100).toFixed(2) === Number.parseFloat(slippageInput).toFixed(2)
|
// populate what the user typed and clear the error
|
||||||
const deadlineInputIsValid = deadlineInput === '' || (deadline / 60).toString() === deadlineInput
|
|
||||||
|
|
||||||
let slippageError: SlippageError | undefined
|
|
||||||
if (slippageInput !== '' && !slippageInputIsValid) {
|
|
||||||
slippageError = SlippageError.InvalidInput
|
|
||||||
} else if (slippageInputIsValid && rawSlippage < 50) {
|
|
||||||
slippageError = SlippageError.RiskyLow
|
|
||||||
} else if (slippageInputIsValid && rawSlippage > 500) {
|
|
||||||
slippageError = SlippageError.RiskyHigh
|
|
||||||
} else {
|
|
||||||
slippageError = undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
let deadlineError: DeadlineError | undefined
|
|
||||||
if (deadlineInput !== '' && !deadlineInputIsValid) {
|
|
||||||
deadlineError = DeadlineError.InvalidInput
|
|
||||||
} else {
|
|
||||||
deadlineError = undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseCustomSlippage(value: string) {
|
|
||||||
setSlippageInput(value)
|
setSlippageInput(value)
|
||||||
|
setSlippageError(false)
|
||||||
|
|
||||||
try {
|
if (value.length === 0) {
|
||||||
const valueAsIntFromRoundedFloat = Number.parseInt((Number.parseFloat(value) * 100).toString())
|
setUserSlippageTolerance('auto')
|
||||||
if (!Number.isNaN(valueAsIntFromRoundedFloat) && valueAsIntFromRoundedFloat < 5000) {
|
} else {
|
||||||
setRawSlippage(valueAsIntFromRoundedFloat)
|
const parsed = Math.floor(Number.parseFloat(value) * 100)
|
||||||
|
|
||||||
|
if (!Number.isInteger(parsed) || parsed < 0 || parsed > 5000) {
|
||||||
|
setUserSlippageTolerance('auto')
|
||||||
|
if (value !== '.') {
|
||||||
|
setSlippageError(SlippageError.InvalidInput)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setUserSlippageTolerance(new Percent(parsed, 10_000))
|
||||||
}
|
}
|
||||||
} catch {}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tooLow = userSlippageTolerance !== 'auto' && userSlippageTolerance.lessThan(new Percent(5, 10_000))
|
||||||
|
const tooHigh = userSlippageTolerance !== 'auto' && userSlippageTolerance.greaterThan(new Percent(1, 100))
|
||||||
|
|
||||||
function parseCustomDeadline(value: string) {
|
function parseCustomDeadline(value: string) {
|
||||||
|
// populate what the user typed and clear the error
|
||||||
setDeadlineInput(value)
|
setDeadlineInput(value)
|
||||||
|
setDeadlineError(false)
|
||||||
|
|
||||||
try {
|
if (value.length === 0) {
|
||||||
const valueAsInt: number = Number.parseInt(value) * 60
|
setDeadline(DEFAULT_DEADLINE_FROM_NOW)
|
||||||
if (!Number.isNaN(valueAsInt) && valueAsInt > 0) {
|
} else {
|
||||||
setDeadline(valueAsInt)
|
try {
|
||||||
|
const parsed: number = Math.floor(Number.parseFloat(value) * 60)
|
||||||
|
if (!Number.isInteger(parsed) || parsed < 60 || parsed > 180 * 60) {
|
||||||
|
setDeadlineError(DeadlineError.InvalidInput)
|
||||||
|
} else {
|
||||||
|
setDeadline(parsed)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
setDeadlineError(DeadlineError.InvalidInput)
|
||||||
}
|
}
|
||||||
} catch {}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -156,71 +162,56 @@ export default function SlippageTabs({ rawSlippage, setRawSlippage, deadline, se
|
|||||||
<RowBetween>
|
<RowBetween>
|
||||||
<Option
|
<Option
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSlippageInput('')
|
parseSlippageInput('')
|
||||||
setRawSlippage(10)
|
|
||||||
}}
|
}}
|
||||||
active={rawSlippage === 10}
|
active={userSlippageTolerance === 'auto'}
|
||||||
>
|
>
|
||||||
0.1%
|
Auto
|
||||||
</Option>
|
</Option>
|
||||||
<Option
|
<OptionCustom active={userSlippageTolerance !== 'auto'} warning={!!slippageError} tabIndex={-1}>
|
||||||
onClick={() => {
|
|
||||||
setSlippageInput('')
|
|
||||||
setRawSlippage(50)
|
|
||||||
}}
|
|
||||||
active={rawSlippage === 50}
|
|
||||||
>
|
|
||||||
0.5%
|
|
||||||
</Option>
|
|
||||||
<Option
|
|
||||||
onClick={() => {
|
|
||||||
setSlippageInput('')
|
|
||||||
setRawSlippage(100)
|
|
||||||
}}
|
|
||||||
active={rawSlippage === 100}
|
|
||||||
>
|
|
||||||
1%
|
|
||||||
</Option>
|
|
||||||
<OptionCustom active={![10, 50, 100].includes(rawSlippage)} warning={!slippageInputIsValid} tabIndex={-1}>
|
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
{!!slippageInput &&
|
{tooLow || tooHigh ? (
|
||||||
(slippageError === SlippageError.RiskyLow || slippageError === SlippageError.RiskyHigh) ? (
|
|
||||||
<SlippageEmojiContainer>
|
<SlippageEmojiContainer>
|
||||||
<span role="img" aria-label="warning">
|
<span role="img" aria-label="warning">
|
||||||
⚠️
|
⚠️
|
||||||
</span>
|
</span>
|
||||||
</SlippageEmojiContainer>
|
</SlippageEmojiContainer>
|
||||||
) : null}
|
) : null}
|
||||||
{/* https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30451 */}
|
|
||||||
<Input
|
<Input
|
||||||
ref={inputRef as any}
|
placeholder={placeholderSlippage.toFixed(2)}
|
||||||
placeholder={(rawSlippage / 100).toFixed(2)}
|
value={
|
||||||
value={slippageInput}
|
slippageInput.length > 0
|
||||||
|
? slippageInput
|
||||||
|
: userSlippageTolerance === 'auto'
|
||||||
|
? ''
|
||||||
|
: userSlippageTolerance.toFixed(2)
|
||||||
|
}
|
||||||
|
onChange={(e) => parseSlippageInput(e.target.value)}
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
parseCustomSlippage((rawSlippage / 100).toFixed(2))
|
setSlippageInput('')
|
||||||
|
setSlippageError(false)
|
||||||
}}
|
}}
|
||||||
onChange={(e) => parseCustomSlippage(e.target.value)}
|
color={slippageError ? 'red' : ''}
|
||||||
color={!slippageInputIsValid ? 'red' : ''}
|
|
||||||
/>
|
/>
|
||||||
%
|
%
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
</OptionCustom>
|
</OptionCustom>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
{!!slippageError && (
|
{slippageError || tooLow || tooHigh ? (
|
||||||
<RowBetween
|
<RowBetween
|
||||||
style={{
|
style={{
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
paddingTop: '7px',
|
paddingTop: '7px',
|
||||||
color: slippageError === SlippageError.InvalidInput ? 'red' : '#F3841E',
|
color: slippageError ? 'red' : '#F3841E',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{slippageError === SlippageError.InvalidInput
|
{slippageError
|
||||||
? 'Enter a valid slippage percentage'
|
? 'Enter a valid slippage percentage'
|
||||||
: slippageError === SlippageError.RiskyLow
|
: tooLow
|
||||||
? 'Your transaction may fail'
|
? 'Your transaction may fail'
|
||||||
: 'Your transaction may be frontrun'}
|
: 'Your transaction may be frontrun'}
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
)}
|
) : null}
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
|
|
||||||
<AutoColumn gap="sm">
|
<AutoColumn gap="sm">
|
||||||
@@ -231,15 +222,22 @@ export default function SlippageTabs({ rawSlippage, setRawSlippage, deadline, se
|
|||||||
<QuestionHelper text="Your transaction will revert if it is pending for more than this period of time." />
|
<QuestionHelper text="Your transaction will revert if it is pending for more than this period of time." />
|
||||||
</RowFixed>
|
</RowFixed>
|
||||||
<RowFixed>
|
<RowFixed>
|
||||||
<OptionCustom style={{ width: '80px' }} tabIndex={-1}>
|
<OptionCustom style={{ width: '80px' }} warning={!!deadlineError} tabIndex={-1}>
|
||||||
<Input
|
<Input
|
||||||
color={!!deadlineError ? 'red' : undefined}
|
placeholder={(DEFAULT_DEADLINE_FROM_NOW / 60).toString()}
|
||||||
onBlur={() => {
|
value={
|
||||||
parseCustomDeadline((deadline / 60).toString())
|
deadlineInput.length > 0
|
||||||
}}
|
? deadlineInput
|
||||||
placeholder={(deadline / 60).toString()}
|
: deadline === DEFAULT_DEADLINE_FROM_NOW
|
||||||
value={deadlineInput}
|
? ''
|
||||||
|
: (deadline / 60).toString()
|
||||||
|
}
|
||||||
onChange={(e) => parseCustomDeadline(e.target.value)}
|
onChange={(e) => parseCustomDeadline(e.target.value)}
|
||||||
|
onBlur={() => {
|
||||||
|
setDeadlineInput('')
|
||||||
|
setDeadlineError(false)
|
||||||
|
}}
|
||||||
|
color={deadlineError ? 'red' : ''}
|
||||||
/>
|
/>
|
||||||
</OptionCustom>
|
</OptionCustom>
|
||||||
<TYPE.body style={{ paddingLeft: '8px' }} fontSize={14}>
|
<TYPE.body style={{ paddingLeft: '8px' }} fontSize={14}>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { ExternalLink } from '../../theme'
|
import { ExternalLink } from '../../theme'
|
||||||
|
|
||||||
const InfoCard = styled.button<{ active?: boolean }>`
|
const InfoCard = styled.button<{ active?: boolean }>`
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { AbstractConnector } from '@web3-react/abstract-connector'
|
import { AbstractConnector } from '@web3-react/abstract-connector'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import Option from './Option'
|
import Option from './Option'
|
||||||
import { SUPPORTED_WALLETS } from '../../constants'
|
import { SUPPORTED_WALLETS } from '../../constants'
|
||||||
import { injected } from '../../connectors'
|
import { injected } from '../../connectors'
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { AutoRow } from 'components/Row'
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { isMobile } from 'react-device-detect'
|
import { isMobile } from 'react-device-detect'
|
||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import MetamaskIcon from '../../assets/images/metamask.png'
|
import MetamaskIcon from '../../assets/images/metamask.png'
|
||||||
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
||||||
import { fortmatic, injected, portis } from '../../connectors'
|
import { fortmatic, injected, portis } from '../../connectors'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
import { network } from '../../connectors'
|
import { network } from '../../connectors'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import { AutoColumn, ColumnCenter } from '../Column'
|
import { AutoColumn, ColumnCenter } from '../Column'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { DataCard, CardSection, Break } from '../earn/styled'
|
import { DataCard, CardSection, Break } from '../earn/styled'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
import { TYPE, ExternalLink, CloseIcon, CustomLightSpinner, UniTokenAnimated } from '../../theme'
|
import { TYPE, ExternalLink, CloseIcon, CustomLightSpinner, UniTokenAnimated } from '../../theme'
|
||||||
@@ -17,7 +17,7 @@ import { isAddress } from 'ethers/lib/utils'
|
|||||||
import Confetti from '../Confetti'
|
import Confetti from '../Confetti'
|
||||||
import { CardNoise, CardBGImage, CardBGImageSmaller } from '../earn/styled'
|
import { CardNoise, CardBGImage, CardBGImageSmaller } from '../earn/styled'
|
||||||
import { useIsTransactionPending } from '../../state/transactions/hooks'
|
import { useIsTransactionPending } from '../../state/transactions/hooks'
|
||||||
import { TokenAmount } from '@uniswap/sdk-core'
|
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
import { getEtherscanLink, shortenAddress } from '../../utils'
|
import { getEtherscanLink, shortenAddress } from '../../utils'
|
||||||
|
|
||||||
const ContentWrapper = styled(AutoColumn)`
|
const ContentWrapper = styled(AutoColumn)`
|
||||||
@@ -59,7 +59,7 @@ export default function AddressClaimModal({ isOpen, onDismiss }: { isOpen: boole
|
|||||||
|
|
||||||
// monitor the status of the claim from contracts and txns
|
// monitor the status of the claim from contracts and txns
|
||||||
const { claimCallback } = useClaimCallback(parsedAddress)
|
const { claimCallback } = useClaimCallback(parsedAddress)
|
||||||
const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(parsedAddress)
|
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(parsedAddress)
|
||||||
|
|
||||||
// check if the user has something available
|
// check if the user has something available
|
||||||
const hasAvailableClaim = useUserHasAvailableClaim(parsedAddress)
|
const hasAvailableClaim = useUserHasAvailableClaim(parsedAddress)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { TokenAmount } from '@uniswap/sdk-core'
|
import JSBI from 'jsbi'
|
||||||
import { JSBI } from '@uniswap/v2-sdk'
|
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
import { isAddress } from 'ethers/lib/utils'
|
import { isAddress } from 'ethers/lib/utils'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import Circle from '../../assets/images/blue-loader.svg'
|
import Circle from '../../assets/images/blue-loader.svg'
|
||||||
import tokenLogo from '../../assets/images/token-logo.png'
|
import tokenLogo from '../../assets/images/token-logo.png'
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
@@ -60,7 +60,7 @@ export default function ClaimModal() {
|
|||||||
|
|
||||||
// monitor the status of the claim from contracts and txns
|
// monitor the status of the claim from contracts and txns
|
||||||
const { claimCallback } = useClaimCallback(account)
|
const { claimCallback } = useClaimCallback(account)
|
||||||
const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
|
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(account)
|
||||||
const { claimSubmitted, claimTxn } = useUserHasSubmittedClaim(account ?? undefined)
|
const { claimSubmitted, claimTxn } = useUserHasSubmittedClaim(account ?? undefined)
|
||||||
const claimConfirmed = Boolean(claimTxn?.receipt)
|
const claimConfirmed = Boolean(claimTxn?.receipt)
|
||||||
|
|
||||||
@@ -116,12 +116,12 @@ export default function ClaimModal() {
|
|||||||
)}
|
)}
|
||||||
{userClaimData?.flags?.isLP &&
|
{userClaimData?.flags?.isLP &&
|
||||||
unclaimedAmount &&
|
unclaimedAmount &&
|
||||||
JSBI.greaterThanOrEqual(unclaimedAmount.raw, nonLPAmount) && (
|
JSBI.greaterThanOrEqual(unclaimedAmount.quotient, nonLPAmount) && (
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
<TYPE.subHeader color="white">Liquidity</TYPE.subHeader>
|
<TYPE.subHeader color="white">Liquidity</TYPE.subHeader>
|
||||||
<TYPE.subHeader color="white">
|
<TYPE.subHeader color="white">
|
||||||
{unclaimedAmount
|
{unclaimedAmount
|
||||||
.subtract(new TokenAmount(unclaimedAmount.token, nonLPAmount))
|
.subtract(CurrencyAmount.fromRawAmount(unclaimedAmount.currency, nonLPAmount))
|
||||||
.toFixed(0, { groupSeparator: ',' })}{' '}
|
.toFixed(0, { groupSeparator: ',' })}{' '}
|
||||||
UNI
|
UNI
|
||||||
</TYPE.subHeader>
|
</TYPE.subHeader>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
import { TYPE, CloseIcon } from '../../theme'
|
import { TYPE, CloseIcon } from '../../theme'
|
||||||
import { ButtonError } from '../Button'
|
import { ButtonError } from '../Button'
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { TYPE, StyledInternalLink } from '../../theme'
|
import { TYPE, StyledInternalLink } from '../../theme'
|
||||||
import DoubleCurrencyLogo from '../DoubleLogo'
|
import DoubleCurrencyLogo from '../DoubleLogo'
|
||||||
import { ETHER, TokenAmount } from '@uniswap/sdk-core'
|
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||||
import { JSBI } from '@uniswap/v2-sdk'
|
import JSBI from 'jsbi'
|
||||||
import { ButtonPrimary } from '../Button'
|
import { ButtonPrimary } from '../Button'
|
||||||
import { StakingInfo } from '../../state/stake/hooks'
|
import { StakingInfo } from '../../state/stake/hooks'
|
||||||
import { useColor } from '../../hooks/useColor'
|
import { useColor } from '../../hooks/useColor'
|
||||||
@@ -79,25 +79,25 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
|
|||||||
const isStaking = Boolean(stakingInfo.stakedAmount.greaterThan('0'))
|
const isStaking = Boolean(stakingInfo.stakedAmount.greaterThan('0'))
|
||||||
|
|
||||||
// get the color of the token
|
// get the color of the token
|
||||||
const token = currency0 === ETHER ? token1 : token0
|
const token = currency0.isEther ? token1 : token0
|
||||||
const WETH = currency0 === ETHER ? token0 : token1
|
const WETH = currency0.isEther ? token0 : token1
|
||||||
const backgroundColor = useColor(token)
|
const backgroundColor = useColor(token)
|
||||||
|
|
||||||
const totalSupplyOfStakingToken = useTotalSupply(stakingInfo.stakedAmount.token)
|
const totalSupplyOfStakingToken = useTotalSupply(stakingInfo.stakedAmount.currency)
|
||||||
const [, stakingTokenPair] = useV2Pair(...stakingInfo.tokens)
|
const [, stakingTokenPair] = useV2Pair(...stakingInfo.tokens)
|
||||||
|
|
||||||
// let returnOverMonth: Percent = new Percent('0')
|
// let returnOverMonth: Percent = new Percent('0')
|
||||||
let valueOfTotalStakedAmountInWETH: TokenAmount | undefined
|
let valueOfTotalStakedAmountInWETH: CurrencyAmount<Token> | undefined
|
||||||
if (totalSupplyOfStakingToken && stakingTokenPair) {
|
if (totalSupplyOfStakingToken && stakingTokenPair) {
|
||||||
// take the total amount of LP tokens staked, multiply by ETH value of all LP tokens, divide by all LP tokens
|
// take the total amount of LP tokens staked, multiply by ETH value of all LP tokens, divide by all LP tokens
|
||||||
valueOfTotalStakedAmountInWETH = new TokenAmount(
|
valueOfTotalStakedAmountInWETH = CurrencyAmount.fromRawAmount(
|
||||||
WETH,
|
WETH,
|
||||||
JSBI.divide(
|
JSBI.divide(
|
||||||
JSBI.multiply(
|
JSBI.multiply(
|
||||||
JSBI.multiply(stakingInfo.totalStakedAmount.raw, stakingTokenPair.reserveOf(WETH).raw),
|
JSBI.multiply(stakingInfo.totalStakedAmount.quotient, stakingTokenPair.reserveOf(WETH).quotient),
|
||||||
JSBI.BigInt(2) // this is b/c the value of LP shares are ~double the value of the WETH they entitle owner to
|
JSBI.BigInt(2) // this is b/c the value of LP shares are ~double the value of the WETH they entitle owner to
|
||||||
),
|
),
|
||||||
totalSupplyOfStakingToken.raw
|
totalSupplyOfStakingToken.quotient
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
|
|||||||
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
import { TYPE, CloseIcon } from '../../theme'
|
import { TYPE, CloseIcon } from '../../theme'
|
||||||
import { ButtonConfirmed, ButtonError } from '../Button'
|
import { ButtonConfirmed, ButtonError } from '../Button'
|
||||||
import ProgressCircles from '../ProgressSteps'
|
import ProgressCircles from '../ProgressSteps'
|
||||||
import CurrencyInputPanel from '../CurrencyInputPanel'
|
import CurrencyInputPanel from '../CurrencyInputPanel'
|
||||||
import { Pair } from '@uniswap/v2-sdk'
|
import { Pair } from '@uniswap/v2-sdk'
|
||||||
import { TokenAmount } from '@uniswap/sdk-core'
|
import { Token, CurrencyAmount } from '@uniswap/sdk-core'
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
import { maxAmountSpend } from '../../utils/maxAmountSpend'
|
||||||
import { usePairContract, useStakingContract } from '../../hooks/useContract'
|
import { usePairContract, useStakingContract } from '../../hooks/useContract'
|
||||||
@@ -40,7 +40,7 @@ interface StakingModalProps {
|
|||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onDismiss: () => void
|
onDismiss: () => void
|
||||||
stakingInfo: StakingInfo
|
stakingInfo: StakingInfo
|
||||||
userLiquidityUnstaked: TokenAmount | undefined
|
userLiquidityUnstaked: CurrencyAmount<Token> | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiquidityUnstaked }: StakingModalProps) {
|
export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiquidityUnstaked }: StakingModalProps) {
|
||||||
@@ -48,10 +48,14 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
|
|||||||
|
|
||||||
// track and parse user input
|
// track and parse user input
|
||||||
const [typedValue, setTypedValue] = useState('')
|
const [typedValue, setTypedValue] = useState('')
|
||||||
const { parsedAmount, error } = useDerivedStakeInfo(typedValue, stakingInfo.stakedAmount.token, userLiquidityUnstaked)
|
const { parsedAmount, error } = useDerivedStakeInfo(
|
||||||
|
typedValue,
|
||||||
|
stakingInfo.stakedAmount.currency,
|
||||||
|
userLiquidityUnstaked
|
||||||
|
)
|
||||||
const parsedAmountWrapped = wrappedCurrencyAmount(parsedAmount, chainId)
|
const parsedAmountWrapped = wrappedCurrencyAmount(parsedAmount, chainId)
|
||||||
|
|
||||||
let hypotheticalRewardRate: TokenAmount = new TokenAmount(stakingInfo.rewardRate.token, '0')
|
let hypotheticalRewardRate: CurrencyAmount<Token> = CurrencyAmount.fromRawAmount(stakingInfo.rewardRate.currency, '0')
|
||||||
if (parsedAmountWrapped?.greaterThan('0')) {
|
if (parsedAmountWrapped?.greaterThan('0')) {
|
||||||
hypotheticalRewardRate = stakingInfo.getHypotheticalRewardRate(
|
hypotheticalRewardRate = stakingInfo.getHypotheticalRewardRate(
|
||||||
stakingInfo.stakedAmount.add(parsedAmountWrapped),
|
stakingInfo.stakedAmount.add(parsedAmountWrapped),
|
||||||
@@ -71,7 +75,10 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
|
|||||||
}, [onDismiss])
|
}, [onDismiss])
|
||||||
|
|
||||||
// pair contract for this token to be staked
|
// pair contract for this token to be staked
|
||||||
const dummyPair = new Pair(new TokenAmount(stakingInfo.tokens[0], '0'), new TokenAmount(stakingInfo.tokens[1], '0'))
|
const dummyPair = new Pair(
|
||||||
|
CurrencyAmount.fromRawAmount(stakingInfo.tokens[0], '0'),
|
||||||
|
CurrencyAmount.fromRawAmount(stakingInfo.tokens[1], '0')
|
||||||
|
)
|
||||||
const pairContract = usePairContract(dummyPair.liquidityToken.address)
|
const pairContract = usePairContract(dummyPair.liquidityToken.address)
|
||||||
|
|
||||||
// approval data for stake
|
// approval data for stake
|
||||||
@@ -84,11 +91,11 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
|
|||||||
setAttempting(true)
|
setAttempting(true)
|
||||||
if (stakingContract && parsedAmount && deadline) {
|
if (stakingContract && parsedAmount && deadline) {
|
||||||
if (approval === ApprovalState.APPROVED) {
|
if (approval === ApprovalState.APPROVED) {
|
||||||
await stakingContract.stake(`0x${parsedAmount.raw.toString(16)}`, { gasLimit: 350000 })
|
await stakingContract.stake(`0x${parsedAmount.quotient.toString(16)}`, { gasLimit: 350000 })
|
||||||
} else if (signatureData) {
|
} else if (signatureData) {
|
||||||
stakingContract
|
stakingContract
|
||||||
.stakeWithPermit(
|
.stakeWithPermit(
|
||||||
`0x${parsedAmount.raw.toString(16)}`,
|
`0x${parsedAmount.quotient.toString(16)}`,
|
||||||
signatureData.deadline,
|
signatureData.deadline,
|
||||||
signatureData.v,
|
signatureData.v,
|
||||||
signatureData.r,
|
signatureData.r,
|
||||||
@@ -155,7 +162,7 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
|
|||||||
onUserInput={onUserInput}
|
onUserInput={onUserInput}
|
||||||
onMax={handleMax}
|
onMax={handleMax}
|
||||||
showMaxButton={!atMaxAmount}
|
showMaxButton={!atMaxAmount}
|
||||||
currency={stakingInfo.stakedAmount.token}
|
currency={stakingInfo.stakedAmount.currency}
|
||||||
pair={dummyPair}
|
pair={dummyPair}
|
||||||
label={''}
|
label={''}
|
||||||
customBalanceText={'Available to deposit: '}
|
customBalanceText={'Available to deposit: '}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
import { TYPE, CloseIcon } from '../../theme'
|
import { TYPE, CloseIcon } from '../../theme'
|
||||||
import { ButtonError } from '../Button'
|
import { ButtonError } from '../Button'
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
|
|
||||||
import uImage from '../../assets/images/big_unicorn.png'
|
import uImage from '../../assets/images/big_unicorn.png'
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { Percent, Currency, TradeType } from '@uniswap/sdk-core'
|
||||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||||
import React, { useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
import { ThemeContext } from 'styled-components'
|
import { ThemeContext } from 'styled-components'
|
||||||
import { useUserSlippageTolerance } from '../../state/user/hooks'
|
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
import { computePriceImpactWithMaximumSlippage } from '../../utils/computePriceImpactWithMaximumSlippage'
|
import { computePriceImpactWithMaximumSlippage } from '../../utils/computePriceImpactWithMaximumSlippage'
|
||||||
import { computeRealizedLPFeeAmount } from '../../utils/prices'
|
import { computeRealizedLPFeeAmount } from '../../utils/prices'
|
||||||
@@ -12,14 +12,14 @@ import FormattedPriceImpact from './FormattedPriceImpact'
|
|||||||
import SwapRoute from './SwapRoute'
|
import SwapRoute from './SwapRoute'
|
||||||
|
|
||||||
export interface AdvancedSwapDetailsProps {
|
export interface AdvancedSwapDetailsProps {
|
||||||
trade?: V2Trade | V3Trade
|
trade?: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
|
||||||
|
allowedSlippage: Percent
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
|
export function AdvancedSwapDetails({ trade, allowedSlippage }: AdvancedSwapDetailsProps) {
|
||||||
const theme = useContext(ThemeContext)
|
const theme = useContext(ThemeContext)
|
||||||
|
|
||||||
const realizedLPFee = computeRealizedLPFeeAmount(trade)
|
const realizedLPFee = computeRealizedLPFeeAmount(trade)
|
||||||
const [allowedSlippage] = useUserSlippageTolerance()
|
|
||||||
|
|
||||||
return !trade ? null : (
|
return !trade ? null : (
|
||||||
<AutoColumn gap="8px">
|
<AutoColumn gap="8px">
|
||||||
@@ -55,6 +55,17 @@ export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
|
|||||||
<FormattedPriceImpact priceImpact={computePriceImpactWithMaximumSlippage(trade, allowedSlippage)} />
|
<FormattedPriceImpact priceImpact={computePriceImpactWithMaximumSlippage(trade, allowedSlippage)} />
|
||||||
</TYPE.black>
|
</TYPE.black>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
|
|
||||||
|
<RowBetween>
|
||||||
|
<RowFixed>
|
||||||
|
<TYPE.black fontSize={12} fontWeight={400} color={theme.text2}>
|
||||||
|
Slippage tolerance
|
||||||
|
</TYPE.black>
|
||||||
|
</RowFixed>
|
||||||
|
<TYPE.black textAlign="right" fontSize={12} color={theme.text1}>
|
||||||
|
{allowedSlippage.toFixed(2)}%
|
||||||
|
</TYPE.black>
|
||||||
|
</RowBetween>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { useLastTruthy } from '../../hooks/useLast'
|
import { useLastTruthy } from '../../hooks/useLast'
|
||||||
import { AdvancedSwapDetails, AdvancedSwapDetailsProps } from './AdvancedSwapDetails'
|
import { AdvancedSwapDetails, AdvancedSwapDetailsProps } from './AdvancedSwapDetails'
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import useParsedQueryString from '../../hooks/useParsedQueryString'
|
|||||||
import { DEFAULT_VERSION, Version } from '../../hooks/useToggledVersion'
|
import { DEFAULT_VERSION, Version } from '../../hooks/useToggledVersion'
|
||||||
import { HideSmall, TYPE, SmallOnly } from '../../theme'
|
import { HideSmall, TYPE, SmallOnly } from '../../theme'
|
||||||
import { ButtonPrimary } from '../Button'
|
import { ButtonPrimary } from '../Button'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { Zap } from 'react-feather'
|
import { Zap } from 'react-feather'
|
||||||
|
|
||||||
const ResponsiveButton = styled(ButtonPrimary)`
|
const ResponsiveButton = styled(ButtonPrimary)`
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { currencyEquals, Percent } from '@uniswap/sdk-core'
|
import { Currency, currencyEquals, Percent, TradeType } from '@uniswap/sdk-core'
|
||||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||||
import React, { useCallback, useMemo } from 'react'
|
import React, { useCallback, useMemo } from 'react'
|
||||||
@@ -13,7 +13,11 @@ import SwapModalHeader from './SwapModalHeader'
|
|||||||
* Returns true if the trade requires a confirmation of details before we can submit it
|
* Returns true if the trade requires a confirmation of details before we can submit it
|
||||||
* @param args either a pair of V2 trades or a pair of V3 trades
|
* @param args either a pair of V2 trades or a pair of V3 trades
|
||||||
*/
|
*/
|
||||||
function tradeMeaningfullyDiffers(...args: [V2Trade, V2Trade] | [V3Trade, V3Trade]): boolean {
|
function tradeMeaningfullyDiffers(
|
||||||
|
...args:
|
||||||
|
| [V2Trade<Currency, Currency, TradeType>, V2Trade<Currency, Currency, TradeType>]
|
||||||
|
| [V3Trade<Currency, Currency, TradeType>, V3Trade<Currency, Currency, TradeType>]
|
||||||
|
): boolean {
|
||||||
const [tradeA, tradeB] = args
|
const [tradeA, tradeB] = args
|
||||||
return (
|
return (
|
||||||
tradeA.tradeType !== tradeB.tradeType ||
|
tradeA.tradeType !== tradeB.tradeType ||
|
||||||
@@ -38,8 +42,8 @@ export default function ConfirmSwapModal({
|
|||||||
txHash,
|
txHash,
|
||||||
}: {
|
}: {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
trade: V2Trade | V3Trade | undefined
|
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined
|
||||||
originalTrade: V2Trade | V3Trade | undefined
|
originalTrade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined
|
||||||
attemptingTxn: boolean
|
attemptingTxn: boolean
|
||||||
txHash: string | undefined
|
txHash: string | undefined
|
||||||
recipient: string | null
|
recipient: string | null
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Percent } from '@uniswap/sdk-core'
|
import { Percent } from '@uniswap/sdk-core'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ONE_BIPS } from '../../constants'
|
|
||||||
import { warningSeverity } from '../../utils/prices'
|
import { warningSeverity } from '../../utils/prices'
|
||||||
import { ErrorText, ErrorPill } from './styleds'
|
import { ErrorText, ErrorPill } from './styleds'
|
||||||
|
|
||||||
@@ -10,11 +9,7 @@ import { ErrorText, ErrorPill } from './styleds'
|
|||||||
export default function FormattedPriceImpact({ priceImpact }: { priceImpact?: Percent }) {
|
export default function FormattedPriceImpact({ priceImpact }: { priceImpact?: Percent }) {
|
||||||
return (
|
return (
|
||||||
<ErrorText fontWeight={500} fontSize={12} severity={warningSeverity(priceImpact)}>
|
<ErrorText fontWeight={500} fontSize={12} severity={warningSeverity(priceImpact)}>
|
||||||
{priceImpact
|
{priceImpact ? `${priceImpact.multiply(-1).toFixed(2)}%` : '-'}
|
||||||
? priceImpact.lessThan(ONE_BIPS)
|
|
||||||
? `-${priceImpact.toFixed(2)}%`
|
|
||||||
: `${priceImpact.toFixed(2)}%`
|
|
||||||
: '-'}
|
|
||||||
</ErrorText>
|
</ErrorText>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -22,11 +17,7 @@ export default function FormattedPriceImpact({ priceImpact }: { priceImpact?: Pe
|
|||||||
export function SmallFormattedPriceImpact({ priceImpact }: { priceImpact?: Percent }) {
|
export function SmallFormattedPriceImpact({ priceImpact }: { priceImpact?: Percent }) {
|
||||||
return (
|
return (
|
||||||
<ErrorPill fontWeight={500} fontSize={12} severity={warningSeverity(priceImpact)}>
|
<ErrorPill fontWeight={500} fontSize={12} severity={warningSeverity(priceImpact)}>
|
||||||
{priceImpact
|
{priceImpact ? `(${priceImpact.multiply(-1).toFixed(2)}%)` : '-'}
|
||||||
? priceImpact.lessThan(ONE_BIPS)
|
|
||||||
? `(-${priceImpact.toFixed(2)}%)`
|
|
||||||
: `(-${priceImpact.toFixed(2)}%)`
|
|
||||||
: '-'}
|
|
||||||
</ErrorPill>
|
</ErrorPill>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import Settings from '../Settings'
|
import SettingsTab from '../Settings'
|
||||||
|
import { Percent } from '@uniswap/sdk-core'
|
||||||
|
|
||||||
import { RowBetween, RowFixed } from '../Row'
|
import { RowBetween, RowFixed } from '../Row'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
@@ -11,7 +12,7 @@ const StyledSwapHeader = styled.div`
|
|||||||
color: ${({ theme }) => theme.text2};
|
color: ${({ theme }) => theme.text2};
|
||||||
`
|
`
|
||||||
|
|
||||||
export default function SwapHeader() {
|
export default function SwapHeader({ allowedSlippage }: { allowedSlippage: Percent }) {
|
||||||
return (
|
return (
|
||||||
<StyledSwapHeader>
|
<StyledSwapHeader>
|
||||||
<RowBetween>
|
<RowBetween>
|
||||||
@@ -21,9 +22,7 @@ export default function SwapHeader() {
|
|||||||
</TYPE.black>
|
</TYPE.black>
|
||||||
</RowFixed>
|
</RowFixed>
|
||||||
<RowFixed>
|
<RowFixed>
|
||||||
{/* <TradeInfo disabled={!trade} trade={trade} /> */}
|
<SettingsTab placeholderSlippage={allowedSlippage} />
|
||||||
{/* <div style={{ width: '8px' }}></div> */}
|
|
||||||
<Settings />
|
|
||||||
</RowFixed>
|
</RowFixed>
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
</StyledSwapHeader>
|
</StyledSwapHeader>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Currency, TradeType } from '@uniswap/sdk-core'
|
||||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||||
|
|
||||||
@@ -12,7 +13,7 @@ export default function SwapModalFooter({
|
|||||||
swapErrorMessage,
|
swapErrorMessage,
|
||||||
disabledConfirm,
|
disabledConfirm,
|
||||||
}: {
|
}: {
|
||||||
trade: V2Trade | V3Trade
|
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
|
||||||
onConfirm: () => void
|
onConfirm: () => void
|
||||||
swapErrorMessage: string | undefined
|
swapErrorMessage: string | undefined
|
||||||
disabledConfirm: boolean
|
disabledConfirm: boolean
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Percent, TradeType } from '@uniswap/sdk-core'
|
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
|
||||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||||
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
import { Trade as V3Trade } from '@uniswap/v3-sdk'
|
||||||
import React, { useContext, useState } from 'react'
|
import React, { useContext, useState } from 'react'
|
||||||
@@ -47,7 +47,7 @@ export default function SwapModalHeader({
|
|||||||
showAcceptChanges,
|
showAcceptChanges,
|
||||||
onAcceptChanges,
|
onAcceptChanges,
|
||||||
}: {
|
}: {
|
||||||
trade: V2Trade | V3Trade
|
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
|
||||||
allowedSlippage: Percent
|
allowedSlippage: Percent
|
||||||
recipient: string | null
|
recipient: string | null
|
||||||
showAcceptChanges: boolean
|
showAcceptChanges: boolean
|
||||||
@@ -135,7 +135,7 @@ export default function SwapModalHeader({
|
|||||||
</RowBetween>
|
</RowBetween>
|
||||||
|
|
||||||
<LightCard style={{ padding: '.75rem', marginTop: '0.5rem' }}>
|
<LightCard style={{ padding: '.75rem', marginTop: '0.5rem' }}>
|
||||||
<AdvancedSwapDetails trade={trade} />
|
<AdvancedSwapDetails trade={trade} allowedSlippage={allowedSlippage} />
|
||||||
</LightCard>
|
</LightCard>
|
||||||
|
|
||||||
{showAcceptChanges ? (
|
{showAcceptChanges ? (
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Currency, TradeType } from '@uniswap/sdk-core'
|
||||||
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
import { Trade as V2Trade } from '@uniswap/v2-sdk'
|
||||||
import { Trade as V3Trade, FeeAmount } from '@uniswap/v3-sdk'
|
import { Trade as V3Trade, FeeAmount } from '@uniswap/v3-sdk'
|
||||||
import React, { Fragment, memo, useContext } from 'react'
|
import React, { Fragment, memo, useContext } from 'react'
|
||||||
@@ -14,7 +15,11 @@ function LabeledArrow({}: { fee: FeeAmount }) {
|
|||||||
return <ChevronRight size={14} color={theme.text2} />
|
return <ChevronRight size={14} color={theme.text2} />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(function SwapRoute({ trade }: { trade: V2Trade | V3Trade }) {
|
export default memo(function SwapRoute({
|
||||||
|
trade,
|
||||||
|
}: {
|
||||||
|
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
|
||||||
|
}) {
|
||||||
const tokenPath = trade instanceof V2Trade ? trade.route.path : trade.route.tokenPath
|
const tokenPath = trade instanceof V2Trade ? trade.route.path : trade.route.tokenPath
|
||||||
const theme = useContext(ThemeContext)
|
const theme = useContext(ThemeContext)
|
||||||
return (
|
return (
|
||||||
@@ -25,7 +30,7 @@ export default memo(function SwapRoute({ trade }: { trade: V2Trade | V3Trade })
|
|||||||
return (
|
return (
|
||||||
<Fragment key={i}>
|
<Fragment key={i}>
|
||||||
<Flex alignItems="end">
|
<Flex alignItems="end">
|
||||||
<TYPE.black fontSize={14} color={theme.text1} ml="0.145rem" mr="0.145rem">
|
<TYPE.black color={theme.text1} ml="0.145rem" mr="0.145rem">
|
||||||
{currency.symbol}
|
{currency.symbol}
|
||||||
</TYPE.black>
|
</TYPE.black>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import React, { useCallback } from 'react'
|
import React, { useCallback } from 'react'
|
||||||
import { Price } from '@uniswap/sdk-core'
|
import { Price, Currency } from '@uniswap/sdk-core'
|
||||||
import { useContext } from 'react'
|
import { useContext } from 'react'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
|
|
||||||
import styled, { ThemeContext } from 'styled-components'
|
import styled, { ThemeContext } from 'styled-components'
|
||||||
|
|
||||||
interface TradePriceProps {
|
interface TradePriceProps {
|
||||||
price: Price
|
price: Price<Currency, Currency>
|
||||||
showInverted: boolean
|
showInverted: boolean
|
||||||
setShowInverted: (showInverted: boolean) => void
|
setShowInverted: (showInverted: boolean) => void
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { TYPE, CloseIcon, ExternalLink } from 'theme'
|
import { TYPE, CloseIcon, ExternalLink } from 'theme'
|
||||||
import { ButtonEmpty } from 'components/Button'
|
import { ButtonEmpty } from 'components/Button'
|
||||||
import Modal from 'components/Modal'
|
import Modal from 'components/Modal'
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const ErrorText = styled(Text)<{ severity?: 0 | 1 | 2 | 3 | 4 }>`
|
|||||||
? theme.yellow2
|
? theme.yellow2
|
||||||
: severity === 1
|
: severity === 1
|
||||||
? theme.text1
|
? theme.text1
|
||||||
: theme.green1};
|
: theme.text2};
|
||||||
`
|
`
|
||||||
|
|
||||||
export const ErrorPill = styled(Text)<{ severity?: 0 | 1 | 2 | 3 | 4 }>`
|
export const ErrorPill = styled(Text)<{ severity?: 0 | 1 | 2 | 3 | 4 }>`
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useState } from 'react'
|
|||||||
|
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components/macro'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
import { X } from 'react-feather'
|
import { X } from 'react-feather'
|
||||||
@@ -15,6 +15,7 @@ import { useDelegateCallback } from '../../state/governance/hooks'
|
|||||||
import { useTokenBalance } from '../../state/wallet/hooks'
|
import { useTokenBalance } from '../../state/wallet/hooks'
|
||||||
import { UNI } from '../../constants'
|
import { UNI } from '../../constants'
|
||||||
import { LoadingView, SubmittedView } from '../ModalViews'
|
import { LoadingView, SubmittedView } from '../ModalViews'
|
||||||
|
import { formatTokenAmount } from 'utils/formatTokenAmount'
|
||||||
|
|
||||||
const ContentWrapper = styled(AutoColumn)`
|
const ContentWrapper = styled(AutoColumn)`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -116,7 +117,7 @@ export default function DelegateModal({ isOpen, onDismiss, title }: VoteModalPro
|
|||||||
<LoadingView onDismiss={wrappedOndismiss}>
|
<LoadingView onDismiss={wrappedOndismiss}>
|
||||||
<AutoColumn gap="12px" justify={'center'}>
|
<AutoColumn gap="12px" justify={'center'}>
|
||||||
<TYPE.largeHeader>{usingDelegate ? 'Delegating votes' : 'Unlocking Votes'}</TYPE.largeHeader>
|
<TYPE.largeHeader>{usingDelegate ? 'Delegating votes' : 'Unlocking Votes'}</TYPE.largeHeader>
|
||||||
<TYPE.main fontSize={36}>{uniBalance?.toSignificant(4)}</TYPE.main>
|
<TYPE.main fontSize={36}> {formatTokenAmount(uniBalance, 4)}</TYPE.main>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</LoadingView>
|
</LoadingView>
|
||||||
)}
|
)}
|
||||||
@@ -124,7 +125,7 @@ export default function DelegateModal({ isOpen, onDismiss, title }: VoteModalPro
|
|||||||
<SubmittedView onDismiss={wrappedOndismiss} hash={hash}>
|
<SubmittedView onDismiss={wrappedOndismiss} hash={hash}>
|
||||||
<AutoColumn gap="12px" justify={'center'}>
|
<AutoColumn gap="12px" justify={'center'}>
|
||||||
<TYPE.largeHeader>Transaction Submitted</TYPE.largeHeader>
|
<TYPE.largeHeader>Transaction Submitted</TYPE.largeHeader>
|
||||||
<TYPE.main fontSize={36}>{uniBalance?.toSignificant(4)}</TYPE.main>
|
<TYPE.main fontSize={36}>{formatTokenAmount(uniBalance, 4)}</TYPE.main>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</SubmittedView>
|
</SubmittedView>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user