Compare commits

...

168 Commits

Author SHA1 Message Date
Ian Lapham
49fee909bc update unsupported list (#3071) 2022-01-05 14:07:01 -05:00
Crowdin Bot
f458ec8e12 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-05 19:05:50 +00:00
Jordan Frankfurt
f9fc506db4 chore: merge widgets work into main (#3065)
* feat: design system (#2622)

* refactor: mv setInterval to lib (#2621)

* chore: widget tooling (#2620)

* chore: remove global styles from cosmos viewer

* chore: add generated svgs to bundle

* chore: alias lib within lib

* feat: widgets swap settings and arch (#2629)

* style: update theme

* feat: grid-based row/column

* feat: widget/modal arch

* feat: tooltip arch

* feat: atoms arch

* feat: swap settings

* chore: update deps

* fix: input width

* refactor: modularize Tooltip

* feat: add grow to Row

* style: true prop

* refactor: clean NumericInput

* fix: customizable data structure

* chore: sort styled-components

* fix: import ReactNode

* fix: svgr index generation

* chore: run tests on widgets (#2635)

* chore: widgets nits (#2636)

* fix: restrict type color to theme

* feat: add types

* fix: input width

* fix: header divider

* fix: eslint

* fix: color name

* fix: use inputs for a11y (#2646)

* fix: clearable customizable

* feat: accent hovered select option

* feat: custom slippage color

* fix: use buttons for a11y

* fix: widgets styles (#2654)

* style: add body1

* refactor: modularize theme/components

* refactor: modularize all text Input

* fix: toggle opacity

* test: fixture arch

* feat: rm gas price select

* fix: toggle styles/strings

* feat: mock toggle

* fix: dialog overflow clipping

* fix: mix-blend-mode for safari

* fix: clip-path for safari svg

* fix: mock toggle content

* fix: input margin

* fix: input and cursor

* fix: validate . input

* fix: unused useMemo

* feat: widgets empty state (#2657)

* refactor: TextButton

* feat: inline icons

* feat: swap empty state

* feat: define TokenSelect

* fix: always inline icons

* feat: recent transactions (#2661)

* feat: wallet button

* fix: tx deps

* feat: widgets token select (#2685)

* fix: line height of 1

* fix: button margin

* fix: update styles

* feat: token select

* refactor: mocks and types

* feat: close dialog on esc

* feat: focus input on token select

* refactor: layer swap elements

* feat: use token color

* fix: widget theme

* fix: use vibrant

* chore: lodash types

* fix: fixture props

* feat: smoother color extraction

* fix: vibrant dep

* perf: extract input token color too

* feat: eased token background

* feat: token color prefetching

* chore: mv polished to deps

* chore: package management

* fix: token background transition

* fix: better color transitions

* feat: widgets UI (#2742)

* feat: add swap states

* fix: widget-global box-sizing

* feat: desaturate and opacity on token approval

* feat: red balance on balance insufficient

* fix: states

* feat: action button

* refactor: action button

* feat: loading spinner border

* fix: typescript errors

* fix: token color transition

* fix: unused typings

* feat: swap summary sans tooltip

* refactor: swap state

* feat: swap summary

* refactor: simpler swap names

* fix: cutoffs around footer

* refactor: recent txs

* refactor: buttons

* feat: tx status

* fix: consistent formatting

* feat: tx error

* test: tx error

* test: widget decorator

* style: theming

* fix: clean up dialogs

* fix: clean up swap

* fix: clean up overlays

* fix: action button text on hover

* fix: pickAtom

* fix: pickAtom typings

* fix: smoother error transition

* feat: enter for toggle

* fix: select tabbing

* refactor: simplify dialogs

* feat: widgets polish (#2757)

* fix: loading spinner fallback for safari

* fix: use border for focus

* refactor: token options

* fix: use react toggle event

* fix: token select

* fix: inert content when modal

* fix: windowed token select

* chore: mv windowing utils to deps

* fix: windowing with no rerender

* feat: widget i18n (#2765)

* feat: configure widget i18n

* i18n: wrap translatable strings in macros

* fix: rm lib/locales

* refactor: t to trans

* feat: cosmos locale selector

* chore: widgets nits (#2786)

* fix: tooltip color

* fix: tx ttl tooltip

* fix: tooltip positioning

* fix: token list padding top

* style: responsive tx

* nit: fix summary copy

* chore: change byline

* feat(widgets): add new @web3-react cosmos decorator (#2799)

 add new @web3-react cosmos decorator and provider api to widget

* feat: token color mock (#2878)

* chore: merge main into widgets (#2893)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: center focused outline card (#2625)

* fix: add usdc to arbitrum/optimism common bases (#2641)

* remove WETH from optimism bases (#2640)

* use l2 logos in base pairs (#2634)

* fix: split calls into more chunks if they fail due to out of gas errors (#2630)

* fix: split calls into more chunks if they fail due to out of gas errors

* set to 100m gas

* back to 25m so we batch fewer calls

* do not pass through gas limit, some simplification of the code

* unused import

* fix: restrict @davatar usage to avoid 3p fetches (#2649)

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): ensure chainIds match before fetching pool data (#2652)

* ensure chainIds match before fetching pool data

* debounce both input currencies, and only look for pairs on currencies that share a chainId

* pr feedback

* fix: use optional operator for chainId (#2666)

* chore: update token list (#2670)

* update token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: update token list (#2671)

* update token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: extend privacy and terms (#2623)

* initial iteration

* add logging

* added hook

* polish

* remove unused import

* add hash

* addressed pr feedback

* remove autorouter icon

* use firebase store

* style

* adjust recat ga

* log remove liquidity

* update copy

* addressed pr feedback

* addressed pr feedback

* prevent privacy content from dismissing modal

* make top-level key origin

* use hostname

* restore trm

* chore(i18n): synchronize translations from crowdin [skip ci]

* log full signed tx (#2681)

* refactor monitoring (#2682)

* chore: set final privacy learn more link' (#2684)

* add learn more button

* add final link

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: back arrow bug in wallet modal and fill tx for wallet (#2687)

* add tx to wallet connect

* remove id from env

* restore env

* block import of unsupported tokens (#2673)

generalize custom import token block ui

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(deps-dev): bump @uniswap/token-lists (#2699)

* chore(i18n): synchronize translations from crowdin [skip ci]

* try out 'dimension1' (#2704)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: walletconnect modal re-open after user rejection (#2693)

Co-authored-by: M0kY <moky@example.com>

* chore: update unsupported token list (#2689)

* chore: update unsupported token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: memoize the list stuff so the tokens are consistently clickable (#2724)

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: update cmc list link (#2710)

* update cmc lists

* update CMC url

* add token to unsupported list (#2732)

* don't overwrite localstorage lists when fetch throws (#2723)

* try cd1 for custom dimension (#2734)

* fix: Update walletlink-connector to 6.2.8 (#2655)

* Update walletlink-connector to 6.2.5 which has a walletlink update to support addEthereumChain+switchEthereumChain requests

* Update walletlink-connector to 6.2.7

* Update walletlink-connector to 6.2.8

* fix: Parse latest proposal description correctly

* add proposal start time (#2738)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: #2741 Increase liquidity form off center (#2746)

* fix: bump to latest token list including ENS token

* fix: remove deprecated optimism status url (#2771)

* feat: Menu update. Add help center & feature requests. Remove analytics & github. (#2709)

* Add help center, remove analytics from menu

* Add canny feature requests link, remove github link

* add coffee icon

* no unused imports eslint rule (#2773)

* chore(i18n): synchronize translations from crowdin [skip ci]

* add protocols param to quote endpoint (#2774)

* add protocols param to quote endpoint

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: lint error (#2775)

* fix(optimism): Optimism regenesis support (#2703)

* feat(optimism): optimistic kovan local regenesis changes

* use the regenesis version of the sdk

* remove the override no longer necessary

* diff rpc url

* back to kovan url

* lint error

* Optimism mainnet regenesis test (#2695)

* remove the optimism mainnet specific code and point to the mainnet regenesis rpc url

* point at the old mainnet multicall address

* bump the sdk version

* copy the list

* multicall address regenesis change

* revert the gas limit special casing for optimism

* bump the sdk version

* remove a couple other temporary edits

* unused test case

* specific version of v3-sdk

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: add support for 0.01% tier (#2769)

* chore: add support for 0.01% tier

* only show 1bps on mainnet

* rename VERY_LOW to LOWEST

* upgrade to v3-sdk 3.7.0

* add snapshot testing for lowest tier

* fix integration test

* fix integration test

* use ALL_SUPPORTED_CHAIN_IDS over string all

* consider 0.01% tier in pool (#2770)

* merge main and only consider lowest tier for mainnet

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): update block warning updater to check most recent block timestamp (#2777)

* update block warning updater to check most recent block timestamp

* stop doing dumb state manipulation

* fix: copy in network alert

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): remove redux from chain connectivity (#2781)

* remove redux from chain connectivity

* useMachineTimeMs instead of Date.now to force updates, useCurrentBlockTimestamp

* use useInterval

* change not created font size to 10 (#2785)

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: format date using Date.toLocaleString (#2459)

* fix: format date using Date.toLocaleString

Fixes #2458

* fix: date typings

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: broken link to docs (#2816)

* chore: fix typo in useAllCurrencyCombinations.ts (#2778)

occurence -> occurrence

* chore: update typechain scripts for Windows (#2707)

There are two errors when deploying on Windows system:
1. Using single quotes in path argument doesn't seem to be accepted in typechain command
2. `?(v3-core|v3-periphery)` operator doesn't work

Here are fixes/workarounds.

* perf: lazy load vote related routes (#2468)

* perf: lazy load vote related routes

* wrap Switch in Suspense

* remove exact to match nested routes

* fix nested routes

* split Landing

* fix

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: Enable 3085 requests for coinbase wallet (#2753)

enable 3085 requests for coinbase wallet

* feat: set the auto slippage tolerance by the dollar value of gas (#2815)

* feat: set the auto slippage tolerance by the dollar value of gas

* comments

* min/max at 0.5% to 25%

* oops on constant

* address review feedback

* Fixing #2818 (#2820)

* Fix code style issues with ESLint

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: fix #2818

* chore(i18n): synchronize translations from crowdin [skip ci]

* log an event on max click (#2827)

* Add trailing slash to L2 info links (#2696)

Some links were broken. For example on /pools/ page click the 'Top Pools' CTA. It would mistakenly direct you to info.uniswap.org/optimismpools instead of optimism/pools

* fix(L2): block L2 tokens explicitly linked to L1 tokens that are blocked (#2721)

* block L2 tokens explicitly linked to L1 tokens that are blocked

* Fix code style issues with ESLint

* check for support on all connectors, and disable when the connector (or lack thereof) no longer supports 3085 (#2824)

* feat: display an ENS avatar (#2806)

* feat: ens avatar resolution

* chore: uninstall @davatar/react

* fix: add avatar alt

* feat: support data uris

* feat: support arweave uris

* feat: support erc721 avatars

* feat: support erc1155 avatars

* fix: jazzicon integration

* fix: clean usage of status icon

* fix: fix jazzicon svg offset

* refactor: share status icon component

* fix: pass memoized args to multicall

* Update locales.ts (#2825)

update Finnish from person (Suomalainen) to language (suomi)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore: fix the build blocking linter error

* chore: run linters with auto_fix = false for forks (#2852)

* fix: do not show urls if issue is not occurring on app.uniswap.org (#2855)

* fix: do not show urls if issue is not occurring on app.uniswap.org

fixes https://github.com/Uniswap/interface/issues/2572

* address comment

* fix: remove orphaned node (#2863)

* fix: remove orphaned node

* fix: react cleanup

* refactor: use ref for jazzicon (#2874)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(deps): bump ws from 5.2.2 to 5.2.3 (#2759)

Bumps [ws](https://github.com/websockets/ws) from 5.2.2 to 5.2.3.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/5.2.2...5.2.3)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump url-parse from 1.5.1 to 1.5.3 (#2504)

Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* add more tests for tryParseTick (#2110)

* fix(lint): clean up the eslint config (#2886)

* fix(lint): clean up the eslint config

* Fix code style issues with ESLint

* fix the linter errors that arose from using the proper config

* clean up the rebass text renames

* fix if statement, use the config

* use the same name prefix for both steps

* `TextPreset` -> `ThemedText`

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: Add routes for stakewise tokens (#2832)

* Add additional routes for stakewise tokens

* Reference StakeWise addresses with sdk tokens

* Sort token imports

* chore: yarn-deduplicate

* chore: lint widgets

* fix: use lib useInterval

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Micael Rodrigues <micaelr95@outlook.pt>
Co-authored-by: Justin Domingue <judo@uniswap.org>
Co-authored-by: Moody Salem <moodysalem@users.noreply.github.com>
Co-authored-by: Jordan Frankfurt <jordanwfrankfurt@gmail.com>
Co-authored-by: Ian Lapham <ian@uniswap.org>
Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: M0kY <46133205+M0kY@users.noreply.github.com>
Co-authored-by: M0kY <moky@example.com>
Co-authored-by: Will Hennessy <hennessywill@gmail.com>
Co-authored-by: Brendan Weinstein <65564422+brendanww@users.noreply.github.com>
Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
Co-authored-by: Ben Krochta <35636764+bkrochta@users.noreply.github.com>
Co-authored-by: Moody Salem <moody.salem@gmail.com>
Co-authored-by: Raj <sukhrajghuman@live.com>
Co-authored-by: Ikko Ashimine <eltociear@gmail.com>
Co-authored-by: Matthew Salamon <35425388+Matthews3301@users.noreply.github.com>
Co-authored-by: Sam Chen <chenxsan@gmail.com>
Co-authored-by: Ali Eray Kısabacak <eraykisabacak@hotmail.com>
Co-authored-by: Kimmo S <kkpsiren@gmail.com>
Co-authored-by: Dmitri Tsumak <tsumak.dmitri@gmail.com>

* chore: merge main into widgets (#2923)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: center focused outline card (#2625)

* fix: add usdc to arbitrum/optimism common bases (#2641)

* remove WETH from optimism bases (#2640)

* use l2 logos in base pairs (#2634)

* fix: split calls into more chunks if they fail due to out of gas errors (#2630)

* fix: split calls into more chunks if they fail due to out of gas errors

* set to 100m gas

* back to 25m so we batch fewer calls

* do not pass through gas limit, some simplification of the code

* unused import

* fix: restrict @davatar usage to avoid 3p fetches (#2649)

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): ensure chainIds match before fetching pool data (#2652)

* ensure chainIds match before fetching pool data

* debounce both input currencies, and only look for pairs on currencies that share a chainId

* pr feedback

* fix: use optional operator for chainId (#2666)

* chore: update token list (#2670)

* update token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: update token list (#2671)

* update token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: extend privacy and terms (#2623)

* initial iteration

* add logging

* added hook

* polish

* remove unused import

* add hash

* addressed pr feedback

* remove autorouter icon

* use firebase store

* style

* adjust recat ga

* log remove liquidity

* update copy

* addressed pr feedback

* addressed pr feedback

* prevent privacy content from dismissing modal

* make top-level key origin

* use hostname

* restore trm

* chore(i18n): synchronize translations from crowdin [skip ci]

* log full signed tx (#2681)

* refactor monitoring (#2682)

* chore: set final privacy learn more link' (#2684)

* add learn more button

* add final link

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: back arrow bug in wallet modal and fill tx for wallet (#2687)

* add tx to wallet connect

* remove id from env

* restore env

* block import of unsupported tokens (#2673)

generalize custom import token block ui

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(deps-dev): bump @uniswap/token-lists (#2699)

* chore(i18n): synchronize translations from crowdin [skip ci]

* try out 'dimension1' (#2704)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: walletconnect modal re-open after user rejection (#2693)

Co-authored-by: M0kY <moky@example.com>

* chore: update unsupported token list (#2689)

* chore: update unsupported token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: memoize the list stuff so the tokens are consistently clickable (#2724)

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: update cmc list link (#2710)

* update cmc lists

* update CMC url

* add token to unsupported list (#2732)

* don't overwrite localstorage lists when fetch throws (#2723)

* try cd1 for custom dimension (#2734)

* fix: Update walletlink-connector to 6.2.8 (#2655)

* Update walletlink-connector to 6.2.5 which has a walletlink update to support addEthereumChain+switchEthereumChain requests

* Update walletlink-connector to 6.2.7

* Update walletlink-connector to 6.2.8

* fix: Parse latest proposal description correctly

* add proposal start time (#2738)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: #2741 Increase liquidity form off center (#2746)

* fix: bump to latest token list including ENS token

* fix: remove deprecated optimism status url (#2771)

* feat: Menu update. Add help center & feature requests. Remove analytics & github. (#2709)

* Add help center, remove analytics from menu

* Add canny feature requests link, remove github link

* add coffee icon

* no unused imports eslint rule (#2773)

* chore(i18n): synchronize translations from crowdin [skip ci]

* add protocols param to quote endpoint (#2774)

* add protocols param to quote endpoint

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: lint error (#2775)

* fix(optimism): Optimism regenesis support (#2703)

* feat(optimism): optimistic kovan local regenesis changes

* use the regenesis version of the sdk

* remove the override no longer necessary

* diff rpc url

* back to kovan url

* lint error

* Optimism mainnet regenesis test (#2695)

* remove the optimism mainnet specific code and point to the mainnet regenesis rpc url

* point at the old mainnet multicall address

* bump the sdk version

* copy the list

* multicall address regenesis change

* revert the gas limit special casing for optimism

* bump the sdk version

* remove a couple other temporary edits

* unused test case

* specific version of v3-sdk

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: add support for 0.01% tier (#2769)

* chore: add support for 0.01% tier

* only show 1bps on mainnet

* rename VERY_LOW to LOWEST

* upgrade to v3-sdk 3.7.0

* add snapshot testing for lowest tier

* fix integration test

* fix integration test

* use ALL_SUPPORTED_CHAIN_IDS over string all

* consider 0.01% tier in pool (#2770)

* merge main and only consider lowest tier for mainnet

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): update block warning updater to check most recent block timestamp (#2777)

* update block warning updater to check most recent block timestamp

* stop doing dumb state manipulation

* fix: copy in network alert

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): remove redux from chain connectivity (#2781)

* remove redux from chain connectivity

* useMachineTimeMs instead of Date.now to force updates, useCurrentBlockTimestamp

* use useInterval

* change not created font size to 10 (#2785)

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: format date using Date.toLocaleString (#2459)

* fix: format date using Date.toLocaleString

Fixes #2458

* fix: date typings

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: broken link to docs (#2816)

* chore: fix typo in useAllCurrencyCombinations.ts (#2778)

occurence -> occurrence

* chore: update typechain scripts for Windows (#2707)

There are two errors when deploying on Windows system:
1. Using single quotes in path argument doesn't seem to be accepted in typechain command
2. `?(v3-core|v3-periphery)` operator doesn't work

Here are fixes/workarounds.

* perf: lazy load vote related routes (#2468)

* perf: lazy load vote related routes

* wrap Switch in Suspense

* remove exact to match nested routes

* fix nested routes

* split Landing

* fix

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: Enable 3085 requests for coinbase wallet (#2753)

enable 3085 requests for coinbase wallet

* feat: set the auto slippage tolerance by the dollar value of gas (#2815)

* feat: set the auto slippage tolerance by the dollar value of gas

* comments

* min/max at 0.5% to 25%

* oops on constant

* address review feedback

* Fixing #2818 (#2820)

* Fix code style issues with ESLint

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: fix #2818

* chore(i18n): synchronize translations from crowdin [skip ci]

* log an event on max click (#2827)

* Add trailing slash to L2 info links (#2696)

Some links were broken. For example on /pools/ page click the 'Top Pools' CTA. It would mistakenly direct you to info.uniswap.org/optimismpools instead of optimism/pools

* fix(L2): block L2 tokens explicitly linked to L1 tokens that are blocked (#2721)

* block L2 tokens explicitly linked to L1 tokens that are blocked

* Fix code style issues with ESLint

* check for support on all connectors, and disable when the connector (or lack thereof) no longer supports 3085 (#2824)

* feat: display an ENS avatar (#2806)

* feat: ens avatar resolution

* chore: uninstall @davatar/react

* fix: add avatar alt

* feat: support data uris

* feat: support arweave uris

* feat: support erc721 avatars

* feat: support erc1155 avatars

* fix: jazzicon integration

* fix: clean usage of status icon

* fix: fix jazzicon svg offset

* refactor: share status icon component

* fix: pass memoized args to multicall

* Update locales.ts (#2825)

update Finnish from person (Suomalainen) to language (suomi)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore: fix the build blocking linter error

* chore: run linters with auto_fix = false for forks (#2852)

* fix: do not show urls if issue is not occurring on app.uniswap.org (#2855)

* fix: do not show urls if issue is not occurring on app.uniswap.org

fixes https://github.com/Uniswap/interface/issues/2572

* address comment

* fix: remove orphaned node (#2863)

* fix: remove orphaned node

* fix: react cleanup

* refactor: use ref for jazzicon (#2874)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(deps): bump ws from 5.2.2 to 5.2.3 (#2759)

Bumps [ws](https://github.com/websockets/ws) from 5.2.2 to 5.2.3.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/5.2.2...5.2.3)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump url-parse from 1.5.1 to 1.5.3 (#2504)

Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* add more tests for tryParseTick (#2110)

* fix(lint): clean up the eslint config (#2886)

* fix(lint): clean up the eslint config

* Fix code style issues with ESLint

* fix the linter errors that arose from using the proper config

* clean up the rebass text renames

* fix if statement, use the config

* use the same name prefix for both steps

* `TextPreset` -> `ThemedText`

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: Add routes for stakewise tokens (#2832)

* Add additional routes for stakewise tokens

* Reference StakeWise addresses with sdk tokens

* Sort token imports

* fix: fix layout of proposal list items on the vote page on mobile (#2898)

* fix: fixing layout from using grid to flexbox

* fix: setting WrapSmall to nowrap due to layout issue on mobile

* fix: using width auto instead of disabling flex wrap

Co-authored-by: Julian Anderson <juliancanderson@gmail.com>

* fix: typo in arweave URI recognition (#2901)

* deleted files

* Revert "Merge branch 'main' of https://github.com/Uniswap/interface" (#2912)

This reverts commit bf7a40be7a, reversing
changes made to 097b8361d4.

* fix: inadvertent merges/reverts (#2915)

* Revert "Revert "Merge branch 'main' of https://github.com/Uniswap/interface" (#2912)"

This reverts commit 7d343dcfbd.

* Revert "deleted files"

This reverts commit 097b8361d4.

* refactor: Replace multicall implementation with library (#2768)

- Replace the local implementation of multicall with the new redux-multicall lib
- Create wrappers for redux-multicall hooks to inject block number and chainId

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Micael Rodrigues <micaelr95@outlook.pt>
Co-authored-by: Justin Domingue <judo@uniswap.org>
Co-authored-by: Moody Salem <moodysalem@users.noreply.github.com>
Co-authored-by: Zach Pomerantz <zzmp@uniswap.org>
Co-authored-by: Ian Lapham <ian@uniswap.org>
Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: M0kY <46133205+M0kY@users.noreply.github.com>
Co-authored-by: M0kY <moky@example.com>
Co-authored-by: Will Hennessy <hennessywill@gmail.com>
Co-authored-by: Brendan Weinstein <65564422+brendanww@users.noreply.github.com>
Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
Co-authored-by: Ben Krochta <35636764+bkrochta@users.noreply.github.com>
Co-authored-by: Moody Salem <moody.salem@gmail.com>
Co-authored-by: Raj <sukhrajghuman@live.com>
Co-authored-by: Ikko Ashimine <eltociear@gmail.com>
Co-authored-by: Matthew Salamon <35425388+Matthews3301@users.noreply.github.com>
Co-authored-by: Sam Chen <chenxsan@gmail.com>
Co-authored-by: Ali Eray Kısabacak <eraykisabacak@hotmail.com>
Co-authored-by: Kimmo S <kkpsiren@gmail.com>
Co-authored-by: Dmitri Tsumak <tsumak.dmitri@gmail.com>
Co-authored-by: Julian Anderson <juliancanderson@gmail.com>
Co-authored-by: Carlos Diaz-Padron <carlosdiazpadron@gmail.com>
Co-authored-by: J M Rossy <jm.rossy@gmail.com>

* feat: Multicall lib integration for widgets (#2946)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: center focused outline card (#2625)

* fix: add usdc to arbitrum/optimism common bases (#2641)

* remove WETH from optimism bases (#2640)

* use l2 logos in base pairs (#2634)

* fix: split calls into more chunks if they fail due to out of gas errors (#2630)

* fix: split calls into more chunks if they fail due to out of gas errors

* set to 100m gas

* back to 25m so we batch fewer calls

* do not pass through gas limit, some simplification of the code

* unused import

* fix: restrict @davatar usage to avoid 3p fetches (#2649)

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): ensure chainIds match before fetching pool data (#2652)

* ensure chainIds match before fetching pool data

* debounce both input currencies, and only look for pairs on currencies that share a chainId

* pr feedback

* fix: use optional operator for chainId (#2666)

* chore: update token list (#2670)

* update token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: update token list (#2671)

* update token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: extend privacy and terms (#2623)

* initial iteration

* add logging

* added hook

* polish

* remove unused import

* add hash

* addressed pr feedback

* remove autorouter icon

* use firebase store

* style

* adjust recat ga

* log remove liquidity

* update copy

* addressed pr feedback

* addressed pr feedback

* prevent privacy content from dismissing modal

* make top-level key origin

* use hostname

* restore trm

* chore(i18n): synchronize translations from crowdin [skip ci]

* log full signed tx (#2681)

* refactor monitoring (#2682)

* chore: set final privacy learn more link' (#2684)

* add learn more button

* add final link

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: back arrow bug in wallet modal and fill tx for wallet (#2687)

* add tx to wallet connect

* remove id from env

* restore env

* block import of unsupported tokens (#2673)

generalize custom import token block ui

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(deps-dev): bump @uniswap/token-lists (#2699)

* chore(i18n): synchronize translations from crowdin [skip ci]

* try out 'dimension1' (#2704)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: walletconnect modal re-open after user rejection (#2693)

Co-authored-by: M0kY <moky@example.com>

* chore: update unsupported token list (#2689)

* chore: update unsupported token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: memoize the list stuff so the tokens are consistently clickable (#2724)

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: update cmc list link (#2710)

* update cmc lists

* update CMC url

* add token to unsupported list (#2732)

* don't overwrite localstorage lists when fetch throws (#2723)

* try cd1 for custom dimension (#2734)

* fix: Update walletlink-connector to 6.2.8 (#2655)

* Update walletlink-connector to 6.2.5 which has a walletlink update to support addEthereumChain+switchEthereumChain requests

* Update walletlink-connector to 6.2.7

* Update walletlink-connector to 6.2.8

* fix: Parse latest proposal description correctly

* add proposal start time (#2738)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: #2741 Increase liquidity form off center (#2746)

* fix: bump to latest token list including ENS token

* fix: remove deprecated optimism status url (#2771)

* feat: Menu update. Add help center & feature requests. Remove analytics & github. (#2709)

* Add help center, remove analytics from menu

* Add canny feature requests link, remove github link

* add coffee icon

* no unused imports eslint rule (#2773)

* chore(i18n): synchronize translations from crowdin [skip ci]

* add protocols param to quote endpoint (#2774)

* add protocols param to quote endpoint

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: lint error (#2775)

* fix(optimism): Optimism regenesis support (#2703)

* feat(optimism): optimistic kovan local regenesis changes

* use the regenesis version of the sdk

* remove the override no longer necessary

* diff rpc url

* back to kovan url

* lint error

* Optimism mainnet regenesis test (#2695)

* remove the optimism mainnet specific code and point to the mainnet regenesis rpc url

* point at the old mainnet multicall address

* bump the sdk version

* copy the list

* multicall address regenesis change

* revert the gas limit special casing for optimism

* bump the sdk version

* remove a couple other temporary edits

* unused test case

* specific version of v3-sdk

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: add support for 0.01% tier (#2769)

* chore: add support for 0.01% tier

* only show 1bps on mainnet

* rename VERY_LOW to LOWEST

* upgrade to v3-sdk 3.7.0

* add snapshot testing for lowest tier

* fix integration test

* fix integration test

* use ALL_SUPPORTED_CHAIN_IDS over string all

* consider 0.01% tier in pool (#2770)

* merge main and only consider lowest tier for mainnet

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): update block warning updater to check most recent block timestamp (#2777)

* update block warning updater to check most recent block timestamp

* stop doing dumb state manipulation

* fix: copy in network alert

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): remove redux from chain connectivity (#2781)

* remove redux from chain connectivity

* useMachineTimeMs instead of Date.now to force updates, useCurrentBlockTimestamp

* use useInterval

* change not created font size to 10 (#2785)

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: format date using Date.toLocaleString (#2459)

* fix: format date using Date.toLocaleString

Fixes #2458

* fix: date typings

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: broken link to docs (#2816)

* chore: fix typo in useAllCurrencyCombinations.ts (#2778)

occurence -> occurrence

* chore: update typechain scripts for Windows (#2707)

There are two errors when deploying on Windows system:
1. Using single quotes in path argument doesn't seem to be accepted in typechain command
2. `?(v3-core|v3-periphery)` operator doesn't work

Here are fixes/workarounds.

* perf: lazy load vote related routes (#2468)

* perf: lazy load vote related routes

* wrap Switch in Suspense

* remove exact to match nested routes

* fix nested routes

* split Landing

* fix

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: Enable 3085 requests for coinbase wallet (#2753)

enable 3085 requests for coinbase wallet

* feat: set the auto slippage tolerance by the dollar value of gas (#2815)

* feat: set the auto slippage tolerance by the dollar value of gas

* comments

* min/max at 0.5% to 25%

* oops on constant

* address review feedback

* Fixing #2818 (#2820)

* Fix code style issues with ESLint

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: fix #2818

* chore(i18n): synchronize translations from crowdin [skip ci]

* log an event on max click (#2827)

* Add trailing slash to L2 info links (#2696)

Some links were broken. For example on /pools/ page click the 'Top Pools' CTA. It would mistakenly direct you to info.uniswap.org/optimismpools instead of optimism/pools

* fix(L2): block L2 tokens explicitly linked to L1 tokens that are blocked (#2721)

* block L2 tokens explicitly linked to L1 tokens that are blocked

* Fix code style issues with ESLint

* check for support on all connectors, and disable when the connector (or lack thereof) no longer supports 3085 (#2824)

* feat: display an ENS avatar (#2806)

* feat: ens avatar resolution

* chore: uninstall @davatar/react

* fix: add avatar alt

* feat: support data uris

* feat: support arweave uris

* feat: support erc721 avatars

* feat: support erc1155 avatars

* fix: jazzicon integration

* fix: clean usage of status icon

* fix: fix jazzicon svg offset

* refactor: share status icon component

* fix: pass memoized args to multicall

* Update locales.ts (#2825)

update Finnish from person (Suomalainen) to language (suomi)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore: fix the build blocking linter error

* chore: run linters with auto_fix = false for forks (#2852)

* fix: do not show urls if issue is not occurring on app.uniswap.org (#2855)

* fix: do not show urls if issue is not occurring on app.uniswap.org

fixes https://github.com/Uniswap/interface/issues/2572

* address comment

* fix: remove orphaned node (#2863)

* fix: remove orphaned node

* fix: react cleanup

* refactor: use ref for jazzicon (#2874)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(deps): bump ws from 5.2.2 to 5.2.3 (#2759)

Bumps [ws](https://github.com/websockets/ws) from 5.2.2 to 5.2.3.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/5.2.2...5.2.3)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump url-parse from 1.5.1 to 1.5.3 (#2504)

Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* add more tests for tryParseTick (#2110)

* fix(lint): clean up the eslint config (#2886)

* fix(lint): clean up the eslint config

* Fix code style issues with ESLint

* fix the linter errors that arose from using the proper config

* clean up the rebass text renames

* fix if statement, use the config

* use the same name prefix for both steps

* `TextPreset` -> `ThemedText`

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: Add routes for stakewise tokens (#2832)

* Add additional routes for stakewise tokens

* Reference StakeWise addresses with sdk tokens

* Sort token imports

* fix: fix layout of proposal list items on the vote page on mobile (#2898)

* fix: fixing layout from using grid to flexbox

* fix: setting WrapSmall to nowrap due to layout issue on mobile

* fix: using width auto instead of disabling flex wrap

Co-authored-by: Julian Anderson <juliancanderson@gmail.com>

* fix: typo in arweave URI recognition (#2901)

* deleted files

* Revert "Merge branch 'main' of https://github.com/Uniswap/interface" (#2912)

This reverts commit bf7a40be7a, reversing
changes made to 097b8361d4.

* fix: inadvertent merges/reverts (#2915)

* Revert "Revert "Merge branch 'main' of https://github.com/Uniswap/interface" (#2912)"

This reverts commit 7d343dcfbd.

* Revert "deleted files"

This reverts commit 097b8361d4.

* refactor: Replace multicall implementation with library (#2768)

- Replace the local implementation of multicall with the new redux-multicall lib
- Create wrappers for redux-multicall hooks to inject block number and chainId

* package.json tweaks

* add multicall lib and some basic provider things

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Micael Rodrigues <micaelr95@outlook.pt>
Co-authored-by: Justin Domingue <judo@uniswap.org>
Co-authored-by: Moody Salem <moodysalem@users.noreply.github.com>
Co-authored-by: Zach Pomerantz <zzmp@uniswap.org>
Co-authored-by: Ian Lapham <ian@uniswap.org>
Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: M0kY <46133205+M0kY@users.noreply.github.com>
Co-authored-by: M0kY <moky@example.com>
Co-authored-by: Will Hennessy <hennessywill@gmail.com>
Co-authored-by: Brendan Weinstein <65564422+brendanww@users.noreply.github.com>
Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
Co-authored-by: Ben Krochta <35636764+bkrochta@users.noreply.github.com>
Co-authored-by: Moody Salem <moody.salem@gmail.com>
Co-authored-by: Raj <sukhrajghuman@live.com>
Co-authored-by: Ikko Ashimine <eltociear@gmail.com>
Co-authored-by: Matthew Salamon <35425388+Matthews3301@users.noreply.github.com>
Co-authored-by: Sam Chen <chenxsan@gmail.com>
Co-authored-by: Ali Eray Kısabacak <eraykisabacak@hotmail.com>
Co-authored-by: Kimmo S <kkpsiren@gmail.com>
Co-authored-by: Dmitri Tsumak <tsumak.dmitri@gmail.com>
Co-authored-by: Julian Anderson <juliancanderson@gmail.com>
Co-authored-by: Carlos Diaz-Padron <carlosdiazpadron@gmail.com>
Co-authored-by: J M Rossy <jm.rossy@gmail.com>

* feat: widgets style update (#2939)

* feat: widgets empty state (#2951)

* chore: mv onHover to computed theme; reduce to 0.16

* chore: transparentize primary on hover

* chore: transparentize dynamic primary on hover

* style: restrict icon usage

Restricts icons to lib/icons. This ensures that icons are loaded as singletons outside of the React lifecycle. Doing otherwise hinders performance.

* fix: logo mix-blend-mode

* wip: empty states

* fix: accent/active colors

* wip: empty states

* fix: input hover states

* nit: specific user select

* nit: button transition

* nit: no button transition

* chore: better cosmos toggles

* chore: load inter

* make cosmos work with new required widget props (#2956)

* separate connector atoms (#2959)

* fix: widgets nits sans summary/status (#2960)

* fix: dynamic scrollbar

* feat: system theme hook

* nit: settings

* nit: large settings icons

* fix: accessible color computation

* fix: ignore status scroll for now

* fix: ignore txs scroll for now

* feat: widgets summary (#2980)

* fix: output first in toolbar

* fix: widget height

* feat: token color extraction toggle

* fix: header sizing

* fix: height nits

* chore: re-arch sub pages

* nit: height

* feat: border radius as range

* fix: exclude cosmos setter from hook deps

* feat: default width to 360

* feat: type classes

* fix: header height

* fix: default cosmos width to 360

* refactor: icon button

* wip: summary

* fix: scrollbar

* feat: summary

* fix: summary expando

* fix: widgets transitions (#2983)

* fix: action button height

* fix: summary scrollbar fading

* fix: summary fixture

* fix: action button transitions

* feat: widgets status (#2987)

* fix: action button height

* fix: summary scrollbar fading

* fix: summary fixture

* fix: action button transitions

* refactor: commit spinner as svg asset

* feat: status dialog

* fix: spinner rounding

* feat: widgets fonts and transitions (#2998)

* feat: fonts using @fontsource

* feat: dialog transitions

* fix: swap transitions

* Refactor use active web3 react (#3002)

* separate connector atoms

* refactor cosmos and set up widgets env var

* fix: cosmos modularization (#3014)

* fix: cosmos modularization

* fix: web3 in atom provider

* feat: make connectors resettable

* drop empty test (#3022)

* Revert "feat: make connectors resettable"

This reverts commit db5af68b9b.

* undo dumb open reorder

* bump widget web3-react versions

* bump to fix tests

Co-authored-by: Jordan Frankfurt <jordanwfrankfurt@gmail.com>
Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>

* chore(widgets): Merge main into widgets (#3013)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: center focused outline card (#2625)

* fix: add usdc to arbitrum/optimism common bases (#2641)

* remove WETH from optimism bases (#2640)

* use l2 logos in base pairs (#2634)

* fix: split calls into more chunks if they fail due to out of gas errors (#2630)

* fix: split calls into more chunks if they fail due to out of gas errors

* set to 100m gas

* back to 25m so we batch fewer calls

* do not pass through gas limit, some simplification of the code

* unused import

* fix: restrict @davatar usage to avoid 3p fetches (#2649)

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): ensure chainIds match before fetching pool data (#2652)

* ensure chainIds match before fetching pool data

* debounce both input currencies, and only look for pairs on currencies that share a chainId

* pr feedback

* fix: use optional operator for chainId (#2666)

* chore: update token list (#2670)

* update token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: update token list (#2671)

* update token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: extend privacy and terms (#2623)

* initial iteration

* add logging

* added hook

* polish

* remove unused import

* add hash

* addressed pr feedback

* remove autorouter icon

* use firebase store

* style

* adjust recat ga

* log remove liquidity

* update copy

* addressed pr feedback

* addressed pr feedback

* prevent privacy content from dismissing modal

* make top-level key origin

* use hostname

* restore trm

* chore(i18n): synchronize translations from crowdin [skip ci]

* log full signed tx (#2681)

* refactor monitoring (#2682)

* chore: set final privacy learn more link' (#2684)

* add learn more button

* add final link

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: back arrow bug in wallet modal and fill tx for wallet (#2687)

* add tx to wallet connect

* remove id from env

* restore env

* block import of unsupported tokens (#2673)

generalize custom import token block ui

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(deps-dev): bump @uniswap/token-lists (#2699)

* chore(i18n): synchronize translations from crowdin [skip ci]

* try out 'dimension1' (#2704)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: walletconnect modal re-open after user rejection (#2693)

Co-authored-by: M0kY <moky@example.com>

* chore: update unsupported token list (#2689)

* chore: update unsupported token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: memoize the list stuff so the tokens are consistently clickable (#2724)

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: update cmc list link (#2710)

* update cmc lists

* update CMC url

* add token to unsupported list (#2732)

* don't overwrite localstorage lists when fetch throws (#2723)

* try cd1 for custom dimension (#2734)

* fix: Update walletlink-connector to 6.2.8 (#2655)

* Update walletlink-connector to 6.2.5 which has a walletlink update to support addEthereumChain+switchEthereumChain requests

* Update walletlink-connector to 6.2.7

* Update walletlink-connector to 6.2.8

* fix: Parse latest proposal description correctly

* add proposal start time (#2738)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: #2741 Increase liquidity form off center (#2746)

* fix: bump to latest token list including ENS token

* fix: remove deprecated optimism status url (#2771)

* feat: Menu update. Add help center & feature requests. Remove analytics & github. (#2709)

* Add help center, remove analytics from menu

* Add canny feature requests link, remove github link

* add coffee icon

* no unused imports eslint rule (#2773)

* chore(i18n): synchronize translations from crowdin [skip ci]

* add protocols param to quote endpoint (#2774)

* add protocols param to quote endpoint

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: lint error (#2775)

* fix(optimism): Optimism regenesis support (#2703)

* feat(optimism): optimistic kovan local regenesis changes

* use the regenesis version of the sdk

* remove the override no longer necessary

* diff rpc url

* back to kovan url

* lint error

* Optimism mainnet regenesis test (#2695)

* remove the optimism mainnet specific code and point to the mainnet regenesis rpc url

* point at the old mainnet multicall address

* bump the sdk version

* copy the list

* multicall address regenesis change

* revert the gas limit special casing for optimism

* bump the sdk version

* remove a couple other temporary edits

* unused test case

* specific version of v3-sdk

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(i18n): synchronize translations from crowdin [skip ci]

* feat: add support for 0.01% tier (#2769)

* chore: add support for 0.01% tier

* only show 1bps on mainnet

* rename VERY_LOW to LOWEST

* upgrade to v3-sdk 3.7.0

* add snapshot testing for lowest tier

* fix integration test

* fix integration test

* use ALL_SUPPORTED_CHAIN_IDS over string all

* consider 0.01% tier in pool (#2770)

* merge main and only consider lowest tier for mainnet

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): update block warning updater to check most recent block timestamp (#2777)

* update block warning updater to check most recent block timestamp

* stop doing dumb state manipulation

* fix: copy in network alert

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix(L2): remove redux from chain connectivity (#2781)

* remove redux from chain connectivity

* useMachineTimeMs instead of Date.now to force updates, useCurrentBlockTimestamp

* use useInterval

* change not created font size to 10 (#2785)

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: format date using Date.toLocaleString (#2459)

* fix: format date using Date.toLocaleString

Fixes #2458

* fix: date typings

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: broken link to docs (#2816)

* chore: fix typo in useAllCurrencyCombinations.ts (#2778)

occurence -> occurrence

* chore: update typechain scripts for Windows (#2707)

There are two errors when deploying on Windows system:
1. Using single quotes in path argument doesn't seem to be accepted in typechain command
2. `?(v3-core|v3-periphery)` operator doesn't work

Here are fixes/workarounds.

* perf: lazy load vote related routes (#2468)

* perf: lazy load vote related routes

* wrap Switch in Suspense

* remove exact to match nested routes

* fix nested routes

* split Landing

* fix

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: Enable 3085 requests for coinbase wallet (#2753)

enable 3085 requests for coinbase wallet

* feat: set the auto slippage tolerance by the dollar value of gas (#2815)

* feat: set the auto slippage tolerance by the dollar value of gas

* comments

* min/max at 0.5% to 25%

* oops on constant

* address review feedback

* Fixing #2818 (#2820)

* Fix code style issues with ESLint

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: fix #2818

* chore(i18n): synchronize translations from crowdin [skip ci]

* log an event on max click (#2827)

* Add trailing slash to L2 info links (#2696)

Some links were broken. For example on /pools/ page click the 'Top Pools' CTA. It would mistakenly direct you to info.uniswap.org/optimismpools instead of optimism/pools

* fix(L2): block L2 tokens explicitly linked to L1 tokens that are blocked (#2721)

* block L2 tokens explicitly linked to L1 tokens that are blocked

* Fix code style issues with ESLint

* check for support on all connectors, and disable when the connector (or lack thereof) no longer supports 3085 (#2824)

* feat: display an ENS avatar (#2806)

* feat: ens avatar resolution

* chore: uninstall @davatar/react

* fix: add avatar alt

* feat: support data uris

* feat: support arweave uris

* feat: support erc721 avatars

* feat: support erc1155 avatars

* fix: jazzicon integration

* fix: clean usage of status icon

* fix: fix jazzicon svg offset

* refactor: share status icon component

* fix: pass memoized args to multicall

* Update locales.ts (#2825)

update Finnish from person (Suomalainen) to language (suomi)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore: fix the build blocking linter error

* chore: run linters with auto_fix = false for forks (#2852)

* fix: do not show urls if issue is not occurring on app.uniswap.org (#2855)

* fix: do not show urls if issue is not occurring on app.uniswap.org

fixes https://github.com/Uniswap/interface/issues/2572

* address comment

* fix: remove orphaned node (#2863)

* fix: remove orphaned node

* fix: react cleanup

* refactor: use ref for jazzicon (#2874)

* chore(i18n): synchronize translations from crowdin [skip ci]

* chore(deps): bump ws from 5.2.2 to 5.2.3 (#2759)

Bumps [ws](https://github.com/websockets/ws) from 5.2.2 to 5.2.3.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/5.2.2...5.2.3)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps): bump url-parse from 1.5.1 to 1.5.3 (#2504)

Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* add more tests for tryParseTick (#2110)

* fix(lint): clean up the eslint config (#2886)

* fix(lint): clean up the eslint config

* Fix code style issues with ESLint

* fix the linter errors that arose from using the proper config

* clean up the rebass text renames

* fix if statement, use the config

* use the same name prefix for both steps

* `TextPreset` -> `ThemedText`

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>

* fix: Add routes for stakewise tokens (#2832)

* Add additional routes for stakewise tokens

* Reference StakeWise addresses with sdk tokens

* Sort token imports

* fix: fix layout of proposal list items on the vote page on mobile (#2898)

* fix: fixing layout from using grid to flexbox

* fix: setting WrapSmall to nowrap due to layout issue on mobile

* fix: using width auto instead of disabling flex wrap

Co-authored-by: Julian Anderson <juliancanderson@gmail.com>

* fix: typo in arweave URI recognition (#2901)

* deleted files

* Revert "Merge branch 'main' of https://github.com/Uniswap/interface" (#2912)

This reverts commit bf7a40be7a, reversing
changes made to 097b8361d4.

* fix: inadvertent merges/reverts (#2915)

* Revert "Revert "Merge branch 'main' of https://github.com/Uniswap/interface" (#2912)"

This reverts commit 7d343dcfbd.

* Revert "deleted files"

This reverts commit 097b8361d4.

* refactor: Replace multicall implementation with library (#2768)

- Replace the local implementation of multicall with the new redux-multicall lib
- Create wrappers for redux-multicall hooks to inject block number and chainId

* fix: introduce safeNamehash (#2925)

* namehash -> safeNamehash where necessary

* cleanup

* address comment

* feat: Add learn more link in TRM description (#2919)

* Add learn more link in TRM description

* Update src/components/PrivacyPolicy/index.tsx

Co-authored-by: Justin Domingue <judo@uniswap.org>

* give a bit more gas to balanceOf (#2943)

* fix: memoize hooks from /swap (#2949)

* fix: memoize hooks from /swap

* chore: rm console

* add fix for polygon proposal title (#2974)

* fix: display Uniswap token list in UI (#2821)

* fix: display Uniswap token list in UI

* chore: remove default-token-list build dependency

* fix: use ENS name for Uniswap token list

* fix: change Uniswap token list url

* fix: extend transaction deadline to 3 days (#2982)

* feat: integrate SwapRouter02 on L1/L2 + gas ui

* client-side smart order router support
* support auto router on L2s
* add swap router version in approval/swap callback GA events to save $ on approval txs
* add persistent UI view of gas estimate on L1s

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: Ian Lapham <ian@uniswap.org>
Co-authored-by: Callil Capuozzo <callil.capuozzo@gmail.com>

* Update CONTRIBUTING.md (#2992)

* feat: Update contribution spec (#2993)

* Update CONTRIBUTING.md (#2994)

* Update CONTRIBUTING.md (#2995)

* feat: Update contribution spec (#2996)

* chore(i18n): synchronize translations from crowdin [skip ci]

* fix: double scroll in manage token list (#3020)

* fix double scroll

* remove bottom padding

* restrict walletlink to mainnet only (#3024)

* increase warning timer (#3004)

* add index.html styles to widget

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Micael Rodrigues <micaelr95@outlook.pt>
Co-authored-by: Justin Domingue <judo@uniswap.org>
Co-authored-by: Moody Salem <moodysalem@users.noreply.github.com>
Co-authored-by: Zach Pomerantz <zzmp@uniswap.org>
Co-authored-by: Ian Lapham <ian@uniswap.org>
Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: M0kY <46133205+M0kY@users.noreply.github.com>
Co-authored-by: M0kY <moky@example.com>
Co-authored-by: Will Hennessy <hennessywill@gmail.com>
Co-authored-by: Brendan Weinstein <65564422+brendanww@users.noreply.github.com>
Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
Co-authored-by: Ben Krochta <35636764+bkrochta@users.noreply.github.com>
Co-authored-by: Moody Salem <moody.salem@gmail.com>
Co-authored-by: Raj <sukhrajghuman@live.com>
Co-authored-by: Ikko Ashimine <eltociear@gmail.com>
Co-authored-by: Matthew Salamon <35425388+Matthews3301@users.noreply.github.com>
Co-authored-by: Sam Chen <chenxsan@gmail.com>
Co-authored-by: Ali Eray Kısabacak <eraykisabacak@hotmail.com>
Co-authored-by: Kimmo S <kkpsiren@gmail.com>
Co-authored-by: Dmitri Tsumak <tsumak.dmitri@gmail.com>
Co-authored-by: Julian Anderson <juliancanderson@gmail.com>
Co-authored-by: Carlos Diaz-Padron <carlosdiazpadron@gmail.com>
Co-authored-by: J M Rossy <jm.rossy@gmail.com>
Co-authored-by: Barry G <bgitarts@gmail.com>
Co-authored-by: Callil Capuozzo <callil.capuozzo@gmail.com>
Co-authored-by: Tina Zheng <59578595+tinaszheng@users.noreply.github.com>

* feat: widgets transitions (#3007)

* fix: logo target

* feat: settings transition

* feat: reverse transition

* fix: transitions will-change and durations

* fix: logo color

* fix: only will-change transform

* fix: header targets

* fix: clip modal transitions

* fix: token select header

* fix: safari transparent gradients

* fix: safari scrollbar

* fix: scroll overlay

* fix: safari bounce jank

* fix: firefox overscroll

* refactor: scrollbar hook

* feat: native event hook

* fix: details nowrap

* fix: settings cog transition

* feat: expando icon

* fix: expando transition

* refactor: cosmos web3 integration (#3052)

* chore: use zustand 4.0.0-beta for dynamic stores

* chore: use strict mode

* refactor: clean connector state

* chore: mv web3 state to cosmos selectors

* chore: dedup yarn.lock

* chore: define EthereumProvider in lib

* fix: destructure would not compile

* fix: make it bundle

* chore: prune deps

* refactor: use error handler instead of GA

* chore: add make-plural

* chore: add redux

* chore: yarn dedup

* chore: do not (re)load default locale

* fix: center error headings

* feat: error dialog for boundary

* fix: tighten up transitions

* test: include bundle depcheck

* fix: rm console

* fix: do not load empty sourceLocale

* fix: no lingui defaults

* refactor: mv svg to assets/svg

* chore: block font display

* fix: remove manual zustand resolution

* fix: svg generation script

Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>

* chore: widget placeholders (#3061)

* chore: update comments

- typo
- performance comment was performant on retest

* nit: status placeholders

- prevent flashes of rerendering from lazy-loaded elements

* chore: initialize cosmos with json rpc

* refactor: token img component

- modularize the TokenImg
- add a placeholder for UX and broken images

* fix: recent tx token img usage

* pr feedback

* undo REACT_APP_IS_WIDGET network ternary

Co-authored-by: Zach Pomerantz <zzmp@uniswap.org>
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Micael Rodrigues <micaelr95@outlook.pt>
Co-authored-by: Justin Domingue <judo@uniswap.org>
Co-authored-by: Moody Salem <moodysalem@users.noreply.github.com>
Co-authored-by: Ian Lapham <ian@uniswap.org>
Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: M0kY <46133205+M0kY@users.noreply.github.com>
Co-authored-by: M0kY <moky@example.com>
Co-authored-by: Will Hennessy <hennessywill@gmail.com>
Co-authored-by: Brendan Weinstein <65564422+brendanww@users.noreply.github.com>
Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
Co-authored-by: Ben Krochta <35636764+bkrochta@users.noreply.github.com>
Co-authored-by: Moody Salem <moody.salem@gmail.com>
Co-authored-by: Raj <sukhrajghuman@live.com>
Co-authored-by: Ikko Ashimine <eltociear@gmail.com>
Co-authored-by: Matthew Salamon <35425388+Matthews3301@users.noreply.github.com>
Co-authored-by: Sam Chen <chenxsan@gmail.com>
Co-authored-by: Ali Eray Kısabacak <eraykisabacak@hotmail.com>
Co-authored-by: Kimmo S <kkpsiren@gmail.com>
Co-authored-by: Dmitri Tsumak <tsumak.dmitri@gmail.com>
Co-authored-by: Julian Anderson <juliancanderson@gmail.com>
Co-authored-by: Carlos Diaz-Padron <carlosdiazpadron@gmail.com>
Co-authored-by: J M Rossy <jm.rossy@gmail.com>
Co-authored-by: Barry G <bgitarts@gmail.com>
Co-authored-by: Callil Capuozzo <callil.capuozzo@gmail.com>
Co-authored-by: Tina Zheng <59578595+tinaszheng@users.noreply.github.com>
2022-01-05 12:38:53 -06:00
yj
5b7a80d10d fix: Add ENSName and address check to Web3Status (#3040)
* Add ENSName and address check to Web3Status

Issue #2838

* Update useENSName.ts

Do the forward ENSAddress check in useENSName

* Update index.tsx

Revert ENSAddress check, which has been moved into ENSName hook

* Update useENSName.ts

Correcting the equality check (was testing that things work, and made a wrong commit)

* add comment, change var names

Co-authored-by: Tina Zheng <tina.s.zheng+github@gmail.com>
2021-12-29 20:04:09 -08:00
Crowdin Bot
db8dab4559 chore(i18n): synchronize translations from crowdin [skip ci] 2021-12-28 17:11:16 +00:00
Crowdin Bot
7cc1b899ea chore(i18n): synchronize translations from crowdin [skip ci] 2021-12-24 21:06:39 +00:00
Crowdin Bot
339a35cb1b chore(i18n): synchronize translations from crowdin [skip ci] 2021-12-24 07:06:39 +00:00
Moody Salem
e2bd8020f3 fix(polygon): enable the smart order router for polygon (#3037)
* fix(polygon): enable the smart order router for polygon

* show gas estimates for polygon
2021-12-23 20:36:56 -05:00
Crowdin Bot
571a932d6e chore(i18n): synchronize translations from crowdin [skip ci] 2021-12-23 21:06:33 +00:00
Callil Capuozzo
3923438011 fix(style): improve the bridge assets style (#3036)
* Re-style bridge cards

* Tweaks

- Header button height and color treatment refinement
- Small sizing issues

* Address comments

* remove network alert state

* code style nits

* remove unused parameter, rename

* copy edit

Co-authored-by: Moody Salem <moody.salem@gmail.com>
2021-12-23 15:13:50 -05:00
Crowdin Bot
4ed9c7ba94 chore(i18n): synchronize translations from crowdin [skip ci] 2021-12-23 18:06:38 +00:00
Crowdin Bot
1ead35e782 chore(i18n): synchronize translations from crowdin [skip ci] 2021-12-23 17:11:21 +00:00
Crowdin Bot
0af516b884 chore(i18n): synchronize translations from crowdin [skip ci] 2021-12-23 16:07:14 +00:00
Moody Salem
13c42a384b fix(network switch): do not show failed to switch networks for successful network switches 2021-12-23 10:18:58 -05:00
Tina Zheng
458e04f94c feat: add santa hat to unicorn logo for the holidays 🎅🏼 (#3027)
* add santa hat to logo

* make generic component

* add 24th to christmas

* oops
2021-12-22 14:34:40 -08:00
Moody Salem
587edf46ea fix(polygon): infoLink should end in forward slash 2021-12-22 15:15:32 -05:00
Moody Salem
768f7659d2 fix(polygon): add missing router addresses 2021-12-22 15:08:11 -05:00
Crowdin Bot
96db27722b chore(i18n): synchronize translations from crowdin [skip ci] 2021-12-22 19:47:25 +00:00
Moody Salem
f047f0d196 feat(polygon): polygon mainnet and testnet support (#3015)
* feat(polygon): polygon mainnet and testnet support

WIP! DO NOT USE

* fix unit test

* fix explorer links

* compute usdc prices

* - fix the header currency label
- fix unit tests

* polygon gradient colors

* chore: adding weth to common bases (#3025)

* adding weth to common bases

* adding usdc and dai

* adding usdt and wbtc

* fix a bunch of polish issues
- 3085 detection
- some wrapping stuff
- the network selector dropdown

* fix wrap/unwrap notification text on polygon

* background color per the figma

* subgraph url

* fix the re-render blinking on the network selector

* failed network switch

* clean up duplicate code in the network switching functions

* fix text color in the privacy notice on light mode

* add some routing constants for polygon

* do not show the separator in the trade route if auto router is not supported

* - network switching without a wallet connected
- remove v2 stuff from pool page when n/a
- remove WMATIC from common bases on polygon

* background colors of network alert

* oops fix background on network alert

* clean up optimism labels

* fix alignment of text on downtime warning

* finish the network alert styles

Co-authored-by: Sara Reynolds <30504811+snreynolds@users.noreply.github.com>
2021-12-22 14:25:10 -05:00
Jordan Frankfurt
7ac1ed3f52 increase warning timer (#3004) 2021-12-22 11:18:53 -05:00
Tina Zheng
205412fe1e restrict walletlink to mainnet only (#3024) 2021-12-21 14:37:42 -08:00
Tina Zheng
43e1fe9764 fix: double scroll in manage token list (#3020)
* fix double scroll

* remove bottom padding
2021-12-21 14:37:30 -08:00
Crowdin Bot
e9a9dd9779 chore(i18n): synchronize translations from crowdin [skip ci] 2021-12-20 15:59:30 +00:00
Ian Lapham
fa3325b7e4 feat: Update contribution spec (#2996) 2021-12-16 16:08:45 -05:00
Ian Lapham
19aa7173ab Update CONTRIBUTING.md (#2995) 2021-12-16 16:04:32 -05:00
Ian Lapham
a3238c701a Update CONTRIBUTING.md (#2994) 2021-12-16 15:46:26 -05:00
Ian Lapham
82a763f905 feat: Update contribution spec (#2993) 2021-12-16 15:39:28 -05:00
Ian Lapham
61e0ce096b Update CONTRIBUTING.md (#2992) 2021-12-16 15:36:48 -05:00
Justin Domingue
9e1a775c13 feat: integrate SwapRouter02 on L1/L2 + gas ui
* client-side smart order router support
* support auto router on L2s
* add swap router version in approval/swap callback GA events to save $ on approval txs
* add persistent UI view of gas estimate on L1s

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: Ian Lapham <ian@uniswap.org>
Co-authored-by: Callil Capuozzo <callil.capuozzo@gmail.com>
2021-12-16 14:44:03 -05:00
Barry G
642a4177d8 fix: extend transaction deadline to 3 days (#2982) 2021-12-15 16:52:41 -08:00
Ben Krochta
37e085763c fix: display Uniswap token list in UI (#2821)
* fix: display Uniswap token list in UI

* chore: remove default-token-list build dependency

* fix: use ENS name for Uniswap token list

* fix: change Uniswap token list url
2021-12-13 19:38:37 -05:00
Noah Zinsmeister
e2baa051c5 add fix for polygon proposal title (#2974) 2021-12-13 16:28:37 -05:00
Zach Pomerantz
a5b152da06 fix: memoize hooks from /swap (#2949)
* fix: memoize hooks from /swap

* chore: rm console
2021-12-09 13:06:55 -08:00
Noah Zinsmeister
38cf4f46d7 give a bit more gas to balanceOf (#2943) 2021-12-07 18:07:11 -05:00
Will Hennessy
744c313ecf feat: Add learn more link in TRM description (#2919)
* Add learn more link in TRM description

* Update src/components/PrivacyPolicy/index.tsx

Co-authored-by: Justin Domingue <judo@uniswap.org>
2021-12-06 12:26:33 -05:00
Noah Zinsmeister
b967b1b236 fix: introduce safeNamehash (#2925)
* namehash -> safeNamehash where necessary

* cleanup

* address comment
2021-12-03 16:45:33 -05:00
J M Rossy
596ea03043 refactor: Replace multicall implementation with library (#2768)
- Replace the local implementation of multicall with the new redux-multicall lib
- Create wrappers for redux-multicall hooks to inject block number and chainId
2021-12-03 06:29:39 -05:00
Zach Pomerantz
e81e8a8f71 fix: inadvertent merges/reverts (#2915)
* Revert "Revert "Merge branch 'main' of https://github.com/Uniswap/interface" (#2912)"

This reverts commit 7d343dcfbd.

* Revert "deleted files"

This reverts commit 097b8361d4.
2021-12-02 10:35:39 -08:00
Justin Domingue
7d343dcfbd Revert "Merge branch 'main' of https://github.com/Uniswap/interface" (#2912)
This reverts commit bf7a40be7a, reversing
changes made to 097b8361d4.
2021-12-02 13:12:22 -05:00
Justin Domingue
bf7a40be7a Merge branch 'main' of https://github.com/Uniswap/interface 2021-12-02 11:15:09 -05:00
Justin Domingue
097b8361d4 deleted files 2021-12-02 11:14:41 -05:00
Carlos Diaz-Padron
82843ff16a fix: typo in arweave URI recognition (#2901) 2021-12-01 13:26:46 -05:00
Moody Salem
890471f590 fix: fix layout of proposal list items on the vote page on mobile (#2898)
* fix: fixing layout from using grid to flexbox

* fix: setting WrapSmall to nowrap due to layout issue on mobile

* fix: using width auto instead of disabling flex wrap

Co-authored-by: Julian Anderson <juliancanderson@gmail.com>
2021-12-01 10:23:02 -05:00
Dmitri Tsumak
478ee7ba14 fix: Add routes for stakewise tokens (#2832)
* Add additional routes for stakewise tokens

* Reference StakeWise addresses with sdk tokens

* Sort token imports
2021-11-30 15:25:50 -05:00
Moody Salem
745be977ef fix(lint): clean up the eslint config (#2886)
* fix(lint): clean up the eslint config

* Fix code style issues with ESLint

* fix the linter errors that arose from using the proper config

* clean up the rebass text renames

* fix if statement, use the config

* use the same name prefix for both steps

* `TextPreset` -> `ThemedText`

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
2021-11-30 15:20:59 -05:00
Justin Domingue
0e25c055fb add more tests for tryParseTick (#2110) 2021-11-30 11:44:40 -05:00
dependabot[bot]
82a079935e chore(deps): bump url-parse from 1.5.1 to 1.5.3 (#2504)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.1 to 1.5.3.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.1...1.5.3)

---
updated-dependencies:
- dependency-name: url-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-30 11:40:15 -05:00
dependabot[bot]
876c1539d4 chore(deps): bump ws from 5.2.2 to 5.2.3 (#2759)
Bumps [ws](https://github.com/websockets/ws) from 5.2.2 to 5.2.3.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/5.2.2...5.2.3)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-30 11:38:15 -05:00
Crowdin Bot
f43fd89884 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-30 02:11:35 +00:00
Zach Pomerantz
efdfdc9083 refactor: use ref for jazzicon (#2874) 2021-11-29 15:49:01 -08:00
Zach Pomerantz
709f0299e2 fix: remove orphaned node (#2863)
* fix: remove orphaned node

* fix: react cleanup
2021-11-29 12:15:08 -08:00
Moody Salem
6b57ffe311 fix: do not show urls if issue is not occurring on app.uniswap.org (#2855)
* fix: do not show urls if issue is not occurring on app.uniswap.org

fixes https://github.com/Uniswap/interface/issues/2572

* address comment
2021-11-29 12:44:14 -05:00
Moody Salem
f7ecdc4332 chore: run linters with auto_fix = false for forks (#2852) 2021-11-28 12:30:58 -05:00
Moody Salem
b1009b0e03 chore: fix the build blocking linter error 2021-11-28 12:07:51 -05:00
Crowdin Bot
5a4c7890c6 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-25 20:06:51 +00:00
Kimmo S
5a3c91f19f Update locales.ts (#2825)
update Finnish from person (Suomalainen) to language (suomi)
2021-11-23 10:04:14 -05:00
Zach Pomerantz
d5c4ee0342 feat: display an ENS avatar (#2806)
* feat: ens avatar resolution

* chore: uninstall @davatar/react

* fix: add avatar alt

* feat: support data uris

* feat: support arweave uris

* feat: support erc721 avatars

* feat: support erc1155 avatars

* fix: jazzicon integration

* fix: clean usage of status icon

* fix: fix jazzicon svg offset

* refactor: share status icon component

* fix: pass memoized args to multicall
2021-11-22 10:55:25 -08:00
Jordan Frankfurt
262d984f92 check for support on all connectors, and disable when the connector (or lack thereof) no longer supports 3085 (#2824) 2021-11-22 12:33:52 -05:00
Lint Action
7781f5112e Fix code style issues with ESLint 2021-11-22 16:08:21 +00:00
Jordan Frankfurt
204e44ac40 fix(L2): block L2 tokens explicitly linked to L1 tokens that are blocked (#2721)
* block L2 tokens explicitly linked to L1 tokens that are blocked
2021-11-22 11:04:36 -05:00
Will Hennessy
7c9d9bdb03 Add trailing slash to L2 info links (#2696)
Some links were broken. For example on /pools/ page click the 'Top Pools' CTA. It would mistakenly direct you to info.uniswap.org/optimismpools instead of optimism/pools
2021-11-22 09:32:34 -05:00
Justin Domingue
cb0ea3f14d log an event on max click (#2827) 2021-11-22 09:27:29 -05:00
Crowdin Bot
e54ffcc483 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-19 16:06:45 +00:00
Justin Domingue
8a72b374a8 fix: fix #2818 2021-11-19 10:10:45 -05:00
Crowdin Bot
3f64415906 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-18 19:06:37 +00:00
Lint Action
41a4500f41 Fix code style issues with ESLint 2021-11-18 18:27:24 +00:00
Ali Eray Kısabacak
093dc66cfe Fixing #2818 (#2820) 2021-11-18 13:23:13 -05:00
Moody Salem
b10729d217 feat: set the auto slippage tolerance by the dollar value of gas (#2815)
* feat: set the auto slippage tolerance by the dollar value of gas

* comments

* min/max at 0.5% to 25%

* oops on constant

* address review feedback
2021-11-18 13:05:29 -05:00
Brendan Weinstein
9b0fa8a2c4 fix: Enable 3085 requests for coinbase wallet (#2753)
enable 3085 requests for coinbase wallet
2021-11-18 12:29:56 -05:00
Crowdin Bot
82c026872f chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-18 06:11:55 +00:00
Sam Chen
222a6d53bc perf: lazy load vote related routes (#2468)
* perf: lazy load vote related routes

* wrap Switch in Suspense

* remove exact to match nested routes

* fix nested routes

* split Landing

* fix
2021-11-17 22:01:45 -08:00
Matthew Salamon
0f35f6ee93 chore: update typechain scripts for Windows (#2707)
There are two errors when deploying on Windows system:
1. Using single quotes in path argument doesn't seem to be accepted in typechain command
2. `?(v3-core|v3-periphery)` operator doesn't work

Here are fixes/workarounds.
2021-11-17 21:00:37 -08:00
Ikko Ashimine
7b83e3968f chore: fix typo in useAllCurrencyCombinations.ts (#2778)
occurence -> occurrence
2021-11-17 20:40:58 -08:00
Raj
7938273c0c fix: broken link to docs (#2816) 2021-11-17 20:30:54 -08:00
Crowdin Bot
51a4504c75 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-18 03:06:35 +00:00
Zach Pomerantz
b2697f0077 fix: format date using Date.toLocaleString (#2459)
* fix: format date using Date.toLocaleString

Fixes #2458

* fix: date typings
2021-11-16 16:20:46 -08:00
Crowdin Bot
34a58851f7 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-14 14:06:34 +00:00
Will Hennessy
5a20dc82cd change not created font size to 10 (#2785) 2021-11-12 15:23:15 -05:00
Jordan Frankfurt
d1627a6c36 fix(L2): remove redux from chain connectivity (#2781)
* remove redux from chain connectivity

* useMachineTimeMs instead of Date.now to force updates, useCurrentBlockTimestamp

* use useInterval
2021-11-12 13:24:45 -06:00
Crowdin Bot
55c971892c chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-12 17:09:58 +00:00
Moody Salem
68f8576499 fix: copy in network alert 2021-11-12 11:50:07 -05:00
Jordan Frankfurt
d0be3bf222 fix(L2): update block warning updater to check most recent block timestamp (#2777)
* update block warning updater to check most recent block timestamp

* stop doing dumb state manipulation
2021-11-12 10:18:25 -05:00
Crowdin Bot
b79fe4b833 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-12 15:06:38 +00:00
Justin Domingue
408c907870 feat: add support for 0.01% tier (#2769)
* chore: add support for 0.01% tier

* only show 1bps on mainnet

* rename VERY_LOW to LOWEST

* upgrade to v3-sdk 3.7.0

* add snapshot testing for lowest tier

* fix integration test

* fix integration test

* use ALL_SUPPORTED_CHAIN_IDS over string all

* consider 0.01% tier in pool (#2770)

* merge main and only consider lowest tier for mainnet
2021-11-12 09:46:26 -05:00
Crowdin Bot
8a99bad736 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-12 09:07:00 +00:00
Crowdin Bot
5ba3d2f679 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-12 01:27:47 +00:00
Crowdin Bot
ec4cd57dc0 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-11 21:07:22 +00:00
Moody Salem
ccad45d24e fix(optimism): Optimism regenesis support (#2703)
* feat(optimism): optimistic kovan local regenesis changes

* use the regenesis version of the sdk

* remove the override no longer necessary

* diff rpc url

* back to kovan url

* lint error

* Optimism mainnet regenesis test (#2695)

* remove the optimism mainnet specific code and point to the mainnet regenesis rpc url

* point at the old mainnet multicall address

* bump the sdk version

* copy the list

* multicall address regenesis change

* revert the gas limit special casing for optimism

* bump the sdk version

* remove a couple other temporary edits

* unused test case

* specific version of v3-sdk
2021-11-11 15:40:12 -05:00
Justin Domingue
1903a16097 fix: lint error (#2775) 2021-11-11 13:12:09 -05:00
Justin Domingue
0ea029db4f add protocols param to quote endpoint (#2774)
* add protocols param to quote endpoint

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
2021-11-11 11:42:17 -05:00
Crowdin Bot
cb41df4cd5 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-11 16:07:15 +00:00
Jordan Frankfurt
659a564db8 no unused imports eslint rule (#2773) 2021-11-11 10:53:14 -05:00
Will Hennessy
74c61c0213 feat: Menu update. Add help center & feature requests. Remove analytics & github. (#2709)
* Add help center, remove analytics from menu

* Add canny feature requests link, remove github link

* add coffee icon
2021-11-11 10:31:08 -05:00
Will Hennessy
dc55a21285 fix: remove deprecated optimism status url (#2771) 2021-11-10 16:41:00 -05:00
Moody Salem
48cc6811c9 fix: bump to latest token list including ENS token 2021-11-08 23:46:50 -05:00
Ben Krochta
ab93d512d3 fix: #2741 Increase liquidity form off center (#2746) 2021-11-05 10:29:55 -04:00
Crowdin Bot
cf4c26a77c chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-03 22:06:57 +00:00
Crowdin Bot
02296c686f chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-03 18:11:33 +00:00
Noah Zinsmeister
60bd0eb86c add proposal start time (#2738) 2021-11-03 13:57:56 -04:00
Noah Zinsmeister
188b321cc9 fix: Parse latest proposal description correctly 2021-11-03 13:12:39 -04:00
Brendan Weinstein
377331c44e fix: Update walletlink-connector to 6.2.8 (#2655)
* Update walletlink-connector to 6.2.5 which has a walletlink update to support addEthereumChain+switchEthereumChain requests

* Update walletlink-connector to 6.2.7

* Update walletlink-connector to 6.2.8
2021-11-03 10:56:54 -04:00
Jordan Frankfurt
dfd442cdac try cd1 for custom dimension (#2734) 2021-11-02 22:50:47 -04:00
Jordan Frankfurt
9561cf54e4 don't overwrite localstorage lists when fetch throws (#2723) 2021-11-02 16:31:25 -05:00
Ian Lapham
714953b50e add token to unsupported list (#2732) 2021-11-02 14:46:14 -04:00
Ian Lapham
b3844e38d1 feat: update cmc list link (#2710)
* update cmc lists

* update CMC url
2021-11-02 10:39:40 -04:00
Crowdin Bot
5dac6a03eb chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-01 21:06:15 +00:00
Moody Salem
d18974480a fix: memoize the list stuff so the tokens are consistently clickable (#2724) 2021-11-01 14:01:41 -04:00
Will Hennessy
6a90bf3b9d chore: update unsupported token list (#2689)
* chore: update unsupported token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
2021-11-01 13:43:55 -04:00
M0kY
5026ebded8 fix: walletconnect modal re-open after user rejection (#2693)
Co-authored-by: M0kY <moky@example.com>
2021-11-01 13:42:16 -04:00
Crowdin Bot
02dbed7a75 chore(i18n): synchronize translations from crowdin [skip ci] 2021-11-01 15:09:04 +00:00
Crowdin Bot
20f462f5a4 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-27 19:06:32 +00:00
Jordan Frankfurt
cf9c6e4b4c try out 'dimension1' (#2704) 2021-10-27 12:49:42 -04:00
Crowdin Bot
c0201206cc chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-27 13:10:19 +00:00
dependabot[bot]
2d2508f681 chore(deps-dev): bump @uniswap/token-lists (#2699) 2021-10-27 07:15:50 -04:00
Crowdin Bot
609542c49b chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-27 06:07:13 +00:00
Crowdin Bot
9a0294f469 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-26 22:06:20 +00:00
Jordan Frankfurt
68e6bc1ba8 block import of unsupported tokens (#2673)
generalize custom import token block ui
2021-10-26 17:38:59 -04:00
Justin Domingue
bbc64f12bb fix: back arrow bug in wallet modal and fill tx for wallet (#2687)
* add tx to wallet connect

* remove id from env

* restore env
2021-10-26 12:46:10 -04:00
Crowdin Bot
06f5fdc6ad chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-26 09:07:10 +00:00
Crowdin Bot
b4e756ebba chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-26 08:07:05 +00:00
Crowdin Bot
17439d6fbb chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-25 18:06:54 +00:00
Crowdin Bot
79d582c72f chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-25 17:09:26 +00:00
Crowdin Bot
245f8d7279 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-25 16:07:10 +00:00
Justin Domingue
3bf36eade4 chore: set final privacy learn more link' (#2684)
* add learn more button

* add final link
2021-10-25 11:57:23 -04:00
Justin Domingue
8eb864426f refactor monitoring (#2682) 2021-10-25 10:39:16 -04:00
Justin Domingue
af83399606 log full signed tx (#2681) 2021-10-25 09:44:07 -04:00
Crowdin Bot
1d5be31621 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-25 13:12:59 +00:00
Justin Domingue
abe6bf500c feat: extend privacy and terms (#2623)
* initial iteration

* add logging

* added hook

* polish

* remove unused import

* add hash

* addressed pr feedback

* remove autorouter icon

* use firebase store

* style

* adjust recat ga

* log remove liquidity

* update copy

* addressed pr feedback

* addressed pr feedback

* prevent privacy content from dismissing modal

* make top-level key origin

* use hostname

* restore trm
2021-10-25 08:41:55 -04:00
Crowdin Bot
36cfe627f1 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-23 10:06:44 +00:00
Crowdin Bot
aef5d0513a chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-23 09:06:47 +00:00
Ian Lapham
5e09a0ced7 fix: update token list (#2671)
* update token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
2021-10-22 16:18:37 -04:00
Ian Lapham
f768428b9d chore: update token list (#2670)
* update token list

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
2021-10-22 15:47:42 -04:00
Zach Pomerantz
76c9bf84cd fix: use optional operator for chainId (#2666) 2021-10-22 10:33:18 -07:00
Jordan Frankfurt
f26a3306ec fix(L2): ensure chainIds match before fetching pool data (#2652)
* ensure chainIds match before fetching pool data

* debounce both input currencies, and only look for pairs on currencies that share a chainId

* pr feedback
2021-10-22 12:14:04 -04:00
Crowdin Bot
1846883e56 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-21 06:06:22 +00:00
Zach Pomerantz
9cacd577e7 fix: restrict @davatar usage to avoid 3p fetches (#2649) 2021-10-20 09:19:19 -07:00
Moody Salem
5e8d725e0e fix: split calls into more chunks if they fail due to out of gas errors (#2630)
* fix: split calls into more chunks if they fail due to out of gas errors

* set to 100m gas

* back to 25m so we batch fewer calls

* do not pass through gas limit, some simplification of the code

* unused import
2021-10-19 11:37:57 -05:00
Justin Domingue
c63482b6f7 use l2 logos in base pairs (#2634) 2021-10-19 10:55:59 -04:00
Justin Domingue
e15a8ddf59 remove WETH from optimism bases (#2640) 2021-10-19 10:08:28 -04:00
Justin Domingue
1e7dff060f fix: add usdc to arbitrum/optimism common bases (#2641) 2021-10-19 10:08:10 -04:00
Micael Rodrigues
244ed38b72 fix: center focused outline card (#2625) 2021-10-18 14:13:09 -04:00
Crowdin Bot
87d547ab2b chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-17 03:06:15 +00:00
Crowdin Bot
0c213be5d9 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-17 01:29:14 +00:00
Crowdin Bot
f62d301891 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-17 00:11:16 +00:00
Crowdin Bot
902cd343d2 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-16 07:06:35 +00:00
Crowdin Bot
a26db9a51d chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-15 07:06:39 +00:00
Crowdin Bot
b7cb2d24c7 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-15 01:28:43 +00:00
Justin Domingue
aea2bca775 fix: increase quote gas overrides on arbitrum (#2614) 2021-10-14 14:22:26 -04:00
Crowdin Bot
93b79be1b6 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-14 18:06:59 +00:00
Justin Domingue
54531b53c6 refactor: migrate state/application to slice (#2615) 2021-10-14 13:40:19 -04:00
Crowdin Bot
b286c1ba09 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-14 15:11:24 +00:00
Justin Domingue
8dd1be3b47 fix: remove extra $ from translations (#2611)
* remove extra $

* refactor

* refactor
2021-10-14 10:34:16 -04:00
Justin Domingue
0b8afcff41 only display TradePrice usdcPrice if available (#2613) 2021-10-14 10:15:17 -04:00
Crowdin Bot
e4b727f6f0 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-14 06:07:01 +00:00
Crowdin Bot
6e0b24cbb1 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-13 23:06:18 +00:00
Justin Domingue
442879ccd9 improve fee tier selector (#2609) 2021-10-13 18:22:45 -04:00
Carlos Diaz-Padron
50386f65e7 upgrade @davatar/react to 1.8.1 (#2485) 2021-10-13 14:03:06 -07:00
Zach Pomerantz
eba8170c46 chore: eslint nit (#2607) 2021-10-13 14:02:17 -07:00
Lint Action
095dbffbca Fix code style issues with ESLint 2021-10-13 18:02:05 +00:00
Justin Domingue
4df2824984 update arbitrum subgraph url
fee tier working, tick data not in this subgraph
2021-10-13 13:59:01 -04:00
Justin Domingue
15345690e3 add reducer path to routing api (#2541) 2021-10-12 16:56:06 -04:00
Connor McEwen
3e36281f77 fix: z-index bug which prevented modal click (#2264)
* Fix z-index bug which prevented modal click. Center button and remove underline

* Fix code style issues with ESLint

* fix: PR comments

* Fix code style issues with ESLint

* z-index comment

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
2021-10-11 14:00:31 -04:00
nitipon.eth
27a868f0cb fix(SafariSquareDots): fixed by using border-top-with instead of bord… (#2474)
* fix(SafariSquareDots): fixed by using border-top-with instead of border-width

* fix(SafariSqaureDots): fixed by using a min width of 5px and then following the width of the screen if the screen is too wide

* fix(SafariSquareDots): fixed by using Dot SVG instead of border-style CSS

* fix(SafariSquareDots):  Fixed code follows suggestions from the Pull Request

* regenerate snapshots

Co-authored-by: NITIPON CHINGTHONGCHAI <nitipon.chingthongchai@scb.co.th>
Co-authored-by: Justin Domingue <judo@uniswap.org>
2021-10-11 13:56:58 -04:00
Connor McEwen
03c3fdef34 Change import to lib/bundle (#2524) 2021-10-11 13:06:29 -04:00
Connor McEwen
d37e963f26 fix: Show proper graph color for non-Ethereum L1 chains (#2049) (#2284)
* Switch to fetching token color from the logoURI included

* Fall back to github hosted images

* Move logger to changes to another PR
2021-10-11 12:07:28 -04:00
Crowdin Bot
2e40bef7f0 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-11 15:06:46 +00:00
Crowdin Bot
dac87e2299 chore(i18n): synchronize translations from crowdin [skip ci] 2021-10-11 14:06:32 +00:00
Justin Domingue
be15604244 fix: replace t with <Trans> where possible (#2516)
* replace t macro with <Trans>

* replace t macro with <Trans>

* add lint rule for t

* fixed more ts
2021-10-11 09:30:51 -04:00
374 changed files with 22430 additions and 13030 deletions

2
.env
View File

@@ -1 +1 @@
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"

View File

@@ -2,3 +2,4 @@ REACT_APP_INFURA_KEY="099fc58e0de9451d80b18d7c74caa7c1"
REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236"
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
REACT_APP_GOOGLE_ANALYTICS_ID="UA-128182339-4"
REACT_APP_FIREBASE_KEY="AIzaSyBcZWwTcTJHj_R6ipZcrJkXdq05PuX0Rs0"

View File

@@ -8,21 +8,42 @@
"jsx": true
}
},
"ignorePatterns": ["node_modules/**/*"],
"settings": {
"react": {
"version": "detect"
}
},
"ignorePatterns": [
"src/types/v3",
"src/abis/types",
"src/locales/**/*.js",
"src/locales/**/en-US.po",
"src/state/data/generated.ts",
"node_modules",
"coverage",
"build",
"dist",
".DS_Store",
".env.local",
".env.development.local",
".env.test.local",
".env.production.local",
".idea/",
".vscode/",
"package-lock.json",
"yarn.lock"
],
"extends": [
"react-app",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
"prettier/@typescript-eslint",
"plugin:prettier/recommended"
],
"plugins": ["simple-import-sort"],
"plugins": ["simple-import-sort", "unused-imports"],
"rules": {
"unused-imports/no-unused-imports": "error",
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"@typescript-eslint/explicit-function-return-type": "off",
@@ -48,6 +69,11 @@
{
"name": "styled-components",
"message": "Please import from styled-components/macro."
},
{
"name": "@lingui/macro",
"importNames": ["t"],
"message": "Please use <Trans> instead of t."
}
],
"patterns": [

View File

@@ -7,3 +7,4 @@ updates:
interval: "daily"
allow:
- dependency-name: "@uniswap/token-lists"
- dependency-name: "@uniswap/default-token-list"

43
.github/workflows/depcheck.yaml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: Bundle Dependency Check
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
depcheck:
name: Bundle depcheck
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up node
uses: actions/setup-node@v2
with:
node-version: 14
registry-url: https://registry.npmjs.org
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Bundle
run: yarn bundle
- name: Depcheck
run: yarn bundle:depcheck

View File

@@ -11,7 +11,6 @@ on:
jobs:
run-linters:
name: Run linters
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login == github.repository_owner }}
runs-on: ubuntu-latest
steps:
@@ -39,10 +38,15 @@ jobs:
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run linters
- name: Run eslint w/ autofix
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login == github.repository_owner }}
uses: wearerequired/lint-action@36c7e6689e80d785d27a22f71d970f3a3b4fcb70
with:
github_token: ${{ secrets.github_token }}
eslint: true
eslint_extensions: js,jsx,ts,tsx,json
eslint_args: "-c .eslintrc.json"
auto_fix: true
- name: Run eslint
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login != github.repository_owner }}
run: yarn eslint .

8
.gitignore vendored
View File

@@ -3,10 +3,18 @@
# generated contract types
/src/types/v3
/src/abis/types
/src/lib/locales/**/*.js
/src/lib/locales/**/en-US.po
/src/lib/locales/**/pseudo.po
/src/locales/**/*.js
/src/locales/**/en-US.po
/src/locales/**/pseudo.po
/src/state/data/generated.ts
# generated assets
/src/lib/assets/svg/*.tsx
/src/lib/assets/fonts/*.css
# dependencies
/node_modules

View File

@@ -27,7 +27,7 @@ makes large architectural changes, consider following all the standards.
- If something breaks, add automated tests so it doesn't break again
- Add integration tests for new pages or flows
- Verify that all CI checks pass before merging
- Have at least one product manager or designer approve of significant UX changes
- Have at least one product manager or designer approve of any significant UX changes
## Guidelines
@@ -42,7 +42,7 @@ The following points should help guide your development:
- An Ethereum node should be the only critical dependency
- All other external dependencies should only enhance the UX ([graceful degradation](https://developer.mozilla.org/en-US/docs/Glossary/Graceful_degradation))
- Accessibility: anyone can use the interface
- The interface should be responsive, small and run well on low performance devices (majority of swaps on mobile!)
- The interface should be responsive, small and also run well on low performance devices (majority of swaps on mobile!)
## Release process
@@ -73,4 +73,4 @@ We sync to the repository on a schedule, rather than download translations at bu
You can contribute by joining Crowdin to proofread existing translations [here](https://crowdin.com/project/uniswap-interface/invite?d=93i5n413q403t4g473p443o4c3t2g3s21343u2c3n403l4b3v2735353i4g4k4l4g453j4g4o4j4e4k4b323l4a3h463s4g453q443m4e3t2b303s2a35353l403o443v293e303k4g4n4r4g483i4g4r4j4e4o473i5n4a3t463t4o4)
Or, ask to join us as a translator in the Discord!
Or, ask to join us as a translator in the Discord!!

View File

@@ -10,7 +10,7 @@ An open source interface for Uniswap -- a protocol for decentralized exchange of
- Website: [uniswap.org](https://uniswap.org/)
- Interface: [app.uniswap.org](https://app.uniswap.org)
- Docs: [uniswap.org/docs/](https://uniswap.org/docs/)
- Docs: [uniswap.org/docs/](https://docs.uniswap.org/)
- Twitter: [@Uniswap](https://twitter.com/Uniswap)
- Reddit: [/r/Uniswap](https://www.reddit.com/r/Uniswap/)
- Email: [contact@uniswap.org](mailto:contact@uniswap.org)

View File

@@ -1,7 +1,9 @@
{
"staticPath": "public",
"watchDirs": ["src"],
"watchDirs": [
"src"
],
"webpack": {
"configPath": "react-scripts/config/webpack.config"
"configPath": "react-scripts/config/webpack.config",
"overridePath": "cosmos.override.js"
}
}
}

14
cosmos.override.js Normal file
View File

@@ -0,0 +1,14 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const HtmlWebpackPlugin = require('html-webpack-plugin')
// Renders the cosmos fixtures in isolation, instead of using public/index.html.
module.exports = (webpackConfig) => ({
...webpackConfig,
plugins: webpackConfig.plugins.map((plugin) =>
plugin instanceof HtmlWebpackPlugin
? new HtmlWebpackPlugin({
templateContent: '<body></body>',
})
: plugin
),
})

View File

@@ -5,6 +5,11 @@
}
},
"asToken0": [
{
"feeTier": "100",
"totalValueLockedToken0": "0",
"totalValueLockedToken1": "3"
},
{
"feeTier": "500",
"totalValueLockedToken0": "0",
@@ -13,7 +18,7 @@
{
"feeTier": "3000",
"totalValueLockedToken0": "0",
"totalValueLockedToken1": "7"
"totalValueLockedToken1": "4"
},
{
"feeTier": "10000",

View File

@@ -58,7 +58,7 @@ describe('Add Liquidity', () => {
cy.wait('@feeTierDistributionQuery')
cy.get('#add-liquidity-selected-fee .selected-fee-label').should('contain.text', '0.3% fee tier')
cy.get('#add-liquidity-selected-fee .selected-fee-percentage').should('contain.text', '70%')
cy.get('#add-liquidity-selected-fee .selected-fee-percentage').should('contain.text', '40%')
})
})
})

View File

@@ -74,6 +74,7 @@ class CustomizedBridge extends Eip1193Bridge {
}
// sets up the injected provider to be a mock ethereum provider with the given mnemonic/index
// eslint-disable-next-line no-undef
Cypress.Commands.overwrite('visit', (original, url, options) => {
return original(url.startsWith('/') && url.length > 2 && !url.startsWith('/#') ? `/#${url}` : url, {
...options,

28
depcheck.js Normal file
View File

@@ -0,0 +1,28 @@
#!/bin/node
/**
* Checks if any dependencies have been bundled with the interface library.
* Exits with non-zero status if dependencies are included in the bundle.
*/
/* eslint-disable */
const { readFile } = require('fs')
function checkDeps(err, sourcemap) {
if (err) {
console.error(err)
process.exit(1)
}
const includesDeps = sourcemap.includes('node_modules')
if (includesDeps) {
const deps = [...sourcemap.toString().matchAll(/node_modules[\\\/]([^\\\/]*)/g)].map(([, match]) => match)
console.error(`
Sourcemap includes node_modules folder(s). External deps must be bundled under "dependencies".
To fix, run: \`yarn add ${deps.join(' ')}\`
`)
process.exit(1)
}
}
readFile('dist/interface.esm.js.map', checkDeps)

View File

@@ -1,4 +1,4 @@
export default {
const linguiConfig = {
catalogs: [
{
path: '<rootDir>/src/locales/{locale}',
@@ -46,9 +46,13 @@ export default {
'vi-VN',
'zh-CN',
'zh-TW',
'pseudo',
],
orderBy: 'messageId',
rootDir: '.',
runtimeConfigModule: ['@lingui/core', 'i18n'],
sourceLocale: 'en-US',
pseudoLocale: 'pseudo',
}
export default linguiConfig

View File

@@ -11,7 +11,6 @@
],
"private": true,
"devDependencies": {
"@davatar/react": "1.6.2",
"@ethersproject/experimental": "^5.4.0",
"@gnosis.pm/safe-apps-web3-react": "^0.6.0",
"@graphql-codegen/cli": "1.21.5",
@@ -19,13 +18,12 @@
"@graphql-codegen/typescript-operations": "^1.18.2",
"@graphql-codegen/typescript-rtk-query": "^1.1.1",
"@lingui/cli": "^3.9.0",
"@lingui/macro": "^3.9.0",
"@lingui/react": "^3.9.0",
"@popperjs/core": "^2.4.4",
"@metamask/jazzicon": "^2.0.0",
"@reach/dialog": "^0.10.3",
"@reach/portal": "^0.10.3",
"@react-hook/window-scroll": "^1.3.0",
"@reduxjs/toolkit": "^1.6.1",
"@svgr/cli": "^5.5.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@testing-library/react-hooks": "^7.0.2",
@@ -37,7 +35,6 @@
"@types/lingui__core": "^2.7.1",
"@types/lingui__macro": "^2.7.4",
"@types/lingui__react": "^2.8.3",
"@types/luxon": "^1.24.4",
"@types/ms.macro": "^2.0.0",
"@types/multicodec": "^1.0.0",
"@types/node": "^13.13.5",
@@ -55,24 +52,26 @@
"@types/wcag-contrast": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
"@uniswap/default-token-list": "^2.0.0",
"@uniswap/default-token-list": "^2.1.0",
"@uniswap/governance": "^1.0.2",
"@uniswap/liquidity-staker": "^1.0.2",
"@uniswap/merkle-distributor": "1.0.1",
"@uniswap/router-sdk": "^1.0.3",
"@uniswap/sdk-core": "^3.0.1",
"@uniswap/token-lists": "^1.0.0-beta.26",
"@uniswap/smart-order-router": "^2.5.4",
"@uniswap/token-lists": "^1.0.0-beta.27",
"@uniswap/v2-core": "1.0.0",
"@uniswap/v2-periphery": "^1.1.0-beta.0",
"@uniswap/v2-sdk": "^3.0.0-alpha.2",
"@uniswap/v2-sdk": "^3.0.1",
"@uniswap/v3-core": "1.0.0",
"@uniswap/v3-periphery": "^1.1.1",
"@uniswap/v3-sdk": "^3.4.1",
"@uniswap/v3-sdk": "^3.7.1",
"@web3-react/core": "^6.0.9",
"@web3-react/fortmatic-connector": "^6.0.9",
"@web3-react/injected-connector": "^6.0.7",
"@web3-react/portis-connector": "^6.0.9",
"@web3-react/walletconnect-connector": "^7.0.2-alpha.0",
"@web3-react/walletlink-connector": "^6.2.3",
"@web3-react/walletlink-connector": "^6.2.8",
"ajv": "^6.12.3",
"array.prototype.flat": "^1.2.4",
"array.prototype.flatmap": "^1.2.4",
@@ -83,50 +82,44 @@
"d3": "^7.0.0",
"eslint": "^7.11.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-better-styled-components": "^1.1.2",
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-react": "^7.19.0",
"eslint-plugin-react-hooks": "^4.0.0",
"eslint-plugin-simple-import-sort": "^7.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"ethers": "^5.4.6",
"firebase": "^9.1.3",
"graphql": "^15.5.0",
"graphql-request": "^3.4.0",
"inter-ui": "^3.13.1",
"jest-styled-components": "^7.0.5",
"luxon": "^1.25.0",
"microbundle": "^0.13.3",
"ms.macro": "^2.0.0",
"multicodec": "^3.0.1",
"multihashes": "^4.0.2",
"node-vibrant": "^3.2.1-alpha.1",
"polished": "^3.3.2",
"polyfill-object.fromentries": "^1.0.1",
"prettier": "^2.2.1",
"qs": "^6.9.4",
"react": "^17.0.1",
"react-confetti": "^6.0.0",
"react-cosmos": "^5.6.3",
"react-dom": "^17.0.1",
"react-feather": "^2.0.8",
"react-ga": "^2.5.7",
"react-is": "^17.0.2",
"react-markdown": "^4.3.1",
"react-popper": "^2.2.3",
"react-redux": "^7.2.2",
"react-router-dom": "^5.0.0",
"react-scripts": "^4.0.3",
"react-spring": "^8.0.27",
"react-use-gesture": "^6.0.14",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.5",
"rebass": "^4.0.7",
"redux-localstorage-simple": "^2.3.1",
"sass": "^1.45.1",
"serve": "^11.3.2",
"start-server-and-test": "^1.11.0",
"styled-components": "^5.3.0",
"typechain": "^5.0.0",
"typescript": "^4.2.3",
"ua-parser-js": "^0.7.28",
"use-count-up": "^2.2.5",
"use-resize-observer": "^8.0.0",
"wcag-contrast": "^3.0.0",
"web-vitals": "^2.1.0",
"workbox-core": "^6.1.0",
@@ -137,26 +130,25 @@
"@walletconnect/ethereum-provider": "1.6.5"
},
"scripts": {
"contracts:compile:abi": "typechain --target ethers-v5 --out-dir src/abis/types './src/abis/**/*.json'",
"contracts:compile:v3": "typechain --target ethers-v5 --out-dir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
"contracts:compile:abi": "typechain --target ethers-v5 --out-dir src/abis/types \"./src/abis/**/*.json\"",
"contracts:compile:v3": "typechain --target ethers-v5 --out-dir src/types/v3 \"./node_modules/@uniswap/**/artifacts/contracts/**/*.json\"",
"contracts:compile": "yarn contracts:compile:abi && yarn contracts:compile:v3",
"graphql:generate": "graphql-codegen --config codegen.yml",
"prei18n:extract": "touch src/locales/en-US.po",
"i18n:extract": "lingui extract --locale en-US",
"i18n:compile": "yarn i18n:extract && lingui compile",
"postinstall": "yarn contracts:compile && yarn graphql:generate && yarn i18n:compile",
"i18n:pseudo": "lingui extract --locale pseudo && lingui compile",
"postinstall": "yarn contracts:compile && yarn graphql:generate && yarn i18n:compile && yarn assets:generate",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=./custom-test-env.js",
"test:e2e": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run --record'",
"bundle": "microbundle --tsconfig tsconfig.lib.json src/lib/index.tsx --format esm,cjs",
"cosmos": "open http://localhost:5000 && cross-env FAST_REFRESH=false cosmos"
},
"eslintConfig": {
"extends": "react-app",
"ignorePatterns": [
"node_modules"
]
"assets:generate": "yarn assets:svg:generate && yarn assets:font:generate",
"assets:svg:generate": "svgr -d src/lib/assets/svg --ext tsx --typescript src/lib/assets/svg && rm src/lib/assets/svg/index.tsx",
"assets:font:generate": "sass src/lib/assets/fonts/index.scss src/lib/assets/fonts/index.css --no-source-map -I node_modules",
"bundle": "microbundle --define process.env.REACT_APP_IS_WIDGET=true --tsconfig tsconfig.lib.json src/lib/index.tsx --format esm,cjs",
"bundle:depcheck": "node depcheck.js",
"cosmos": "cross-env FAST_REFRESH=false REACT_APP_IS_WIDGET=true cosmos"
},
"browserslist": {
"production": [
@@ -171,5 +163,37 @@
]
},
"license": "GPL-3.0-or-later",
"dependencies": {}
"dependencies": {
"@fontsource/ibm-plex-mono": "^4.5.1",
"@fontsource/inter": "^4.5.1",
"@lingui/core": "^3.9.0",
"@lingui/macro": "^3.9.0",
"@lingui/react": "^3.9.0",
"@popperjs/core": "^2.4.4",
"@uniswap/redux-multicall": "^1.0.0",
"immer": "^9.0.6",
"jotai": "^1.3.7",
"lodash": "^4.17.21",
"make-plural": "^7.0.0",
"node-vibrant": "^3.2.1-alpha.1",
"polished": "^3.3.2",
"popper-max-size-modifier": "^0.2.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-feather": "^2.0.8",
"react-popper": "^2.2.3",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.5",
"rebass": "^4.0.7",
"redux": "^4.1.2",
"styled-components": "^5.3.0",
"tiny-invariant": "^1.2.0",
"wcag-contrast": "^3.0.0",
"wicg-inert": "^3.1.1",
"widgets-web3-react/core": "npm:@web3-react/core@8.0.15-alpha.0",
"widgets-web3-react/eip1193": "npm:@web3-react/eip1193@8.0.15-alpha.0",
"widgets-web3-react/metamask": "npm:@web3-react/metamask@8.0.15-alpha.0",
"widgets-web3-react/network": "npm:@web3-react/network@8.0.15-alpha.0",
"widgets-web3-react/types": "npm:@web3-react/types@8.0.15-alpha.0"
}
}

View File

@@ -67,6 +67,7 @@
html {
font-size: 16px;
font-variant: none;
font-smooth: always;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);

49
src/abis/erc1155.json Normal file
View File

@@ -0,0 +1,49 @@
[
{
"constant": true,
"inputs": [
{
"internalType": "address",
"name": "_owner",
"type": "address"
},
{
"internalType": "uint256",
"name": "_id",
"type": "uint256"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"internalType": "uint256",
"name": "_id",
"type": "uint256"
}
],
"name": "uri",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
]

40
src/abis/erc721.json Normal file
View File

@@ -0,0 +1,40 @@
[
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "ownerOf",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "tokenURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
}
]

View File

@@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.0047 9.26921H10.2714C11.0078 9.26921 11.6047 9.86617 11.6047 10.6025V12.1359C11.6047 12.7987 12.142 13.3359 12.8047 13.3359C13.4675 13.3359 14.0047 12.7995 14.0047 12.1367V5.22059C14.0047 4.86697 13.7758 4.56227 13.5258 4.31223L10.6714 1.33594M4.00472 2.00254H8.00472C8.7411 2.00254 9.33805 2.59949 9.33805 3.33587V14.0015H2.67139V3.33587C2.67139 2.59949 3.26834 2.00254 4.00472 2.00254ZM14.0047 5.33587C14.0047 6.07225 13.4078 6.66921 12.6714 6.66921C11.935 6.66921 11.3381 6.07225 11.3381 5.33587C11.3381 4.59949 11.935 4.00254 12.6714 4.00254C13.4078 4.00254 14.0047 4.59949 14.0047 5.33587Z" stroke="white"/>
<line x1="4" y1="9.99414" x2="8" y2="9.99414" stroke="white"/>
<line x1="4" y1="11.9941" x2="8" y2="11.9941" stroke="white"/>
<path d="M4 8.16113H8" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 895 B

View File

@@ -0,0 +1,12 @@
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_988_5781)">
<path d="M11.3333 12.5C7.33329 12.5 6.66663 8.5 3.99996 8.5M3.99996 8.5C6.66663 8.5 7.33329 4.5 11.3333 4.5M3.99996 8.5H1.66663" stroke="#888D9B" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="13.3334" cy="4.5" r="2" stroke="#888D9B" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="13.3334" cy="12.5" r="2" stroke="#888D9B" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_988_5781">
<rect width="16" height="16" fill="white" transform="translate(0 0.5)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,3 @@
<svg width="100%" height="35" viewBox="800 0 300 200" xmlns="http://www.w3.org/2000/svg">
<line x1="0" x2="2000" y1="100" y2="100" stroke="currentColor" stroke-width="20" stroke-linecap="round" stroke-dasharray="1, 45"/>
</svg>

After

Width:  |  Height:  |  Size: 233 B

View File

@@ -0,0 +1,4 @@
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="512" cy="512" r="512" fill="#8247E5"/>
<path d="M681.469 402.456C669.189 395.312 653.224 395.312 639.716 402.456L543.928 457.228L478.842 492.949L383.055 547.721C370.774 554.865 354.81 554.865 341.301 547.721L265.162 504.856C252.882 497.712 244.286 484.614 244.286 470.325V385.786C244.286 371.498 251.654 358.4 265.162 351.256L340.073 309.581C352.353 302.437 368.318 302.437 381.827 309.581L456.737 351.256C469.018 358.4 477.614 371.498 477.614 385.786V440.558L542.7 403.646V348.874C542.7 334.586 535.332 321.488 521.824 314.344L383.055 235.758C370.774 228.614 354.81 228.614 341.301 235.758L200.076 314.344C186.567 321.488 179.199 334.586 179.199 348.874V507.237C179.199 521.525 186.567 534.623 200.076 541.767L341.301 620.353C353.582 627.498 369.546 627.498 383.055 620.353L478.842 566.772L543.928 529.86L639.716 476.279C651.996 469.135 667.961 469.135 681.469 476.279L756.38 517.953C768.66 525.098 777.257 538.195 777.257 552.484V637.023C777.257 651.312 769.888 664.409 756.38 671.553L681.469 714.419C669.189 721.563 653.224 721.563 639.716 714.419L564.805 672.744C552.525 665.6 543.928 652.502 543.928 638.214V583.442L478.842 620.353V675.125C478.842 689.414 486.21 702.512 499.719 709.656L640.944 788.242C653.224 795.386 669.189 795.386 682.697 788.242L823.922 709.656C836.203 702.512 844.799 689.414 844.799 675.125V516.763C844.799 502.474 837.431 489.377 823.922 482.232L681.469 402.456Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 38.4 33.5" style="enable-background:new 0 0 38.4 33.5;" xml:space="preserve">
<style type="text/css">
.st0{fill:#8247E5;}
</style>
<g>
<path class="st0" d="M29,10.2c-0.7-0.4-1.6-0.4-2.4,0L21,13.5l-3.8,2.1l-5.5,3.3c-0.7,0.4-1.6,0.4-2.4,0L5,16.3
c-0.7-0.4-1.2-1.2-1.2-2.1v-5c0-0.8,0.4-1.6,1.2-2.1l4.3-2.5c0.7-0.4,1.6-0.4,2.4,0L16,7.2c0.7,0.4,1.2,1.2,1.2,2.1v3.3l3.8-2.2V7
c0-0.8-0.4-1.6-1.2-2.1l-8-4.7c-0.7-0.4-1.6-0.4-2.4,0L1.2,5C0.4,5.4,0,6.2,0,7v9.4c0,0.8,0.4,1.6,1.2,2.1l8.1,4.7
c0.7,0.4,1.6,0.4,2.4,0l5.5-3.2l3.8-2.2l5.5-3.2c0.7-0.4,1.6-0.4,2.4,0l4.3,2.5c0.7,0.4,1.2,1.2,1.2,2.1v5c0,0.8-0.4,1.6-1.2,2.1
L29,28.8c-0.7,0.4-1.6,0.4-2.4,0l-4.3-2.5c-0.7-0.4-1.2-1.2-1.2-2.1V21l-3.8,2.2v3.3c0,0.8,0.4,1.6,1.2,2.1l8.1,4.7
c0.7,0.4,1.6,0.4,2.4,0l8.1-4.7c0.7-0.4,1.2-1.2,1.2-2.1V17c0-0.8-0.4-1.6-1.2-2.1L29,10.2z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro'
import { Fraction, TradeType } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
import { nativeOnChain } from '../../constants/tokens'
import { useCurrency, useToken } from '../../hooks/Tokens'
import useENSName from '../../hooks/useENSName'
import { VoteOption } from '../../state/governance/types'
@@ -80,7 +81,7 @@ function ClaimSummary({ info: { recipient, uniAmountRaw } }: { info: ClaimTransa
)
}
function SubmitProposalTransactionSummary({}: { info: SubmitProposalTransactionInfo }) {
function SubmitProposalTransactionSummary(_: { info: SubmitProposalTransactionInfo }) {
return <Trans>Submit new proposal</Trans>
}
@@ -130,30 +131,45 @@ function DelegateSummary({ info: { delegatee } }: { info: DelegateTransactionInf
return <Trans>Delegate voting power to {ENSName ?? delegatee}</Trans>
}
function WrapSummary({ info: { currencyAmountRaw, unwrapped } }: { info: WrapTransactionInfo }) {
function WrapSummary({ info: { chainId, currencyAmountRaw, unwrapped } }: { info: WrapTransactionInfo }) {
const native = chainId ? nativeOnChain(chainId) : undefined
if (unwrapped) {
return (
<Trans>
Unwrap <FormattedCurrencyAmount rawAmount={currencyAmountRaw} symbol={'WETH'} decimals={18} sigFigs={6} /> to
ETH
Unwrap{' '}
<FormattedCurrencyAmount
rawAmount={currencyAmountRaw}
symbol={native?.wrapped?.symbol ?? 'WETH'}
decimals={18}
sigFigs={6}
/>{' '}
to {native?.symbol ?? 'ETH'}
</Trans>
)
} else {
return (
<Trans>
Wrap <FormattedCurrencyAmount rawAmount={currencyAmountRaw} symbol={'ETH'} decimals={18} sigFigs={6} /> to WETH
Wrap{' '}
<FormattedCurrencyAmount
rawAmount={currencyAmountRaw}
symbol={native?.symbol ?? 'ETH'}
decimals={18}
sigFigs={6}
/>{' '}
to {native?.wrapped?.symbol ?? 'WETH'}
</Trans>
)
}
}
function DepositLiquidityStakingSummary({}: { info: DepositLiquidityStakingTransactionInfo }) {
function DepositLiquidityStakingSummary(_: { info: DepositLiquidityStakingTransactionInfo }) {
// not worth rendering the tokens since you can should no longer deposit liquidity in the staking contracts
// todo: deprecate and delete the code paths that allow this, show user more information
return <Trans>Deposit liquidity</Trans>
}
function WithdrawLiquidityStakingSummary({}: { info: WithdrawLiquidityStakingTransactionInfo }) {
function WithdrawLiquidityStakingSummary(_: { info: WithdrawLiquidityStakingTransactionInfo }) {
return <Trans>Withdraw deposited liquidity</Trans>
}

View File

@@ -1,23 +1,21 @@
import { Trans } from '@lingui/macro'
import { AbstractConnector } from '@web3-react/abstract-connector'
import { useCallback, useContext } from 'react'
import { ExternalLink as LinkIcon } from 'react-feather'
import { useAppDispatch } from 'state/hooks'
import styled, { ThemeContext } from 'styled-components/macro'
import { Connector } from 'widgets-web3-react/types'
import CoinbaseWalletIcon from '../../assets/images/coinbaseWalletIcon.svg'
import FortmaticIcon from '../../assets/images/fortmaticIcon.png'
import PortisIcon from '../../assets/images/portisIcon.png'
import WalletConnectIcon from '../../assets/images/walletConnectIcon.svg'
import { ReactComponent as Close } from '../../assets/images/x.svg'
import { fortmatic, injected, portis, walletconnect, walletlink } from '../../connectors'
import { injected, portis, walletlink } from '../../connectors'
import { SUPPORTED_WALLETS } from '../../constants/wallet'
import { useActiveWeb3React } from '../../hooks/web3'
import { clearAllTransactions } from '../../state/transactions/actions'
import { ExternalLink, LinkStyledButton, TYPE } from '../../theme'
import { ExternalLink, LinkStyledButton, ThemedText } from '../../theme'
import { shortenAddress } from '../../utils'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { ButtonSecondary } from '../Button'
import Identicon from '../Identicon'
import StatusIcon from '../Identicon/StatusIcon'
import { AutoRow } from '../Row'
import Copy from './Copy'
import Transaction from './Transaction'
@@ -179,6 +177,23 @@ const IconWrapper = styled.div<{ size?: number }>`
`};
`
function WrappedStatusIcon({ connector }: { connector: AbstractConnector | Connector }) {
return (
<IconWrapper size={16}>
<StatusIcon connector={connector} />
{connector === portis && (
<MainWalletAction
onClick={() => {
portis.portis.showPortis()
}}
>
<Trans>Show Portis</Trans>
</MainWalletAction>
)}
</IconWrapper>
)
}
const TransactionListWrapper = styled.div`
${({ theme }) => theme.flexColumnNoWrap};
`
@@ -244,50 +259,6 @@ export default function AccountDetails({
)
}
function getStatusIcon() {
if (connector === injected) {
return (
<IconWrapper size={16}>
<Identicon />
</IconWrapper>
)
} else if (connector === walletconnect) {
return (
<IconWrapper size={16}>
<img src={WalletConnectIcon} alt={'WalletConnect logo'} />
</IconWrapper>
)
} else if (connector === walletlink) {
return (
<IconWrapper size={16}>
<img src={CoinbaseWalletIcon} alt={'Coinbase Wallet logo'} />
</IconWrapper>
)
} else if (connector === fortmatic) {
return (
<IconWrapper size={16}>
<img src={FortmaticIcon} alt={'Fortmatic logo'} />
</IconWrapper>
)
} else if (connector === portis) {
return (
<>
<IconWrapper size={16}>
<img src={PortisIcon} alt={'Portis logo'} />
<MainWalletAction
onClick={() => {
portis.portis.showPortis()
}}
>
<Trans>Show Portis</Trans>
</MainWalletAction>
</IconWrapper>
</>
)
}
return null
}
const clearAllTransactionsCallback = useCallback(() => {
if (chainId) dispatch(clearAllTransactions({ chainId }))
}, [dispatch, chainId])
@@ -332,14 +303,14 @@ export default function AccountDetails({
{ENSName ? (
<>
<div>
{getStatusIcon()}
{connector && <WrappedStatusIcon connector={connector} />}
<p> {ENSName}</p>
</div>
</>
) : (
<>
<div>
{getStatusIcon()}
{connector && <WrappedStatusIcon connector={connector} />}
<p> {account && shortenAddress(account)}</p>
</div>
</>
@@ -408,9 +379,9 @@ export default function AccountDetails({
{!!pendingTransactions.length || !!confirmedTransactions.length ? (
<LowerSection>
<AutoRow mb={'1rem'} style={{ justifyContent: 'space-between' }}>
<TYPE.body>
<ThemedText.Body>
<Trans>Recent Transactions</Trans>
</TYPE.body>
</ThemedText.Body>
<LinkStyledButton onClick={clearAllTransactionsCallback}>
<Trans>(clear all)</Trans>
</LinkStyledButton>
@@ -420,9 +391,9 @@ export default function AccountDetails({
</LowerSection>
) : (
<LowerSection>
<TYPE.body color={theme.text1}>
<ThemedText.Body color={theme.text1}>
<Trans>Your transactions will appear here...</Trans>
</TYPE.body>
</ThemedText.Body>
</LowerSection>
)}
</>

View File

@@ -1,10 +1,12 @@
import { t, Trans } from '@lingui/macro'
import { Trans } from '@lingui/macro'
// eslint-disable-next-line no-restricted-imports
import { t } from '@lingui/macro'
import { ReactNode, useCallback, useContext } from 'react'
import styled, { ThemeContext } from 'styled-components/macro'
import useENS from '../../hooks/useENS'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink, TYPE } from '../../theme'
import { ExternalLink, ThemedText } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { AutoColumn } from '../Column'
import { RowBetween } from '../Row'
@@ -106,9 +108,9 @@ export default function AddressInputPanel({
<InputContainer>
<AutoColumn gap="md">
<RowBetween>
<TYPE.black color={theme.text2} fontWeight={500} fontSize={14}>
<ThemedText.Black color={theme.text2} fontWeight={500} fontSize={14}>
{label ?? <Trans>Recipient</Trans>}
</TYPE.black>
</ThemedText.Black>
{address && chainId && (
<ExternalLink
href={getExplorerLink(chainId, name ?? address, ExplorerDataType.ADDRESS)}

View File

@@ -0,0 +1,34 @@
import { animated, useSpring } from 'react-spring'
import useResizeObserver from 'use-resize-observer'
/**
* @param open conditional to show content or hide
* @returns Wrapper to smoothly hide and expand content
*/
export default function AnimatedDropdown({ open, children }: React.PropsWithChildren<{ open: boolean }>) {
const { ref, height } = useResizeObserver()
const props = useSpring({
height: open ? height ?? 0 : 0,
config: {
mass: 1.2,
tension: 300,
friction: 20,
clamp: true,
velocity: 0.01,
},
})
return (
<animated.div
style={{
...props,
overflow: 'hidden',
width: '100%',
willChange: 'height',
}}
>
<div ref={ref}>{children}</div>
</animated.div>
)
}

View File

@@ -23,7 +23,7 @@ export const BaseButton = styled(RebassButton)<
border-radius: ${({ $borderRadius }) => $borderRadius ?? '20px'};
outline: none;
border: 1px solid transparent;
color: white;
color: ${({ theme }) => theme.text1};
text-decoration: none;
display: flex;
justify-content: center;
@@ -33,6 +33,7 @@ export const BaseButton = styled(RebassButton)<
position: relative;
z-index: 1;
&:disabled {
opacity: 50%;
cursor: auto;
pointer-events: none;
}
@@ -236,7 +237,7 @@ const ButtonConfirmedStyle = styled(BaseButton)`
/* border: 1px solid ${({ theme }) => theme.green1}; */
&:disabled {
/* opacity: 50%; */
opacity: 50%;
background-color: ${({ theme }) => theme.bg2};
color: ${({ theme }) => theme.text2};
cursor: auto;
@@ -315,8 +316,8 @@ const ActiveOutlined = styled(ButtonOutlined)`
`
const Circle = styled.div`
height: 20px;
width: 20px;
height: 17px;
width: 17px;
border-radius: 50%;
background-color: ${({ theme }) => theme.primary1};
display: flex;
@@ -325,11 +326,11 @@ const Circle = styled.div`
`
const CheckboxWrapper = styled.div`
width: 30px;
width: 20px;
padding: 0 10px;
position: absolute;
top: 10px;
right: 10px;
top: 11px;
right: 15px;
`
const ResponsiveCheck = styled(Check)`

View File

@@ -1,11 +1,14 @@
import { Trans } from '@lingui/macro'
// eslint-disable-next-line no-restricted-imports
import { t } from '@lingui/macro'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import HoverInlineText from 'components/HoverInlineText'
import { useMemo } from 'react'
import useTheme from '../../hooks/useTheme'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { warningSeverity } from '../../utils/prices'
import { MouseoverTooltip } from '../Tooltip'
export function FiatValue({
fiatValue,
@@ -25,10 +28,14 @@ export function FiatValue({
}, [priceImpact, theme.green1, theme.red1, theme.text3, theme.yellow1])
return (
<TYPE.body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
<ThemedText.Body fontSize={14} color={fiatValue ? theme.text3 : theme.text4}>
{fiatValue ? (
<Trans>
~$ <HoverInlineText text={fiatValue?.toSignificant(6, { groupSeparator: ',' })} />
$
<HoverInlineText
text={fiatValue?.toSignificant(6, { groupSeparator: ',' })}
textColor={fiatValue ? theme.text3 : theme.text4}
/>
</Trans>
) : (
''
@@ -36,9 +43,11 @@ export function FiatValue({
{priceImpact ? (
<span style={{ color: priceImpactColor }}>
{' '}
(<Trans>{priceImpact.multiply(-1).toSignificant(3)}%</Trans>)
<MouseoverTooltip text={t`The estimated difference between the USD values of input and output amounts.`}>
(<Trans>{priceImpact.multiply(-1).toSignificant(3)}%</Trans>)
</MouseoverTooltip>
</span>
) : null}
</TYPE.body>
</ThemedText.Body>
)
}

View File

@@ -13,7 +13,7 @@ import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import useTheme from '../../hooks/useTheme'
import { useActiveWeb3React } from '../../hooks/web3'
import { useCurrencyBalance } from '../../state/wallet/hooks'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { ButtonGray } from '../Button'
import CurrencyLogo from '../CurrencyLogo'
import DoubleCurrencyLogo from '../DoubleLogo'
@@ -29,6 +29,8 @@ const InputPanel = styled.div<{ hideInput?: boolean }>`
background-color: ${({ theme, hideInput }) => (hideInput ? 'transparent' : theme.bg2)};
z-index: 1;
width: ${({ hideInput }) => (hideInput ? '100%' : 'initial')};
transition: height 1s ease;
will-change: height;
`
const FixedContainer = styled.div`
@@ -36,8 +38,7 @@ const FixedContainer = styled.div`
height: 100%;
position: absolute;
border-radius: 20px;
background-color: ${({ theme }) => theme.bg1};
opacity: 0.95;
background-color: ${({ theme }) => theme.bg2};
display: flex;
align-items: center;
justify-content: center;
@@ -46,7 +47,7 @@ const FixedContainer = styled.div`
const Container = styled.div<{ hideInput: boolean }>`
border-radius: ${({ hideInput }) => (hideInput ? '16px' : '20px')};
border: 1px solid ${({ theme, hideInput }) => (hideInput ? ' transparent' : theme.bg2)};
border: 1px solid ${({ theme }) => theme.bg0};
background-color: ${({ theme }) => theme.bg1};
width: ${({ hideInput }) => (hideInput ? '100%' : 'initial')};
:focus,
@@ -56,35 +57,35 @@ const Container = styled.div<{ hideInput: boolean }>`
`
const CurrencySelect = styled(ButtonGray)<{ visible: boolean; selected: boolean; hideInput?: boolean }>`
visibility: ${({ visible }) => (visible ? 'visible' : 'hidden')};
align-items: center;
font-size: 24px;
font-weight: 500;
background-color: ${({ selected, theme }) => (selected ? theme.bg0 : theme.primary1)};
color: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)};
border-radius: 16px;
background-color: ${({ selected, theme }) => (selected ? theme.bg2 : theme.primary1)};
box-shadow: ${({ selected }) => (selected ? 'none' : '0px 6px 10px rgba(0, 0, 0, 0.075)')};
box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075);
outline: none;
color: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)};
cursor: pointer;
border-radius: 16px;
outline: none;
user-select: none;
border: none;
font-size: 24px;
font-weight: 500;
height: ${({ hideInput }) => (hideInput ? '2.8rem' : '2.4rem')};
width: ${({ hideInput }) => (hideInput ? '100%' : 'initial')};
padding: 0 8px;
justify-content: space-between;
margin-right: ${({ hideInput }) => (hideInput ? '0' : '12px')};
margin-left: ${({ hideInput }) => (hideInput ? '0' : '12px')};
:focus,
:hover {
background-color: ${({ selected, theme }) => (selected ? theme.bg2 : darken(0.05, theme.primary1))};
background-color: ${({ selected, theme }) => (selected ? theme.bg3 : darken(0.05, theme.primary1))};
}
visibility: ${({ visible }) => (visible ? 'visible' : 'hidden')};
`
const InputRow = styled.div<{ selected: boolean }>`
${({ theme }) => theme.flexRowNoWrap}
align-items: center;
justify-content: space-between;
padding: ${({ selected }) => (selected ? ' 1rem 1rem 0.75rem 1rem' : '1rem 1rem 0.75rem 1rem')};
padding: ${({ selected }) => (selected ? ' 1rem 1rem 0.75rem 1rem' : '1rem 1rem 1rem 1rem')};
`
const LabelRow = styled.div`
@@ -128,28 +129,30 @@ const StyledTokenName = styled.span<{ active?: boolean }>`
const StyledBalanceMax = styled.button<{ disabled?: boolean }>`
background-color: transparent;
background-color: ${({ theme }) => theme.primary5};
border: none;
border-radius: 12px;
font-size: 14px;
font-weight: 500;
color: ${({ theme }) => theme.primary1};
cursor: pointer;
padding: 0;
color: ${({ theme }) => theme.primaryText1};
opacity: ${({ disabled }) => (!disabled ? 1 : 0.4)};
pointer-events: ${({ disabled }) => (!disabled ? 'initial' : 'none')};
font-size: 11px;
font-weight: 500;
margin-left: 0.25rem;
opacity: ${({ disabled }) => (!disabled ? 1 : 0.4)};
padding: 4px 6px;
pointer-events: ${({ disabled }) => (!disabled ? 'initial' : 'none')};
:hover {
opacity: ${({ disabled }) => (!disabled ? 0.8 : 0.4)};
}
:focus {
outline: none;
}
${({ theme }) => theme.mediaWidth.upToExtraSmall`
margin-right: 0.5rem;
`};
`
const StyledNumericalInput = styled(NumericalInput)<{ $loading: boolean }>`
${loadingOpacityMixin}
${loadingOpacityMixin};
text-align: left;
`
interface CurrencyInputPanelProps {
@@ -212,14 +215,23 @@ export default function CurrencyInputPanel({
<FixedContainer>
<AutoColumn gap="sm" justify="center">
<Lock />
<TYPE.label fontSize="12px" textAlign="center" padding="0 12px">
<ThemedText.Label fontSize="12px" textAlign="center" padding="0 12px">
<Trans>The market price is outside your specified price range. Single-asset deposit only.</Trans>
</TYPE.label>
</ThemedText.Label>
</AutoColumn>
</FixedContainer>
)}
<Container hideInput={hideInput}>
<InputRow style={hideInput ? { padding: '0', borderRadius: '8px' } : {}} selected={!onCurrencySelect}>
{!hideInput && (
<StyledNumericalInput
className="token-amount-input"
value={value}
onUserInput={onUserInput}
$loading={loading}
/>
)}
<CurrencySelect
visible={currency !== undefined}
selected={!!currency}
@@ -257,24 +269,19 @@ export default function CurrencyInputPanel({
{onCurrencySelect && <StyledDropDown selected={!!currency} />}
</Aligner>
</CurrencySelect>
{!hideInput && (
<StyledNumericalInput
className="token-amount-input"
value={value}
onUserInput={onUserInput}
$loading={loading}
/>
)}
</InputRow>
{!hideInput && !hideBalance && (
{!hideInput && !hideBalance && currency && (
<FiatRow>
<RowBetween>
<LoadingOpacityContainer $loading={loading}>
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
</LoadingOpacityContainer>
{account ? (
<RowFixed style={{ height: '17px' }}>
<TYPE.body
<ThemedText.Body
onClick={onMax}
color={theme.text2}
fontWeight={400}
color={theme.text3}
fontWeight={500}
fontSize={14}
style={{ display: 'inline', cursor: 'pointer' }}
>
@@ -282,24 +289,19 @@ export default function CurrencyInputPanel({
renderBalance ? (
renderBalance(selectedCurrencyBalance)
) : (
<Trans>
Balance: {formatCurrencyAmount(selectedCurrencyBalance, 4)} {currency.symbol}
</Trans>
<Trans>Balance: {formatCurrencyAmount(selectedCurrencyBalance, 4)}</Trans>
)
) : null}
</TYPE.body>
</ThemedText.Body>
{showMaxButton && selectedCurrencyBalance ? (
<StyledBalanceMax onClick={onMax}>
<Trans>(Max)</Trans>
<Trans>MAX</Trans>
</StyledBalanceMax>
) : null}
</RowFixed>
) : (
<span />
)}
<LoadingOpacityContainer $loading={loading}>
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
</LoadingOpacityContainer>
</RowBetween>
</FiatRow>
)}

View File

@@ -1,11 +1,12 @@
import { Currency } from '@uniswap/sdk-core'
import EthereumLogo from 'assets/images/ethereum-logo.png'
import MaticLogo from 'assets/svg/matic-token-icon.svg'
import { SupportedChainId } from 'constants/chains'
import useHttpLocations from 'hooks/useHttpLocations'
import React, { useMemo } from 'react'
import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo'
import styled from 'styled-components/macro'
import EthereumLogo from '../../assets/images/ethereum-logo.png'
import useHttpLocations from '../../hooks/useHttpLocations'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
import Logo from '../Logo'
type Network = 'ethereum' | 'arbitrum' | 'optimism'
@@ -34,19 +35,27 @@ export const getTokenLogoURL = (
}
}
const StyledEthereumLogo = styled.img<{ size: string }>`
const StyledNativeLogo = styled.img<{ size: string }>`
width: ${({ size }) => size};
height: ${({ size }) => size};
box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075);
border-radius: 24px;
background: radial-gradient(white 50%, #ffffff00 calc(75% + 1px), #ffffff00 100%);
border-radius: 50%;
-mox-box-shadow: 0 0 1px white;
-webkit-box-shadow: 0 0 1px white;
box-shadow: 0 0 1px white;
border: 0px solid rgba(255, 255, 255, 0);
`
const StyledLogo = styled(Logo)<{ size: string }>`
width: ${({ size }) => size};
height: ${({ size }) => size};
border-radius: ${({ size }) => size};
box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075);
background-color: ${({ theme }) => theme.white};
background: radial-gradient(white 50%, #ffffff00 calc(75% + 1px), #ffffff00 100%);
border-radius: 50%;
-mox-box-shadow: 0 0 1px black;
-webkit-box-shadow: 0 0 1px black;
box-shadow: 0 0 1px black;
border: 0px solid rgba(255, 255, 255, 0);
`
export default function CurrencyLogo({
@@ -79,7 +88,17 @@ export default function CurrencyLogo({
}, [currency, uriLocations])
if (currency?.isNative) {
return <StyledEthereumLogo src={EthereumLogo} alt="ethereum logo" size={size} style={style} {...rest} />
let nativeLogoUrl: string
switch (currency.chainId) {
case SupportedChainId.POLYGON_MUMBAI:
case SupportedChainId.POLYGON:
nativeLogoUrl = MaticLogo
break
default:
nativeLogoUrl = EthereumLogo
break
}
return <StyledNativeLogo src={nativeLogoUrl} alt="ethereum logo" size={size} style={style} {...rest} />
}
return <StyledLogo size={size} srcs={srcs} alt={`${currency?.symbol ?? 'token'} logo`} style={style} {...rest} />

View File

@@ -1,10 +1,12 @@
import { Trans } from '@lingui/macro'
import { L2_CHAIN_IDS, SupportedChainId } from 'constants/chains'
import { SupportedChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import { AlertOctagon } from 'react-feather'
import styled from 'styled-components/macro'
import { ExternalLink } from 'theme'
import { isL2ChainId } from '../../utils/chains'
const Root = styled.div`
background-color: ${({ theme }) => (theme.darkMode ? '#888D9B' : '#CED0D9')};
border-radius: 18px;
@@ -18,7 +20,6 @@ const Root = styled.div`
max-width: 880px;
`
const WarningIcon = styled(AlertOctagon)`
display: block;
margin: auto 16px auto 0;
min-height: 22px;
min-width: 22px;
@@ -28,50 +29,54 @@ const ReadMoreLink = styled(ExternalLink)`
text-decoration: underline;
`
export default function DowntimeWarning() {
const { chainId } = useActiveWeb3React()
if (!chainId || !L2_CHAIN_IDS.includes(chainId)) {
return null
}
const Content = () => {
switch (chainId) {
case SupportedChainId.OPTIMISM:
case SupportedChainId.OPTIMISTIC_KOVAN:
return (
<div>
<Trans>
Optimistic Ethereum is in Beta and may experience downtime. Optimism expects planned downtime to upgrade
the network in the near future. During downtime, your position will not earn fees and you will be unable
to remove liquidity.{' '}
<ReadMoreLink href="https://help.uniswap.org/en/articles/5406082-what-happens-if-the-optimistic-ethereum-network-experiences-downtime">
Read more.
</ReadMoreLink>
</Trans>
</div>
)
case SupportedChainId.ARBITRUM_ONE:
case SupportedChainId.ARBITRUM_RINKEBY:
return (
<div>
<Trans>
Arbitrum is in Beta and may experience downtime. During downtime, your position will not earn fees and you
will be unable to remove liquidity.{' '}
<ReadMoreLink href="https://help.uniswap.org/en/articles/5576122-arbitrum-network-downtime">
Read more.
</ReadMoreLink>
</Trans>
</div>
)
default:
return null
}
}
function Wrapper({ children }: { children: React.ReactNode }) {
return (
<Root>
<WarningIcon />
<Content />
<div>{children}</div>
</Root>
)
}
/**
* Shows a downtime warning for the network if it's relevant
*/
export default function DowntimeWarning() {
const { chainId } = useActiveWeb3React()
if (!isL2ChainId(chainId)) {
return null
}
switch (chainId) {
case SupportedChainId.OPTIMISM:
case SupportedChainId.OPTIMISTIC_KOVAN:
return (
<Wrapper>
<Trans>
Optimism is in Beta and may experience downtime. Optimism expects planned downtime to upgrade the network in
the near future. During downtime, your position will not earn fees and you will be unable to remove
liquidity.{' '}
<ReadMoreLink href="https://help.uniswap.org/en/articles/5406082-what-happens-if-the-optimistic-ethereum-network-experiences-downtime">
Read more.
</ReadMoreLink>
</Trans>
</Wrapper>
)
case SupportedChainId.ARBITRUM_ONE:
case SupportedChainId.ARBITRUM_RINKEBY:
return (
<Wrapper>
<Trans>
Arbitrum is in Beta and may experience downtime. During downtime, your position will not earn fees and you
will be unable to remove liquidity.{' '}
<ReadMoreLink href="https://help.uniswap.org/en/articles/5576122-arbitrum-network-downtime">
Read more.
</ReadMoreLink>
</Trans>
</Wrapper>
)
default:
return null
}
}

View File

@@ -4,7 +4,7 @@ import ReactGA from 'react-ga'
import styled from 'styled-components/macro'
import store, { AppState } from '../../state'
import { ExternalLink, TYPE } from '../../theme'
import { ExternalLink, ThemedText } from '../../theme'
import { userAgent } from '../../utils/userAgent'
import { AutoColumn } from '../Column'
import { AutoRow } from '../Row'
@@ -47,6 +47,8 @@ type ErrorBoundaryState = {
error: Error | null
}
const IS_UNISWAP = window.location.hostname === 'app.uniswap.org'
export default class ErrorBoundary extends React.Component<unknown, ErrorBoundaryState> {
constructor(props: unknown) {
super(props)
@@ -67,6 +69,7 @@ export default class ErrorBoundary extends React.Component<unknown, ErrorBoundar
render() {
const { error } = this.state
if (error !== null) {
const encodedBody = encodeURIComponent(issueBody(error))
return (
@@ -74,39 +77,41 @@ export default class ErrorBoundary extends React.Component<unknown, ErrorBoundar
<BodyWrapper>
<AutoColumn gap={'md'}>
<SomethingWentWrongWrapper>
<TYPE.label fontSize={24} fontWeight={600}>
<ThemedText.Label fontSize={24} fontWeight={600}>
<Trans>Something went wrong</Trans>
</TYPE.label>
</ThemedText.Label>
</SomethingWentWrongWrapper>
<CodeBlockWrapper>
<code>
<TYPE.main fontSize={10}>{error.stack}</TYPE.main>
<ThemedText.Main fontSize={10}>{error.stack}</ThemedText.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}>
<Trans>Create an issue on GitHub</Trans>
<span></span>
</TYPE.link>
</ExternalLink>
</LinkWrapper>
<LinkWrapper>
<ExternalLink id="get-support-on-discord" href="https://discord.gg/FCfyBSbCU5" target="_blank">
<TYPE.link fontSize={16}>
<Trans>Get support on Discord</Trans>
<span></span>
</TYPE.link>
</ExternalLink>
</LinkWrapper>
</AutoRow>
{IS_UNISWAP ? (
<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"
>
<ThemedText.Link fontSize={16}>
<Trans>Create an issue on GitHub</Trans>
<span></span>
</ThemedText.Link>
</ExternalLink>
</LinkWrapper>
<LinkWrapper>
<ExternalLink id="get-support-on-discord" href="https://discord.gg/FCfyBSbCU5" target="_blank">
<ThemedText.Link fontSize={16}>
<Trans>Get support on Discord</Trans>
<span></span>
</ThemedText.Link>
</ExternalLink>
</LinkWrapper>
</AutoRow>
) : null}
</AutoColumn>
</BodyWrapper>
</FallbackWrapper>
@@ -121,7 +126,7 @@ function getRelevantState(): null | keyof AppState {
if (!path.startsWith('#/')) {
return null
}
const pieces = path.substring(2).split(/[\/\\?]/)
const pieces = path.substring(2).split(/[/\\?]/)
switch (pieces[0]) {
case 'swap':
return 'swap'

View File

@@ -0,0 +1,51 @@
import { Trans } from '@lingui/macro'
import { FeeAmount } from '@uniswap/v3-sdk'
import { ButtonRadioChecked } from 'components/Button'
import { AutoColumn } from 'components/Column'
import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution'
import { PoolState } from 'hooks/usePools'
import React from 'react'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { FeeTierPercentageBadge } from './FeeTierPercentageBadge'
import { FEE_AMOUNT_DETAIL } from './shared'
const ResponsiveText = styled(ThemedText.Label)`
line-height: 16px;
font-size: 14px;
${({ theme }) => theme.mediaWidth.upToSmall`
font-size: 12px;
line-height: 12px;
`};
`
interface FeeOptionProps {
feeAmount: FeeAmount
active: boolean
distributions: ReturnType<typeof useFeeTierDistribution>['distributions']
poolState: PoolState
onClick: () => void
}
export function FeeOption({ feeAmount, active, poolState, distributions, onClick }: FeeOptionProps) {
return (
<ButtonRadioChecked active={active} onClick={onClick}>
<AutoColumn gap="sm" justify="flex-start">
<AutoColumn justify="flex-start" gap="6px">
<ResponsiveText>
<Trans>{FEE_AMOUNT_DETAIL[feeAmount].label}%</Trans>
</ResponsiveText>
<ThemedText.Main fontWeight={400} fontSize="12px" textAlign="left">
{FEE_AMOUNT_DETAIL[feeAmount].description}
</ThemedText.Main>
</AutoColumn>
{distributions && (
<FeeTierPercentageBadge distributions={distributions} feeAmount={feeAmount} poolState={poolState} />
)}
</AutoColumn>
</ButtonRadioChecked>
)
}

View File

@@ -0,0 +1,31 @@
import { Trans } from '@lingui/macro'
import { FeeAmount } from '@uniswap/v3-sdk'
import Badge from 'components/Badge'
import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution'
import { PoolState } from 'hooks/usePools'
import React from 'react'
import { ThemedText } from 'theme'
export function FeeTierPercentageBadge({
feeAmount,
distributions,
poolState,
}: {
feeAmount: FeeAmount
distributions: ReturnType<typeof useFeeTierDistribution>['distributions']
poolState: PoolState
}) {
return (
<Badge>
<ThemedText.Label fontSize={10}>
{!distributions || poolState === PoolState.NOT_EXISTS || poolState === PoolState.INVALID ? (
<Trans>Not created</Trans>
) : distributions[feeAmount] !== undefined ? (
<Trans>{distributions[feeAmount]?.toFixed(0)}% select</Trans>
) : (
<Trans>No data</Trans>
)}
</ThemedText.Label>
</Badge>
)
}

View File

@@ -1,19 +1,24 @@
import { Trans } from '@lingui/macro'
import { Currency } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk'
import Badge from 'components/Badge'
import { ButtonGray, ButtonRadioChecked } from 'components/Button'
import { ButtonGray } from 'components/Button'
import Card from 'components/Card'
import { AutoColumn } from 'components/Column'
import { RowBetween } from 'components/Row'
import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution'
import { PoolState, usePools } from 'hooks/usePools'
import usePrevious from 'hooks/usePrevious'
import { useActiveWeb3React } from 'hooks/web3'
import { DynamicSection } from 'pages/AddLiquidity/styled'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import ReactGA from 'react-ga'
import { Box } from 'rebass'
import styled, { keyframes } from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { FeeOption } from './FeeOption'
import { FeeTierPercentageBadge } from './FeeTierPercentageBadge'
import { FEE_AMOUNT_DETAIL } from './shared'
const pulse = (color: string) => keyframes`
0% {
@@ -28,45 +33,18 @@ const pulse = (color: string) => keyframes`
box-shadow: 0 0 0 0 ${color};
}
`
const ResponsiveText = styled(TYPE.label)`
line-height: 16px;
${({ theme }) => theme.mediaWidth.upToSmall`
font-size: 12px;
line-height: 12px;
`};
`
const FocusedOutlineCard = styled(Card)<{ pulsing: boolean }>`
border: 1px solid ${({ theme }) => theme.bg2};
animation: ${({ pulsing, theme }) => pulsing && pulse(theme.primary1)} 0.6s linear;
align-self: center;
`
const FeeAmountLabel = {
[FeeAmount.LOW]: {
label: '0.05',
description: <Trans>Best for stable pairs.</Trans>,
},
[FeeAmount.MEDIUM]: {
label: '0.3',
description: <Trans>Best for most pairs.</Trans>,
},
[FeeAmount.HIGH]: {
label: '1',
description: <Trans>Best for exotic pairs.</Trans>,
},
}
const FeeTierPercentageBadge = ({ percentage }: { percentage: number | undefined }) => {
return (
<Badge>
<TYPE.label fontSize={12}>
{percentage !== undefined ? <Trans>{percentage?.toFixed(0)}% select</Trans> : <Trans>Not created</Trans>}
</TYPE.label>
</Badge>
)
}
const Select = styled.div`
align-items: flex-start;
display: grid;
grid-auto-flow: column;
grid-gap: 8px;
`
export default function FeeSelector({
disabled = false,
@@ -81,8 +59,39 @@ export default function FeeSelector({
currencyA?: Currency | undefined
currencyB?: Currency | undefined
}) {
const { chainId } = useActiveWeb3React()
const { isLoading, isError, largestUsageFeeTier, distributions } = useFeeTierDistribution(currencyA, currencyB)
// get pool data on-chain for latest states
const pools = usePools([
[currencyA, currencyB, FeeAmount.LOWEST],
[currencyA, currencyB, FeeAmount.LOW],
[currencyA, currencyB, FeeAmount.MEDIUM],
[currencyA, currencyB, FeeAmount.HIGH],
])
const poolsByFeeTier: Record<FeeAmount, PoolState> = useMemo(
() =>
pools.reduce(
(acc, [curPoolState, curPool]) => {
acc = {
...acc,
...{ [curPool?.fee as FeeAmount]: curPoolState },
}
return acc
},
{
// default all states to NOT_EXISTS
[FeeAmount.LOWEST]: PoolState.NOT_EXISTS,
[FeeAmount.LOW]: PoolState.NOT_EXISTS,
[FeeAmount.MEDIUM]: PoolState.NOT_EXISTS,
[FeeAmount.HIGH]: PoolState.NOT_EXISTS,
}
),
[pools]
)
const [showOptions, setShowOptions] = useState(false)
const [pulsing, setPulsing] = useState(false)
@@ -91,7 +100,7 @@ export default function FeeSelector({
const recommended = useRef(false)
const handleFeePoolSelectWithEvent = useCallback(
(fee) => {
(fee: FeeAmount) => {
ReactGA.event({
category: 'FeePoolSelect',
action: 'Manual',
@@ -140,20 +149,26 @@ export default function FeeSelector({
<AutoColumn id="add-liquidity-selected-fee">
{!feeAmount ? (
<>
<TYPE.label>
<ThemedText.Label>
<Trans>Fee tier</Trans>
</TYPE.label>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
</ThemedText.Label>
<ThemedText.Main fontWeight={400} fontSize="12px" textAlign="left">
<Trans>The % you will earn in fees.</Trans>
</TYPE.main>
</ThemedText.Main>
</>
) : (
<>
<TYPE.label className="selected-fee-label">
<Trans>{FeeAmountLabel[feeAmount].label}% fee tier</Trans>
</TYPE.label>
<ThemedText.Label className="selected-fee-label">
<Trans>{FEE_AMOUNT_DETAIL[feeAmount].label}% fee tier</Trans>
</ThemedText.Label>
<Box style={{ width: 'fit-content', marginTop: '8px' }} className="selected-fee-percentage">
{distributions && feeAmount && <FeeTierPercentageBadge percentage={distributions[feeAmount]} />}
{distributions && (
<FeeTierPercentageBadge
distributions={distributions}
feeAmount={feeAmount}
poolState={poolsByFeeTier[feeAmount]}
/>
)}
</Box>
</>
)}
@@ -165,63 +180,25 @@ export default function FeeSelector({
</RowBetween>
</FocusedOutlineCard>
{showOptions && (
<RowBetween>
<ButtonRadioChecked
width="32%"
active={feeAmount === FeeAmount.LOW}
onClick={() => handleFeePoolSelectWithEvent(FeeAmount.LOW)}
>
<AutoColumn gap="sm" justify="flex-start">
<AutoColumn justify="flex-start" gap="6px">
<ResponsiveText>
<Trans>0.05% fee</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
<Trans>Best for stable pairs.</Trans>
</TYPE.main>
</AutoColumn>
{distributions && <FeeTierPercentageBadge percentage={distributions[FeeAmount.LOW]} />}
</AutoColumn>
</ButtonRadioChecked>
<ButtonRadioChecked
width="32%"
active={feeAmount === FeeAmount.MEDIUM}
onClick={() => handleFeePoolSelectWithEvent(FeeAmount.MEDIUM)}
>
<AutoColumn gap="sm" justify="flex-start">
<AutoColumn justify="flex-start" gap="4px">
<ResponsiveText>
<Trans>0.3% fee</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
<Trans>Best for most pairs.</Trans>
</TYPE.main>
</AutoColumn>
{distributions && <FeeTierPercentageBadge percentage={distributions[FeeAmount.MEDIUM]} />}
</AutoColumn>
</ButtonRadioChecked>
<ButtonRadioChecked
width="32%"
active={feeAmount === FeeAmount.HIGH}
onClick={() => handleFeePoolSelectWithEvent(FeeAmount.HIGH)}
>
<AutoColumn gap="sm" justify="flex-start">
<AutoColumn justify="flex-start" gap="4px">
<ResponsiveText>
<Trans>1% fee</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
<Trans>Best for exotic pairs.</Trans>
</TYPE.main>
</AutoColumn>
{distributions && <FeeTierPercentageBadge percentage={distributions[FeeAmount.HIGH]} />}
</AutoColumn>
</ButtonRadioChecked>
</RowBetween>
{chainId && showOptions && (
<Select>
{[FeeAmount.LOWEST, FeeAmount.LOW, FeeAmount.MEDIUM, FeeAmount.HIGH].map((_feeAmount, i) => {
const { supportedChains } = FEE_AMOUNT_DETAIL[_feeAmount]
if (supportedChains.includes(chainId)) {
return (
<FeeOption
feeAmount={_feeAmount}
active={feeAmount === _feeAmount}
onClick={() => handleFeePoolSelectWithEvent(_feeAmount)}
distributions={distributions}
poolState={poolsByFeeTier[_feeAmount]}
key={i}
/>
)
}
return null
})}
</Select>
)}
</DynamicSection>
</AutoColumn>

View File

@@ -0,0 +1,30 @@
import { Trans } from '@lingui/macro'
import { FeeAmount } from '@uniswap/v3-sdk'
import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from 'constants/chains'
import { ReactNode } from 'react'
export const FEE_AMOUNT_DETAIL: Record<
FeeAmount,
{ label: string; description: ReactNode; supportedChains: SupportedChainId[] }
> = {
[FeeAmount.LOWEST]: {
label: '0.01',
description: <Trans>Best for very stable pairs.</Trans>,
supportedChains: [SupportedChainId.MAINNET],
},
[FeeAmount.LOW]: {
label: '0.05',
description: <Trans>Best for stable pairs.</Trans>,
supportedChains: ALL_SUPPORTED_CHAIN_IDS,
},
[FeeAmount.MEDIUM]: {
label: '0.3',
description: <Trans>Best for most pairs.</Trans>,
supportedChains: ALL_SUPPORTED_CHAIN_IDS,
},
[FeeAmount.HIGH]: {
label: '1',
description: <Trans>Best for exotic pairs.</Trans>,
supportedChains: ALL_SUPPORTED_CHAIN_IDS,
},
}

View File

@@ -0,0 +1,26 @@
import { ReactElement } from 'react'
import styled from 'styled-components/macro'
import SantaHat from '../../assets/images/santa-hat.png'
const SantaHatImage = styled.img`
position: absolute;
top: -4px;
right: -4px;
height: 18px;
`
const Christmas = <SantaHatImage src={SantaHat} alt="Santa hat" />
const DATE_TO_ORNAMENT: { [date: string]: ReactElement } = {
'12-24': Christmas,
'12-25': Christmas,
}
const HolidayOrnament = () => {
// months in javascript are 0 indexed...
const today = `${new Date().getMonth() + 1}-${new Date().getDate()}`
return DATE_TO_ORNAMENT[today] || null
}
export default HolidayOrnament

View File

@@ -1,22 +1,16 @@
import { Trans } from '@lingui/macro'
import {
ARBITRUM_HELP_CENTER_LINK,
CHAIN_INFO,
L2_CHAIN_IDS,
OPTIMISM_HELP_CENTER_LINK,
SupportedChainId,
SupportedL2ChainId,
} from 'constants/chains'
import { CHAIN_INFO, SupportedChainId } from 'constants/chains'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
import { useActiveWeb3React } from 'hooks/web3'
import { useCallback, useRef } from 'react'
import { ArrowDownCircle, ChevronDown } from 'react-feather'
import { ApplicationModal } from 'state/application/actions'
import { useModalOpen, useToggleModal } from 'state/application/hooks'
import { useAppSelector } from 'state/hooks'
import { addPopup, ApplicationModal } from 'state/application/reducer'
import styled from 'styled-components/macro'
import { ExternalLink, MEDIA_WIDTHS } from 'theme'
import { switchToNetwork } from 'utils/switchToNetwork'
import { useAppDispatch } from '../../state/hooks'
import { switchToNetwork } from '../../utils/switchToNetwork'
const ActiveRowLinkList = styled.div`
display: flex;
@@ -34,17 +28,16 @@ const ActiveRowLinkList = styled.div`
text-decoration: none;
}
& > a:first-child {
border-top: 1px solid ${({ theme }) => theme.text2};
margin: 0;
margin-top: 6px;
margin-top: 0px;
padding-top: 10px;
}
`
const ActiveRowWrapper = styled.div`
background-color: ${({ theme }) => theme.bg2};
background-color: ${({ theme }) => theme.bg1};
border-radius: 8px;
cursor: pointer;
padding: 8px 0 8px 0;
padding: 8px;
width: 100%;
`
const FlyoutHeader = styled.div`
@@ -53,7 +46,7 @@ const FlyoutHeader = styled.div`
`
const FlyoutMenu = styled.div`
align-items: flex-start;
background-color: ${({ theme }) => theme.bg1};
background-color: ${({ theme }) => theme.bg0};
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: 20px;
@@ -75,7 +68,7 @@ const FlyoutMenu = styled.div`
`
const FlyoutRow = styled.div<{ active: boolean }>`
align-items: center;
background-color: ${({ active, theme }) => (active ? theme.bg2 : 'transparent')};
background-color: ${({ active, theme }) => (active ? theme.bg1 : 'transparent')};
border-radius: 8px;
cursor: pointer;
display: flex;
@@ -113,9 +106,9 @@ const SelectorLabel = styled(NetworkLabel)`
`
const SelectorControls = styled.div<{ interactive: boolean }>`
align-items: center;
background-color: ${({ theme }) => theme.bg1};
border: 2px solid ${({ theme }) => theme.bg1};
border-radius: 12px;
background-color: ${({ theme }) => theme.bg0};
border: 2px solid ${({ theme }) => theme.bg0};
border-radius: 16px;
color: ${({ theme }) => theme.text1};
cursor: ${({ interactive }) => (interactive ? 'pointer' : 'auto')};
display: flex;
@@ -135,9 +128,9 @@ const SelectorWrapper = styled.div`
}
`
const StyledChevronDown = styled(ChevronDown)`
width: 12px;
width: 16px;
`
const BridgeText = ({ chainId }: { chainId: SupportedL2ChainId }) => {
const BridgeLabel = ({ chainId }: { chainId: SupportedChainId }) => {
switch (chainId) {
case SupportedChainId.ARBITRUM_ONE:
case SupportedChainId.ARBITRUM_RINKEBY:
@@ -145,11 +138,14 @@ const BridgeText = ({ chainId }: { chainId: SupportedL2ChainId }) => {
case SupportedChainId.OPTIMISM:
case SupportedChainId.OPTIMISTIC_KOVAN:
return <Trans>Optimism Gateway</Trans>
case SupportedChainId.POLYGON:
case SupportedChainId.POLYGON_MUMBAI:
return <Trans>Polygon Bridge</Trans>
default:
return <Trans>Bridge</Trans>
}
}
const ExplorerText = ({ chainId }: { chainId: SupportedL2ChainId }) => {
const ExplorerLabel = ({ chainId }: { chainId: SupportedChainId }) => {
switch (chainId) {
case SupportedChainId.ARBITRUM_ONE:
case SupportedChainId.ARBITRUM_RINKEBY:
@@ -157,91 +153,108 @@ const ExplorerText = ({ chainId }: { chainId: SupportedL2ChainId }) => {
case SupportedChainId.OPTIMISM:
case SupportedChainId.OPTIMISTIC_KOVAN:
return <Trans>Optimistic Etherscan</Trans>
case SupportedChainId.POLYGON:
case SupportedChainId.POLYGON_MUMBAI:
return <Trans>Polygonscan</Trans>
default:
return <Trans>Explorer</Trans>
return <Trans>Etherscan</Trans>
}
}
function Row({
targetChain,
onSelectChain,
}: {
targetChain: SupportedChainId
onSelectChain: (targetChain: number) => void
}) {
const { library, chainId } = useActiveWeb3React()
if (!library || !chainId) {
return null
}
const active = chainId === targetChain
const { helpCenterUrl, explorer, bridge, label, logoUrl } = CHAIN_INFO[targetChain]
const rowContent = (
<FlyoutRow onClick={() => onSelectChain(targetChain)} active={active}>
<Logo src={logoUrl} />
<NetworkLabel>{label}</NetworkLabel>
{chainId === targetChain && <FlyoutRowActiveIndicator />}
</FlyoutRow>
)
if (active) {
return (
<ActiveRowWrapper>
{rowContent}
<ActiveRowLinkList>
{bridge ? (
<ExternalLink href={bridge}>
<BridgeLabel chainId={chainId} /> <LinkOutCircle />
</ExternalLink>
) : null}
{explorer ? (
<ExternalLink href={explorer}>
<ExplorerLabel chainId={chainId} /> <LinkOutCircle />
</ExternalLink>
) : null}
{helpCenterUrl ? (
<ExternalLink href={helpCenterUrl}>
<Trans>Help Center</Trans> <LinkOutCircle />
</ExternalLink>
) : null}
</ActiveRowLinkList>
</ActiveRowWrapper>
)
}
return rowContent
}
export default function NetworkSelector() {
const { chainId, library } = useActiveWeb3React()
const node = useRef<HTMLDivElement>()
const open = useModalOpen(ApplicationModal.NETWORK_SELECTOR)
const toggle = useToggleModal(ApplicationModal.NETWORK_SELECTOR)
useOnClickOutside(node, open ? toggle : undefined)
const implements3085 = useAppSelector((state) => state.application.implements3085)
const info = chainId ? CHAIN_INFO[chainId] : undefined
const isOnL2 = chainId ? L2_CHAIN_IDS.includes(chainId) : false
const showSelector = Boolean(implements3085 || isOnL2)
const mainnetInfo = CHAIN_INFO[SupportedChainId.MAINNET]
const dispatch = useAppDispatch()
const conditionalToggle = useCallback(() => {
if (showSelector) {
toggle()
}
}, [showSelector, toggle])
const handleRowClick = useCallback(
(targetChain: number) => {
if (!library) return
switchToNetwork({ library, chainId: targetChain })
.then(() => toggle())
.catch((error) => {
console.error('Failed to switch networks', error)
toggle()
dispatch(addPopup({ content: { failedSwitchNetwork: targetChain }, key: `failed-network-switch` }))
})
},
[dispatch, library, toggle]
)
if (!chainId || !info || !library) {
return null
}
function Row({ targetChain }: { targetChain: number }) {
if (!library || !chainId || (!implements3085 && targetChain !== chainId)) {
return null
}
const handleRowClick = () => {
switchToNetwork({ library, chainId: targetChain })
toggle()
}
const active = chainId === targetChain
const hasExtendedInfo = L2_CHAIN_IDS.includes(targetChain)
const isOptimism = targetChain === SupportedChainId.OPTIMISM
const rowText = `${CHAIN_INFO[targetChain].label}${isOptimism ? ' (Optimism)' : ''}`
const RowContent = () => (
<FlyoutRow onClick={handleRowClick} active={active}>
<Logo src={CHAIN_INFO[targetChain].logoUrl} />
<NetworkLabel>{rowText}</NetworkLabel>
{chainId === targetChain && <FlyoutRowActiveIndicator />}
</FlyoutRow>
)
const helpCenterLink = isOptimism ? OPTIMISM_HELP_CENTER_LINK : ARBITRUM_HELP_CENTER_LINK
if (active && hasExtendedInfo) {
return (
<ActiveRowWrapper>
<RowContent />
<ActiveRowLinkList>
<ExternalLink href={CHAIN_INFO[targetChain as SupportedL2ChainId].bridge}>
<BridgeText chainId={chainId} /> <LinkOutCircle />
</ExternalLink>
<ExternalLink href={CHAIN_INFO[targetChain].explorer}>
<ExplorerText chainId={chainId} /> <LinkOutCircle />
</ExternalLink>
<ExternalLink href={helpCenterLink}>
<Trans>Help Center</Trans> <LinkOutCircle />
</ExternalLink>
</ActiveRowLinkList>
</ActiveRowWrapper>
)
}
return <RowContent />
}
return (
<SelectorWrapper ref={node as any}>
<SelectorControls onClick={conditionalToggle} interactive={showSelector}>
<SelectorLogo interactive={showSelector} src={info.logoUrl || mainnetInfo.logoUrl} />
<SelectorControls onClick={toggle} interactive>
<SelectorLogo interactive src={info.logoUrl} />
<SelectorLabel>{info.label}</SelectorLabel>
{showSelector && <StyledChevronDown />}
<StyledChevronDown />
</SelectorControls>
{open && (
<FlyoutMenu>
<FlyoutMenu onMouseLeave={toggle}>
<FlyoutHeader>
<Trans>Select a network</Trans>
</FlyoutHeader>
<Row targetChain={SupportedChainId.MAINNET} />
<Row targetChain={SupportedChainId.OPTIMISM} />
<Row targetChain={SupportedChainId.ARBITRUM_ONE} />
<Row onSelectChain={handleRowClick} targetChain={SupportedChainId.MAINNET} />
<Row onSelectChain={handleRowClick} targetChain={SupportedChainId.POLYGON} />
<Row onSelectChain={handleRowClick} targetChain={SupportedChainId.OPTIMISM} />
<Row onSelectChain={handleRowClick} targetChain={SupportedChainId.ARBITRUM_ONE} />
</FlyoutMenu>
)}
</SelectorWrapper>

View File

@@ -1,11 +1,20 @@
import { Trans } from '@lingui/macro'
import { RowFixed } from 'components/Row'
import { CHAIN_INFO } from 'constants/chains'
import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
import useGasPrice from 'hooks/useGasPrice'
import useMachineTimeMs from 'hooks/useMachineTime'
import useTheme from 'hooks/useTheme'
import { useActiveWeb3React } from 'hooks/web3'
import JSBI from 'jsbi'
import ms from 'ms.macro'
import { useEffect, useState } from 'react'
import { useAppSelector } from 'state/hooks'
import { useBlockNumber } from 'state/application/hooks'
import styled, { keyframes } from 'styled-components/macro'
import { ExternalLink, ThemedText } from 'theme'
import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink'
import { useActiveWeb3React } from '../../hooks/web3'
import { useBlockNumber } from '../../state/application/hooks'
import { ExternalLink, TYPE } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { MouseoverTooltip } from '../Tooltip'
import { ChainConnectivityWarning } from './ChainConnectivityWarning'
const StyledPolling = styled.div<{ warning: boolean }>`
@@ -22,12 +31,20 @@ const StyledPolling = styled.div<{ warning: boolean }>`
display: none;
`}
`
const StyledPollingNumber = styled(TYPE.small)<{ breathe: boolean; hovering: boolean }>`
const StyledPollingNumber = styled(ThemedText.Small)<{ breathe: boolean; hovering: boolean }>`
transition: opacity 0.25s ease;
opacity: ${({ breathe, hovering }) => (hovering ? 0.7 : breathe ? 1 : 0.5)};
:hover {
opacity: 1;
}
a {
color: unset;
}
a:hover {
text-decoration: none;
color: unset;
}
`
const StyledPollingDot = styled.div<{ warning: boolean }>`
width: 8px;
@@ -40,6 +57,17 @@ const StyledPollingDot = styled.div<{ warning: boolean }>`
transition: 250ms ease background-color;
`
const StyledGasDot = styled.div`
background-color: ${({ theme }) => theme.text3};
border-radius: 50%;
height: 4px;
min-height: 4px;
min-width: 4px;
position: relative;
transition: 250ms ease background-color;
width: 4px;
`
const rotate360 = keyframes`
from {
transform: rotate(0deg);
@@ -68,12 +96,25 @@ const Spinner = styled.div<{ warning: boolean }>`
top: -3px;
`
const DEFAULT_MS_BEFORE_WARNING = ms`10m`
const NETWORK_HEALTH_CHECK_MS = ms`10s`
export default function Polling() {
const { chainId } = useActiveWeb3React()
const blockNumber = useBlockNumber()
const [isMounting, setIsMounting] = useState(false)
const [isHover, setIsHover] = useState(false)
const chainConnectivityWarning = useAppSelector((state) => state.application.chainConnectivityWarning)
const machineTime = useMachineTimeMs(NETWORK_HEALTH_CHECK_MS)
const blockTime = useCurrentBlockTimestamp()
const theme = useTheme()
const ethGasPrice = useGasPrice()
const priceGwei = ethGasPrice ? JSBI.divide(ethGasPrice, JSBI.BigInt(1000000000)) : undefined
const waitMsBeforeWarning =
(chainId ? CHAIN_INFO[chainId]?.blockWaitMsBeforeWarning : DEFAULT_MS_BEFORE_WARNING) ?? DEFAULT_MS_BEFORE_WARNING
const warning = Boolean(!!blockTime && machineTime - blockTime.mul(1000).toNumber() > waitMsBeforeWarning)
useEffect(
() => {
@@ -93,25 +134,48 @@ export default function Polling() {
//if you pass a value to array, like this [data] than clearTimeout will run every time this value changes (useEffect re-run)
)
//TODO - chainlink gas oracle is really slow. Can we get a better data source?
return (
<>
<ExternalLink
href={chainId && blockNumber ? getExplorerLink(chainId, blockNumber.toString(), ExplorerDataType.BLOCK) : ''}
>
<StyledPolling
onMouseEnter={() => setIsHover(true)}
onMouseLeave={() => setIsHover(false)}
warning={chainConnectivityWarning}
>
<RowFixed>
<StyledPolling onMouseEnter={() => setIsHover(true)} onMouseLeave={() => setIsHover(false)} warning={warning}>
<ExternalLink href={'https://etherscan.io/gastracker'}>
{priceGwei ? (
<RowFixed style={{ marginRight: '8px' }}>
<ThemedText.Main fontSize="11px" mr="8px" color={theme.text3}>
<MouseoverTooltip
text={
<Trans>
The current fast gas amount for sending a transaction on L1. Gas fees are paid in
Ethereum&apos;s native currency Ether (ETH) and denominated in GWEI.
</Trans>
}
>
{priceGwei.toString()} <Trans>gwei</Trans>
</MouseoverTooltip>
</ThemedText.Main>
<StyledGasDot />
</RowFixed>
) : null}
</ExternalLink>
<StyledPollingNumber breathe={isMounting} hovering={isHover}>
{blockNumber}&ensp;
<ExternalLink
href={
chainId && blockNumber ? getExplorerLink(chainId, blockNumber.toString(), ExplorerDataType.BLOCK) : ''
}
>
<MouseoverTooltip
text={<Trans>The most recent block number on this network. Prices update on every block.</Trans>}
>
{blockNumber}&ensp;
</MouseoverTooltip>
</ExternalLink>
</StyledPollingNumber>
<StyledPollingDot warning={chainConnectivityWarning}>
{isMounting && <Spinner warning={chainConnectivityWarning} />}
</StyledPollingDot>{' '}
<StyledPollingDot warning={warning}>{isMounting && <Spinner warning={warning} />}</StyledPollingDot>{' '}
</StyledPolling>
</ExternalLink>
{chainConnectivityWarning && <ChainConnectivityWarning />}
{warning && <ChainConnectivityWarning />}
</RowFixed>
</>
)
}

View File

@@ -1,144 +0,0 @@
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { CHAIN_INFO, SupportedChainId } from 'constants/chains'
import { useMemo } from 'react'
import { X } from 'react-feather'
import styled from 'styled-components/macro'
import tokenLogo from '../../assets/images/token-logo.png'
import { UNI } from '../../constants/tokens'
import { useMerkleDistributorContract } from '../../hooks/useContract'
import useCurrentBlockTimestamp from '../../hooks/useCurrentBlockTimestamp'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import useUSDCPrice from '../../hooks/useUSDCPrice'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTotalUniEarned } from '../../state/stake/hooks'
import { useAggregateUniBalance, useTokenBalance } from '../../state/wallet/hooks'
import { ExternalLink, StyledInternalLink, TYPE, UniTokenAnimated } from '../../theme'
import { computeUniCirculation } from '../../utils/computeUniCirculation'
import { AutoColumn } from '../Column'
import { Break, CardBGImage, CardNoise, CardSection, DataCard } from '../earn/styled'
import { RowBetween } from '../Row'
const ContentWrapper = styled(AutoColumn)`
width: 100%;
`
const ModalUpper = styled(DataCard)`
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
background: radial-gradient(76.02% 75.41% at 1.84% 0%, #ff007a 0%, #021d43 100%);
padding: 0.5rem;
`
const StyledClose = styled(X)`
position: absolute;
right: 16px;
top: 16px;
:hover {
cursor: pointer;
}
`
/**
* Content for balance stats modal
*/
export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowUniBalanceModal: any }) {
const { account, chainId } = useActiveWeb3React()
const uni = chainId ? UNI[chainId] : undefined
const total = useAggregateUniBalance()
const uniBalance: CurrencyAmount<Token> | undefined = useTokenBalance(account ?? undefined, uni)
const uniToClaim: CurrencyAmount<Token> | undefined = useTotalUniEarned()
const totalSupply: CurrencyAmount<Token> | undefined = useTotalSupply(uni)
const uniPrice = useUSDCPrice(uni)
const blockTimestamp = useCurrentBlockTimestamp()
const unclaimedUni = useTokenBalance(useMerkleDistributorContract()?.address, uni)
const circulation: CurrencyAmount<Token> | undefined = useMemo(
() =>
blockTimestamp && uni && chainId === 1 ? computeUniCirculation(uni, blockTimestamp, unclaimedUni) : totalSupply,
[blockTimestamp, chainId, totalSupply, unclaimedUni, uni]
)
const { infoLink } = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET]
return (
<ContentWrapper gap="lg">
<ModalUpper>
<CardBGImage />
<CardNoise />
<CardSection gap="md">
<RowBetween>
<TYPE.white color="white">
<Trans>Your UNI Breakdown</Trans>
</TYPE.white>
<StyledClose stroke="white" onClick={() => setShowUniBalanceModal(false)} />
</RowBetween>
</CardSection>
<Break />
{account && (
<>
<CardSection gap="sm">
<AutoColumn gap="md" justify="center">
<UniTokenAnimated width="48px" src={tokenLogo} />{' '}
<TYPE.white fontSize={48} fontWeight={600} color="white">
{total?.toFixed(2, { groupSeparator: ',' })}
</TYPE.white>
</AutoColumn>
<AutoColumn gap="md">
<RowBetween>
<TYPE.white color="white">
<Trans>Balance:</Trans>
</TYPE.white>
<TYPE.white color="white">{uniBalance?.toFixed(2, { groupSeparator: ',' })}</TYPE.white>
</RowBetween>
<RowBetween>
<TYPE.white color="white">
<Trans>Unclaimed:</Trans>
</TYPE.white>
<TYPE.white color="white">
{uniToClaim?.toFixed(4, { groupSeparator: ',' })}{' '}
{uniToClaim && uniToClaim.greaterThan('0') && (
<StyledInternalLink onClick={() => setShowUniBalanceModal(false)} to="/uni">
<Trans>(claim)</Trans>
</StyledInternalLink>
)}
</TYPE.white>
</RowBetween>
</AutoColumn>
</CardSection>
<Break />
</>
)}
<CardSection gap="sm">
<AutoColumn gap="md">
<RowBetween>
<TYPE.white color="white">
<Trans>UNI price:</Trans>
</TYPE.white>
<TYPE.white color="white">${uniPrice?.toFixed(2) ?? '-'}</TYPE.white>
</RowBetween>
<RowBetween>
<TYPE.white color="white">
<Trans>UNI in circulation:</Trans>
</TYPE.white>
<TYPE.white color="white">{circulation?.toFixed(0, { groupSeparator: ',' })}</TYPE.white>
</RowBetween>
<RowBetween>
<TYPE.white color="white">
<Trans>Total Supply</Trans>
</TYPE.white>
<TYPE.white color="white">{totalSupply?.toFixed(0, { groupSeparator: ',' })}</TYPE.white>
</RowBetween>
{uni && uni.chainId === 1 ? (
<ExternalLink href={`${infoLink}/token/${uni.address}`}>
<Trans>View UNI Analytics</Trans>
</ExternalLink>
) : null}
</AutoColumn>
</CardSection>
</ModalUpper>
</ContentWrapper>
)
}

View File

@@ -3,28 +3,26 @@ import useScrollPosition from '@react-hook/window-scroll'
import { CHAIN_INFO, SupportedChainId } from 'constants/chains'
import useTheme from 'hooks/useTheme'
import { darken } from 'polished'
import { useState } from 'react'
import { NavLink } from 'react-router-dom'
import { Text } from 'rebass'
import { useShowClaimPopup, useToggleSelfClaimModal } from 'state/application/hooks'
import { useUserHasAvailableClaim } from 'state/claim/hooks'
import { useUserHasSubmittedClaim } from 'state/transactions/hooks'
import { useDarkModeManager } from 'state/user/hooks'
import { useETHBalances } from 'state/wallet/hooks'
import { useNativeCurrencyBalances } from 'state/wallet/hooks'
import styled from 'styled-components/macro'
import { ReactComponent as Logo } from '../../assets/svg/logo.svg'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink, TYPE } from '../../theme'
import { ExternalLink, ThemedText } from '../../theme'
import ClaimModal from '../claim/ClaimModal'
import { CardNoise } from '../earn/styled'
import Menu from '../Menu'
import Modal from '../Modal'
import Row from '../Row'
import { Dots } from '../swap/styleds'
import Web3Status from '../Web3Status'
import HolidayOrnament from './HolidayOrnament'
import NetworkSelector from './NetworkSelector'
import UniBalanceContent from './UniBalanceContent'
const HeaderFrame = styled.div<{ showBackground: boolean }>`
display: grid;
@@ -91,7 +89,7 @@ const HeaderLinks = styled(Row)`
justify-self: center;
background-color: ${({ theme }) => theme.bg0};
width: fit-content;
padding: 4px;
padding: 2px;
border-radius: 16px;
display: grid;
grid-auto-flow: column;
@@ -123,10 +121,11 @@ const AccountElement = styled.div<{ active: boolean }>`
display: flex;
flex-direction: row;
align-items: center;
background-color: ${({ theme, active }) => (!active ? theme.bg1 : theme.bg1)};
border-radius: 12px;
background-color: ${({ theme, active }) => (!active ? theme.bg0 : theme.bg0)};
border-radius: 16px;
white-space: nowrap;
width: 100%;
height: 40px;
:focus {
border: 1px solid blue;
@@ -181,6 +180,8 @@ const UniIcon = styled.div`
:hover {
transform: rotate(-5deg);
}
position: relative;
`
const activeClassName = 'ACTIVE'
@@ -202,11 +203,11 @@ const StyledNavLink = styled(NavLink).attrs({
overflow: hidden;
white-space: nowrap;
&.${activeClassName} {
border-radius: 12px;
border-radius: 14px;
font-weight: 600;
justify-content: center;
color: ${({ theme }) => theme.text1};
background-color: ${({ theme }) => theme.bg2};
background-color: ${({ theme }) => theme.bg1};
}
:hover,
@@ -231,7 +232,7 @@ const StyledExternalLink = styled(ExternalLink).attrs({
font-weight: 500;
&.${activeClassName} {
border-radius: 12px;
border-radius: 14px;
font-weight: 600;
color: ${({ theme }) => theme.text1};
}
@@ -246,7 +247,7 @@ const StyledExternalLink = styled(ExternalLink).attrs({
export default function Header() {
const { account, chainId } = useActiveWeb3React()
const userEthBalance = useETHBalances(account ? [account] : [])?.[account ?? '']
const userEthBalance = useNativeCurrencyBalances(account ? [account] : [])?.[account ?? '']
const [darkMode] = useDarkModeManager()
const { white, black } = useTheme()
@@ -256,21 +257,24 @@ export default function Header() {
const { claimTxn } = useUserHasSubmittedClaim(account ?? undefined)
const [showUniBalanceModal, setShowUniBalanceModal] = useState(false)
const showClaimPopup = useShowClaimPopup()
const scrollY = useScrollPosition()
const { infoLink } = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET]
const {
infoLink,
addNetworkInfo: {
nativeCurrency: { symbol: nativeCurrencySymbol },
},
} = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET]
return (
<HeaderFrame showBackground={scrollY > 45}>
<ClaimModal />
<Modal isOpen={showUniBalanceModal} onDismiss={() => setShowUniBalanceModal(false)}>
<UniBalanceContent setShowUniBalanceModal={setShowUniBalanceModal} />
</Modal>
<Title href=".">
<UniIcon>
<Logo fill={darkMode ? white : black} width="24px" height="100%" title="logo" />
<HolidayOrnament />
</UniIcon>
</Title>
<HeaderLinks>
@@ -309,7 +313,7 @@ export default function Header() {
{availableClaim && !showClaimPopup && (
<UNIWrapper onClick={toggleClaimModal}>
<UNIAmount active={!!account && !availableClaim} style={{ pointerEvents: 'auto' }}>
<TYPE.white padding="0 2px">
<ThemedText.White padding="0 2px">
{claimTxn && !claimTxn?.receipt ? (
<Dots>
<Trans>Claiming UNI</Trans>
@@ -317,7 +321,7 @@ export default function Header() {
) : (
<Trans>Claim UNI</Trans>
)}
</TYPE.white>
</ThemedText.White>
</UNIAmount>
<CardNoise />
</UNIWrapper>
@@ -325,7 +329,9 @@ export default function Header() {
<AccountElement active={!!account}>
{account && userEthBalance ? (
<BalanceText style={{ flexShrink: 0, userSelect: 'none' }} pl="0.75rem" pr="0.5rem" fontWeight={500}>
<Trans>{userEthBalance?.toSignificant(3)} ETH</Trans>
<Trans>
{userEthBalance?.toSignificant(3)} {nativeCurrencySymbol}
</Trans>
</BalanceText>
) : null}
<Web3Status />

View File

@@ -2,9 +2,15 @@ import Tooltip from 'components/Tooltip'
import { useState } from 'react'
import styled from 'styled-components/macro'
const TextWrapper = styled.span<{ margin: boolean; link?: boolean; fontSize?: string; adjustSize?: boolean }>`
const TextWrapper = styled.span<{
margin: boolean
link?: boolean
fontSize?: string
adjustSize?: boolean
textColor?: string
}>`
margin-left: ${({ margin }) => margin && '4px'};
color: ${({ theme, link }) => (link ? theme.blue1 : theme.text1)};
color: ${({ theme, link, textColor }) => (link ? theme.blue1 : textColor ?? theme.text1)};
font-size: ${({ fontSize }) => fontSize ?? 'inherit'};
@media screen and (max-width: 600px) {
@@ -18,6 +24,7 @@ const HoverInlineText = ({
margin = false,
adjustSize = false,
fontSize,
textColor,
link,
...rest
}: {
@@ -26,6 +33,7 @@ const HoverInlineText = ({
margin?: boolean
adjustSize?: boolean
fontSize?: string
textColor?: string
link?: boolean
}) => {
const [showHover, setShowHover] = useState(false)
@@ -42,6 +50,7 @@ const HoverInlineText = ({
onMouseLeave={() => setShowHover(false)}
margin={margin}
adjustSize={adjustSize}
textColor={textColor}
link={link}
fontSize={fontSize}
{...rest}
@@ -53,7 +62,14 @@ const HoverInlineText = ({
}
return (
<TextWrapper margin={margin} adjustSize={adjustSize} link={link} fontSize={fontSize} {...rest}>
<TextWrapper
margin={margin}
adjustSize={adjustSize}
link={link}
fontSize={fontSize}
textColor={textColor}
{...rest}
>
{text}
</TextWrapper>
)

View File

@@ -0,0 +1,26 @@
import { AbstractConnector } from '@web3-react/abstract-connector'
import { Connector } from 'widgets-web3-react/types'
import CoinbaseWalletIcon from '../../assets/images/coinbaseWalletIcon.svg'
import FortmaticIcon from '../../assets/images/fortmaticIcon.png'
import PortisIcon from '../../assets/images/portisIcon.png'
import WalletConnectIcon from '../../assets/images/walletConnectIcon.svg'
import { fortmatic, injected, portis, walletconnect, walletlink } from '../../connectors'
import Identicon from '../Identicon'
export default function StatusIcon({ connector }: { connector: AbstractConnector | Connector }) {
switch (connector) {
case injected:
return <Identicon />
case walletconnect:
return <img src={WalletConnectIcon} alt={'WalletConnect'} />
case walletlink:
return <img src={CoinbaseWalletIcon} alt={'Coinbase Wallet'} />
case fortmatic:
return <img src={FortmaticIcon} alt={'Fortmatic'} />
case portis:
return <img src={PortisIcon} alt={'Portis'} />
default:
return null
}
}

View File

@@ -1,22 +1,53 @@
import Davatar from '@davatar/react'
import jazzicon from '@metamask/jazzicon'
import useENSAvatar from 'hooks/useENSAvatar'
import { useLayoutEffect, useMemo, useRef, useState } from 'react'
import styled from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks/web3'
const StyledIdenticonContainer = styled.div`
const StyledIdenticon = styled.div`
height: 1rem;
width: 1rem;
border-radius: 1.125rem;
background-color: ${({ theme }) => theme.bg4};
font-size: initial;
`
const StyledAvatar = styled.img`
height: inherit;
width: inherit;
border-radius: inherit;
`
export default function Identicon() {
const { account, library } = useActiveWeb3React()
const { account } = useActiveWeb3React()
const { avatar } = useENSAvatar(account ?? undefined)
const [fetchable, setFetchable] = useState(true)
const icon = useMemo(() => account && jazzicon(16, parseInt(account.slice(2, 10), 16)), [account])
const iconRef = useRef<HTMLDivElement>(null)
useLayoutEffect(() => {
const current = iconRef.current
if (icon) {
current?.appendChild(icon)
return () => {
try {
current?.removeChild(icon)
} catch (e) {
console.error('Avatar icon not found')
}
}
}
return
}, [icon, iconRef])
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30451
return (
<StyledIdenticonContainer>
{account && library?.provider && <Davatar address={account} size={16} provider={library.provider} />}
</StyledIdenticonContainer>
<StyledIdenticon>
{avatar && fetchable ? (
<StyledAvatar alt="avatar" src={avatar} onError={() => setFetchable(false)}></StyledAvatar>
) : (
<span ref={iconRef} />
)}
</StyledIdenticon>
)
}

View File

@@ -6,7 +6,7 @@ import { AutoColumn } from 'components/Column'
import { ReactNode, useCallback, useEffect, useState } from 'react'
import { Minus, Plus } from 'react-feather'
import styled, { keyframes } from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { Input as NumericalInput } from '../NumericalInput'
@@ -57,13 +57,13 @@ const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>`
`};
`
const InputTitle = styled(TYPE.small)`
const InputTitle = styled(ThemedText.Small)`
color: ${({ theme }) => theme.text2};
font-size: 12px;
font-weight: 500;
`
const ButtonLabel = styled(TYPE.white)<{ disabled: boolean }>`
const ButtonLabel = styled(ThemedText.White)<{ disabled: boolean }>`
color: ${({ theme, disabled }) => (disabled ? theme.text2 : theme.text1)} !important;
`

View File

@@ -37,7 +37,7 @@ export const Area = ({
.y0(yScale(0))(
series.filter((d) => {
const value = xScale(xValue(d))
return value > 0 && value <= innerWidth
return value > 0 && value <= window.innerWidth
}) as Iterable<[number, number]>
) ?? undefined
}

View File

@@ -14,12 +14,18 @@ import { batch } from 'react-redux'
import { Bound } from 'state/mint/v3/actions'
import styled from 'styled-components/macro'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { Chart } from './Chart'
import { useDensityChartData } from './hooks'
import { ZoomLevels } from './types'
const ZOOM_LEVELS: Record<FeeAmount, ZoomLevels> = {
[FeeAmount.LOWEST]: {
initialMin: 0.999,
initialMax: 1.001,
min: 0.00001,
max: 1.5,
},
[FeeAmount.LOW]: {
initialMin: 0.999,
initialMax: 1.001,
@@ -52,9 +58,9 @@ function InfoBox({ message, icon }: { message?: ReactNode; icon: ReactNode }) {
<ColumnCenter style={{ height: '100%', justifyContent: 'center' }}>
{icon}
{message && (
<TYPE.mediumHeader padding={10} marginTop="20px" textAlign="center">
<ThemedText.MediumHeader padding={10} marginTop="20px" textAlign="center">
{message}
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
)}
</ColumnCenter>
)

View File

@@ -1,11 +1,24 @@
import { t } from '@lingui/macro'
import { Trans } from '@lingui/macro'
import { CHAIN_INFO, L2_CHAIN_IDS, SupportedChainId } from 'constants/chains'
// eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro'
import { PrivacyPolicyModal } from 'components/PrivacyPolicy'
import { L2_CHAIN_IDS } from 'constants/chains'
import { LOCALE_LABEL, SUPPORTED_LOCALES, SupportedLocale } from 'constants/locales'
import { useActiveLocale } from 'hooks/useActiveLocale'
import { useLocationLinkProps } from 'hooks/useLocationLinkProps'
import React, { useEffect, useRef, useState } from 'react'
import { BookOpen, Check, ChevronLeft, Code, Globe, Info, MessageCircle, Moon, PieChart, Sun } from 'react-feather'
import {
BookOpen,
Check,
ChevronLeft,
Coffee,
FileText,
Globe,
HelpCircle,
Info,
MessageCircle,
Moon,
Sun,
} from 'react-feather'
import { Link } from 'react-router-dom'
import { useDarkModeManager } from 'state/user/hooks'
import styled, { css } from 'styled-components/macro'
@@ -13,8 +26,8 @@ import styled, { css } from 'styled-components/macro'
import { ReactComponent as MenuIcon } from '../../assets/images/menu.svg'
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
import { useActiveWeb3React } from '../../hooks/web3'
import { ApplicationModal } from '../../state/application/actions'
import { useModalOpen, useToggleModal } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { ExternalLink } from '../../theme'
import { ButtonPrimary } from '../Button'
@@ -36,12 +49,11 @@ const StyledMenuButton = styled.button`
background-color: transparent;
margin: 0;
padding: 0;
height: 38px;
height: 40px;
background-color: ${({ theme }) => theme.bg0};
border: 1px solid ${({ theme }) => theme.bg0};
padding: 0.15rem 0.5rem;
border-radius: 12px;
border-radius: 16px;
:hover,
:focus {
@@ -166,8 +178,6 @@ const ToggleMenuItem = styled.button`
}
`
const CODE_LINK = 'https://github.com/Uniswap/uniswap-interface'
function LanguageMenuItem({ locale, active, key }: { locale: SupportedLocale; active: boolean; key: string }) {
const { to, onClick } = useLocationLinkProps(locale)
@@ -201,11 +211,11 @@ export default function Menu() {
const node = useRef<HTMLDivElement>()
const open = useModalOpen(ApplicationModal.MENU)
const toggle = useToggleModal(ApplicationModal.MENU)
useOnClickOutside(node, open ? toggle : undefined)
const toggleMenu = useToggleModal(ApplicationModal.MENU)
useOnClickOutside(node, open ? toggleMenu : undefined)
const togglePrivacyPolicy = useToggleModal(ApplicationModal.PRIVACY_POLICY)
const openClaimModal = useToggleModal(ApplicationModal.ADDRESS_CLAIM)
const showUNIClaimOption = Boolean(!!account && !!chainId && !L2_CHAIN_IDS.includes(chainId))
const { infoLink } = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET]
const [darkMode, toggleDarkMode] = useDarkModeManager()
@@ -216,77 +226,86 @@ export default function Menu() {
}, [open])
return (
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30451
<StyledMenu ref={node as any}>
<StyledMenuButton onClick={toggle} aria-label={t`Menu`}>
<StyledMenuIcon />
</StyledMenuButton>
<>
{/* // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30451 */}
<StyledMenu ref={node as any}>
<StyledMenuButton onClick={toggleMenu} aria-label={t`Menu`}>
<StyledMenuIcon />
</StyledMenuButton>
{open &&
(() => {
switch (menu) {
case 'lang':
return <LanguageMenu close={() => setMenu('main')} />
case 'main':
default:
return (
<MenuFlyout>
<MenuItem href="https://uniswap.org/">
<div>
<Trans>About</Trans>
</div>
<Info opacity={0.6} size={16} />
</MenuItem>
<MenuItem href="https://docs.uniswap.org/">
<div>
<Trans>Docs</Trans>
</div>
<BookOpen opacity={0.6} size={16} />
</MenuItem>
<MenuItem href={CODE_LINK}>
<div>
<Trans>Code</Trans>
</div>
<Code opacity={0.6} size={16} />
</MenuItem>
<MenuItem href="https://discord.gg/FCfyBSbCU5">
<div>
<Trans>Discord</Trans>
</div>
<MessageCircle opacity={0.6} size={16} />
</MenuItem>
<MenuItem href={infoLink}>
<div>
<Trans>Analytics</Trans>
</div>
<PieChart opacity={0.6} size={16} />
</MenuItem>
<ToggleMenuItem onClick={() => setMenu('lang')}>
<div>
<Trans>Language</Trans>
</div>
<Globe opacity={0.6} size={16} />
</ToggleMenuItem>
<ToggleMenuItem onClick={() => toggleDarkMode()}>
<div>{darkMode ? <Trans>Light Theme</Trans> : <Trans>Dark Theme</Trans>}</div>
{darkMode ? <Moon opacity={0.6} size={16} /> : <Sun opacity={0.6} size={16} />}
</ToggleMenuItem>
{showUNIClaimOption && (
<UNIbutton
onClick={openClaimModal}
padding="8px 16px"
width="100%"
$borderRadius="12px"
mt="0.5rem"
>
<Trans>Claim UNI</Trans>
</UNIbutton>
)}
</MenuFlyout>
)
}
})()}
</StyledMenu>
{open &&
(() => {
switch (menu) {
case 'lang':
return <LanguageMenu close={() => setMenu('main')} />
case 'main':
default:
return (
<MenuFlyout>
<MenuItem href="https://uniswap.org/">
<div>
<Trans>About</Trans>
</div>
<Info opacity={0.6} size={16} />
</MenuItem>
<MenuItem href="https://help.uniswap.org/">
<div>
<Trans>Help Center</Trans>
</div>
<HelpCircle opacity={0.6} size={16} />
</MenuItem>
<MenuItem href="https://uniswap.canny.io/feature-requests">
<div>
<Trans>Request Features</Trans>
</div>
<Coffee opacity={0.6} size={16} />
</MenuItem>
<MenuItem href="https://discord.gg/FCfyBSbCU5">
<div>
<Trans>Discord</Trans>
</div>
<MessageCircle opacity={0.6} size={16} />
</MenuItem>
<ToggleMenuItem onClick={() => setMenu('lang')}>
<div>
<Trans>Language</Trans>
</div>
<Globe opacity={0.6} size={16} />
</ToggleMenuItem>
<ToggleMenuItem onClick={() => toggleDarkMode()}>
<div>{darkMode ? <Trans>Light Theme</Trans> : <Trans>Dark Theme</Trans>}</div>
{darkMode ? <Moon opacity={0.6} size={16} /> : <Sun opacity={0.6} size={16} />}
</ToggleMenuItem>
<MenuItem href="https://docs.uniswap.org/">
<div>
<Trans>Docs</Trans>
</div>
<BookOpen opacity={0.6} size={16} />
</MenuItem>
<ToggleMenuItem onClick={() => togglePrivacyPolicy()}>
<div>
<Trans>Legal & Privacy</Trans>
</div>
<FileText opacity={0.6} size={16} />
</ToggleMenuItem>
{showUNIClaimOption && (
<UNIbutton
onClick={openClaimModal}
padding="8px 16px"
width="100%"
$borderRadius="12px"
mt="0.5rem"
>
<Trans>Claim UNI</Trans>
</UNIbutton>
)}
</MenuFlyout>
)
}
})()}
</StyledMenu>
<PrivacyPolicyModal />
</>
)
}

View File

@@ -5,7 +5,7 @@ import styled, { ThemeContext } from 'styled-components/macro'
import Circle from '../../assets/images/blue-loader.svg'
import { useActiveWeb3React } from '../../hooks/web3'
import { CloseIcon, CustomLightSpinner, TYPE } from '../../theme'
import { CloseIcon, CustomLightSpinner, ThemedText } from '../../theme'
import { ExternalLink } from '../../theme/components'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { AutoColumn, ColumnCenter } from '../Column'
@@ -32,9 +32,9 @@ export function LoadingView({ children, onDismiss }: { children: any; onDismiss:
</ConfirmedIcon>
<AutoColumn gap="100px" justify={'center'}>
{children}
<TYPE.subHeader>
<ThemedText.SubHeader>
<Trans>Confirm this transaction in your wallet</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</AutoColumn>
</ConfirmOrLoadingWrapper>
)
@@ -68,9 +68,9 @@ export function SubmittedView({
href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}
style={{ marginLeft: '4px' }}
>
<TYPE.subHeader>
<ThemedText.SubHeader>
<Trans>View transaction on Explorer</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</ExternalLink>
)}
</AutoColumn>

View File

@@ -10,7 +10,7 @@ import { useAppDispatch } from 'state/hooks'
import { resetMintState } from 'state/mint/actions'
import { resetMintState as resetMintV3State } from 'state/mint/v3/actions'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import Row, { RowBetween } from '../Row'
import SettingsTab from '../Settings'
@@ -136,7 +136,7 @@ export function AddRemoveTabs({
>
<StyledArrowLeft stroke={theme.text2} />
</StyledHistoryLink>
<TYPE.mediumHeader
<ThemedText.MediumHeader
fontWeight={500}
fontSize={20}
style={{ flex: '1', margin: 'auto', textAlign: children ? 'start' : 'center' }}
@@ -148,7 +148,7 @@ export function AddRemoveTabs({
) : (
<Trans>Remove Liquidity</Trans>
)}
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<Box style={{ marginRight: '.5rem' }}>{children}</Box>
<SettingsTab placeholderSlippage={defaultSlippage} />
</RowBetween>

View File

@@ -1,157 +1,93 @@
import { Trans } from '@lingui/macro'
import {
ARBITRUM_HELP_CENTER_LINK,
L2_CHAIN_IDS,
OPTIMISM_HELP_CENTER_LINK,
SupportedChainId,
SupportedL2ChainId,
} from 'constants/chains'
import { SupportedChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import { useCallback, useState } from 'react'
import { ArrowDownCircle, X } from 'react-feather'
import { useArbitrumAlphaAlert, useDarkModeManager, useOptimismAlphaAlert } from 'state/user/hooks'
import { useETHBalances } from 'state/wallet/hooks'
import styled, { css } from 'styled-components/macro'
import { ExternalLink, MEDIA_WIDTHS } from 'theme'
import { ArrowUpRight } from 'react-feather'
import { useDarkModeManager } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { ExternalLink, HideSmall } from 'theme'
import { CHAIN_INFO } from '../../constants/chains'
export const DesktopTextBreak = styled.div`
display: none;
@media screen and (min-width: ${MEDIA_WIDTHS.upToMedium}px) {
display: block;
}
`
import { AutoRow } from '../Row'
const L2Icon = styled.img`
width: 36px;
height: 36px;
justify-self: center;
width: 24px;
height: 24px;
margin-right: 16px;
`
const BetaTag = styled.span<{ color: string }>`
align-items: center;
background-color: ${({ color }) => color};
border-radius: 6px;
color: ${({ theme }) => theme.white};
display: flex;
font-size: 14px;
height: 28px;
justify-content: center;
left: -16px;
position: absolute;
transform: rotate(-15deg);
top: -16px;
width: 60px;
z-index: 1;
`
const Body = styled.p`
font-size: 12px;
grid-column: 1 / 3;
line-height: 143%;
margin: 0;
@media screen and (min-width: ${MEDIA_WIDTHS.upToSmall}px) {
grid-column: 2 / 3;
}
`
export const Controls = styled.div<{ thin?: boolean }>`
export const Controls = styled.div`
align-items: center;
display: flex;
justify-content: flex-start;
${({ thin }) =>
thin &&
css`
margin: auto 32px auto 0;
`}
`
const CloseIcon = styled(X)`
cursor: pointer;
position: absolute;
top: 16px;
right: 16px;
padding: 0 20px 20px 20px;
`
const BodyText = styled.div`
align-items: center;
display: grid;
grid-gap: 4px;
grid-template-columns: 40px 4fr;
grid-template-rows: auto auto;
margin: 20px 16px;
@media screen and (min-width: ${MEDIA_WIDTHS.upToSmall}px) {
grid-template-columns: 42px 4fr;
grid-gap: 8px;
}
`
const LearnMoreLink = styled(ExternalLink)<{ thin?: boolean }>`
align-items: center;
background-color: transparent;
border: 1px solid rgba(255, 255, 255, 0.4);
border-radius: 8px;
color: ${({ theme }) => theme.text1};
color: ${({ color }) => color};
display: flex;
font-size: 16px;
height: 44px;
justify-content: space-between;
margin: 0 0 20px 0;
padding: 12px 16px;
text-decoration: none;
width: auto;
:hover,
:focus,
:active {
background-color: rgba(255, 255, 255, 0.05);
}
transition: background-color 150ms ease-in-out;
${({ thin }) =>
thin &&
css`
font-size: 14px;
margin: auto;
width: 112px;
`}
align-items: center;
justify-content: flex-start;
margin: 8px;
font-size: 14px;
`
const RootWrapper = styled.div`
position: relative;
margin-top: 16px;
`
export const ArbitrumWrapperBackgroundDarkMode = css`
background: radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.1) 0%, rgba(219, 255, 0, 0) 100%),
radial-gradient(75% 75% at 0% 0%, rgba(150, 190, 220, 0.3) 0%, rgba(33, 114, 229, 0.3) 100%), hsla(0, 0%, 100%, 0.1);
`
export const ArbitrumWrapperBackgroundLightMode = css`
background: radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.1) 0%, rgba(219, 255, 0, 0) 100%),
radial-gradient(circle at top left, hsla(206, 50%, 75%, 0.01), hsla(215, 79%, 51%, 0.12)), hsla(0, 0%, 100%, 0.1);
`
export const OptimismWrapperBackgroundDarkMode = css`
background: radial-gradient(948% 292% at 42% 0%, rgba(255, 58, 212, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%),
radial-gradient(98% 96% at 2% 0%, rgba(255, 39, 39, 0.5) 0%, rgba(235, 0, 255, 0.345) 96%);
`
export const OptimismWrapperBackgroundLightMode = css`
background: radial-gradient(92% 105% at 50% 7%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.03) 100%),
radial-gradient(100% 97% at 0% 12%, rgba(235, 0, 255, 0.1) 0%, rgba(243, 19, 19, 0.1) 100%), hsla(0, 0%, 100%, 0.5);
`
const ContentWrapper = styled.div<{ chainId: SupportedChainId; darkMode: boolean; logoUrl: string; thin?: boolean }>`
${({ chainId, darkMode }) =>
[SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISTIC_KOVAN].includes(chainId)
? darkMode
? OptimismWrapperBackgroundDarkMode
: OptimismWrapperBackgroundLightMode
: darkMode
? ArbitrumWrapperBackgroundDarkMode
: ArbitrumWrapperBackgroundLightMode};
const SHOULD_SHOW_ALERT = {
[SupportedChainId.OPTIMISM]: true,
[SupportedChainId.OPTIMISTIC_KOVAN]: true,
[SupportedChainId.ARBITRUM_ONE]: true,
[SupportedChainId.ARBITRUM_RINKEBY]: true,
[SupportedChainId.POLYGON]: true,
[SupportedChainId.POLYGON_MUMBAI]: true,
}
type NetworkAlertChains = keyof typeof SHOULD_SHOW_ALERT
const BG_COLORS_BY_DARK_MODE_AND_CHAIN_ID: {
[darkMode in 'dark' | 'light']: { [chainId in NetworkAlertChains]: string }
} = {
dark: {
[SupportedChainId.POLYGON]:
'radial-gradient(100% 93.36% at 0% 6.64%, rgba(160, 108, 247, 0.1) 0%, rgba(82, 32, 166, 0.1) 100%)',
[SupportedChainId.POLYGON_MUMBAI]:
'radial-gradient(100% 93.36% at 0% 6.64%, rgba(160, 108, 247, 0.1) 0%, rgba(82, 32, 166, 0.1) 100%)',
[SupportedChainId.OPTIMISM]:
'radial-gradient(948% 292% at 42% 0%, rgba(255, 58, 212, 0.01) 0%, rgba(255, 255, 255, 0.04) 100%),radial-gradient(98% 96% at 2% 0%, rgba(255, 39, 39, 0.01) 0%, rgba(235, 0, 255, 0.01) 96%)',
[SupportedChainId.OPTIMISTIC_KOVAN]:
'radial-gradient(948% 292% at 42% 0%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.04) 100%),radial-gradient(98% 96% at 2% 0%, rgba(255, 39, 39, 0.04) 0%, rgba(235, 0, 255, 0.01 96%)',
[SupportedChainId.ARBITRUM_ONE]:
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.01) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(75% 75% at 0% 0%, rgba(150, 190, 220, 0.05) 0%, rgba(33, 114, 229, 0.05) 100%), hsla(0, 0%, 100%, 0.05)',
[SupportedChainId.ARBITRUM_RINKEBY]:
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.05) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(75% 75% at 0% 0%, rgba(150, 190, 220, 0.05) 0%, rgba(33, 114, 229, 0.1) 100%), hsla(0, 0%, 100%, 0.05)',
},
light: {
[SupportedChainId.POLYGON]:
'radial-gradient(182.71% 205.59% at 2.81% 7.69%, rgba(130, 71, 229, 0.2) 0%, rgba(167, 202, 255, 0.2) 100%)',
[SupportedChainId.POLYGON_MUMBAI]:
'radial-gradient(182.71% 205.59% at 2.81% 7.69%, rgba(130, 71, 229, 0.2) 0%, rgba(167, 202, 255, 0.2) 100%)',
[SupportedChainId.OPTIMISM]:
'radial-gradient(92% 105% at 50% 7%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.03) 100%),radial-gradient(100% 97% at 0% 12%, rgba(235, 0, 255, 0.1) 0%, rgba(243, 19, 19, 0.1) 100%), hsla(0, 0%, 100%, 0.1)',
[SupportedChainId.OPTIMISTIC_KOVAN]:
'radial-gradient(92% 105% at 50% 7%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.03) 100%),radial-gradient(100% 97% at 0% 12%, rgba(235, 0, 255, 0.1) 0%, rgba(243, 19, 19, 0.1) 100%), hsla(0, 0%, 100%, 0.1)',
[SupportedChainId.ARBITRUM_ONE]:
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.1) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(circle at top left, hsla(206, 50%, 75%, 0.01), hsla(215, 79%, 51%, 0.12)), hsla(0, 0%, 100%, 0.1)',
[SupportedChainId.ARBITRUM_RINKEBY]:
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.1) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(circle at top left, hsla(206, 50%, 75%, 0.01), hsla(215, 79%, 51%, 0.12)), hsla(0, 0%, 100%, 0.1)',
},
}
const ContentWrapper = styled.div<{ chainId: NetworkAlertChains; darkMode: boolean; logoUrl: string }>`
background: ${({ chainId, darkMode }) => BG_COLORS_BY_DARK_MODE_AND_CHAIN_ID[darkMode ? 'dark' : 'light'][chainId]};
border-radius: 20px;
display: flex;
flex-direction: column;
max-width: 480px;
min-height: 174px;
flex-direction: row;
overflow: hidden;
position: relative;
width: 100%;
${({ thin }) =>
thin &&
css`
flex-direction: row;
max-width: max-content;
min-height: min-content;
`}
:before {
background-image: url(${({ logoUrl }) => logoUrl});
background-repeat: no-repeat;
@@ -165,116 +101,73 @@ const ContentWrapper = styled.div<{ chainId: SupportedChainId; darkMode: boolean
z-index: -1;
}
`
const Header = styled.h2<{ thin?: boolean }>`
const Header = styled.h2`
font-weight: 600;
font-size: 20px;
font-size: 16px;
margin: 0;
padding-right: 30px;
display: ${({ thin }) => (thin ? 'none' : 'block')};
`
const LinkOutCircle = styled(ArrowDownCircle)`
margin-left: 12px;
transform: rotate(230deg);
width: 20px;
height: 20px;
`
const LinkOutToBridge = styled(ExternalLink)<{ thin?: boolean }>`
const LinkOutToBridge = styled(ExternalLink)`
align-items: center;
background-color: black;
border-radius: 8px;
color: white;
display: flex;
font-size: 16px;
height: 44px;
justify-content: space-between;
margin: 0 12px 20px 18px;
padding: 12px 16px;
text-decoration: none;
width: auto;
:hover,
:focus,
:active {
background-color: black;
}
${({ thin }) =>
thin &&
css`
font-size: 14px;
margin: auto 10px;
width: 168px;
`}
padding: 6px 8px;
margin-right: 12px;
text-decoration: none !important;
width: 100%;
`
interface NetworkAlertProps {
thin?: boolean
const StyledArrowUpRight = styled(ArrowUpRight)`
margin-left: 12px;
width: 24px;
height: 24px;
`
const TEXT_COLORS: { [chainId in NetworkAlertChains]: string } = {
[SupportedChainId.POLYGON]: 'rgba(130, 71, 229)',
[SupportedChainId.POLYGON_MUMBAI]: 'rgba(130, 71, 229)',
[SupportedChainId.OPTIMISM]: '#ff3856',
[SupportedChainId.OPTIMISTIC_KOVAN]: '#ff3856',
[SupportedChainId.ARBITRUM_ONE]: '#0490ed',
[SupportedChainId.ARBITRUM_RINKEBY]: '#0490ed',
}
export function NetworkAlert(props: NetworkAlertProps) {
const { account, chainId } = useActiveWeb3React()
function shouldShowAlert(chainId: number | undefined): chainId is NetworkAlertChains {
return Boolean(chainId && SHOULD_SHOW_ALERT[chainId as unknown as NetworkAlertChains])
}
export function NetworkAlert() {
const { chainId } = useActiveWeb3React()
const [darkMode] = useDarkModeManager()
const [arbitrumAlphaAcknowledged, setArbitrumAlphaAcknowledged] = useArbitrumAlphaAlert()
const [optimismAlphaAcknowledged, setOptimismAlphaAcknowledged] = useOptimismAlphaAlert()
const [locallyDismissed, setLocallyDimissed] = useState(false)
const userEthBalance = useETHBalances(account ? [account] : [])?.[account ?? '']
const dismiss = useCallback(() => {
if (userEthBalance?.greaterThan(0)) {
switch (chainId) {
case SupportedChainId.OPTIMISM:
setOptimismAlphaAcknowledged(true)
break
case SupportedChainId.ARBITRUM_ONE:
setArbitrumAlphaAcknowledged(true)
break
}
} else {
setLocallyDimissed(true)
}
}, [chainId, setArbitrumAlphaAcknowledged, setOptimismAlphaAcknowledged, userEthBalance])
const onOptimismAndOptimismAcknowledged = SupportedChainId.OPTIMISM === chainId && optimismAlphaAcknowledged
const onArbitrumAndArbitrumAcknowledged = SupportedChainId.ARBITRUM_ONE === chainId && arbitrumAlphaAcknowledged
if (
!chainId ||
!L2_CHAIN_IDS.includes(chainId) ||
onArbitrumAndArbitrumAcknowledged ||
onOptimismAndOptimismAcknowledged ||
locallyDismissed
) {
if (!shouldShowAlert(chainId)) {
return null
}
const info = CHAIN_INFO[chainId as SupportedL2ChainId]
const isOptimism = [SupportedChainId.OPTIMISM, SupportedChainId.OPTIMISTIC_KOVAN].includes(chainId)
const depositUrl = isOptimism ? `${info.bridge}?chainId=1` : info.bridge
const helpCenterLink = isOptimism ? OPTIMISM_HELP_CENTER_LINK : ARBITRUM_HELP_CENTER_LINK
const showCloseIcon = Boolean(userEthBalance?.greaterThan(0) && !props.thin)
return (
const { label, logoUrl, bridge } = CHAIN_INFO[chainId]
const textColor = TEXT_COLORS[chainId]
return bridge ? (
<RootWrapper>
<BetaTag color={isOptimism ? '#ff0420' : '#0490ed'}>Beta</BetaTag>
<ContentWrapper chainId={chainId} darkMode={darkMode} logoUrl={info.logoUrl} thin={props.thin}>
{showCloseIcon && <CloseIcon onClick={dismiss} />}
<BodyText>
<L2Icon src={info.logoUrl} />
<Header thin={props.thin}>
<Trans>Uniswap on {info.label}</Trans>
</Header>
<Body>
<Trans>
To starting trading on {info.label}, first bridge your assets from L1 to L2. Please treat this as a beta
release and learn about the risks before using {info.label}.
</Trans>
</Body>
</BodyText>
<Controls thin={props.thin}>
<LinkOutToBridge href={depositUrl} thin={props.thin}>
<Trans>Deposit Assets</Trans>
<LinkOutCircle />
</LinkOutToBridge>
<LearnMoreLink href={helpCenterLink} thin={props.thin}>
<Trans>Learn More</Trans>
</LearnMoreLink>
</Controls>
<ContentWrapper chainId={chainId} darkMode={darkMode} logoUrl={logoUrl}>
<LinkOutToBridge href={bridge}>
<BodyText color={textColor}>
<L2Icon src={logoUrl} />
<AutoRow>
<Header>
<Trans>{label} token bridge</Trans>
</Header>
<HideSmall>
<Trans>Deposit tokens to the {label} network.</Trans>
</HideSmall>
</AutoRow>
</BodyText>
<StyledArrowUpRight color={textColor} />
</LinkOutToBridge>
</ContentWrapper>
</RootWrapper>
)
) : null
}

View File

@@ -12,7 +12,7 @@ const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: s
border: none;
flex: 1 1 auto;
background-color: ${({ theme }) => theme.bg1};
font-size: ${({ fontSize }) => fontSize ?? '24px'};
font-size: ${({ fontSize }) => fontSize ?? '28px'};
text-align: ${({ align }) => align && align};
white-space: nowrap;
overflow: hidden;

View File

@@ -1,11 +1,10 @@
import { Options, Placement } from '@popperjs/core'
import Portal from '@reach/portal'
import useInterval from 'lib/hooks/useInterval'
import React, { useCallback, useMemo, useState } from 'react'
import { usePopper } from 'react-popper'
import styled from 'styled-components/macro'
import useInterval from '../../hooks/useInterval'
const PopoverContainer = styled.div<{ show: boolean }>`
z-index: 9999;
visibility: ${(props) => (props.show ? 'visible' : 'hidden')};

View File

@@ -6,17 +6,17 @@ import ReactGA from 'react-ga'
import styled, { keyframes } from 'styled-components/macro'
import tokenLogo from '../../assets/images/token-logo.png'
import { ButtonPrimary } from '../../components/Button'
import { useActiveWeb3React } from '../../hooks/web3'
import { ApplicationModal } from '../../state/application/actions'
import {
useModalOpen,
useShowClaimPopup,
useToggleSelfClaimModal,
useToggleShowClaimPopup,
} from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { useUserHasAvailableClaim, useUserUnclaimedAmount } from '../../state/claim/hooks'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { ButtonPrimary } from '../Button'
import { AutoColumn } from '../Column'
import { CardBGImage, CardNoise } from '../earn/styled'
@@ -98,10 +98,10 @@ export default function ClaimPopup() {
<StyledClose stroke="white" onClick={toggleShowClaimPopup} />
<AutoColumn style={{ padding: '2rem 0', zIndex: 10 }} justify="center">
<UniToken width="48px" src={tokenLogo} />{' '}
<TYPE.white style={{ marginTop: '1rem' }} fontSize={36} fontWeight={600}>
<ThemedText.White style={{ marginTop: '1rem' }} fontSize={36} fontWeight={600}>
{unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI
</TYPE.white>
<TYPE.white style={{ paddingTop: '1.25rem', textAlign: 'center' }} fontWeight={600} color="white">
</ThemedText.White>
<ThemedText.White style={{ paddingTop: '1.25rem', textAlign: 'center' }} fontWeight={600} color="white">
<span role="img" aria-label="party">
🎉
</span>{' '}
@@ -109,12 +109,12 @@ export default function ClaimPopup() {
<span role="img" aria-label="party">
🎉
</span>
</TYPE.white>
<TYPE.subHeader style={{ paddingTop: '0.5rem', textAlign: 'center' }} color="white">
</ThemedText.White>
<ThemedText.SubHeader style={{ paddingTop: '0.5rem', textAlign: 'center' }} color="white">
<Trans>
Thanks for being part of the Uniswap community <Heart size={12} />
</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</AutoColumn>
<AutoColumn style={{ zIndex: 10 }} justify="center">
<ButtonPrimary padding="8px" $borderRadius="8px" width={'fit-content'} onClick={handleToggleSelfClaimModal}>

View File

@@ -0,0 +1,34 @@
import { Trans } from '@lingui/macro'
import { useContext } from 'react'
import { AlertCircle } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
import { CHAIN_INFO, SupportedChainId } from '../../constants/chains'
import { ThemedText } from '../../theme'
import { AutoColumn } from '../Column'
import { AutoRow } from '../Row'
const RowNoFlex = styled(AutoRow)`
flex-wrap: nowrap;
`
export default function FailedNetworkSwitchPopup({ chainId }: { chainId: SupportedChainId }) {
const chainInfo = CHAIN_INFO[chainId]
const theme = useContext(ThemeContext)
return (
<RowNoFlex>
<div style={{ paddingRight: 16 }}>
<AlertCircle color={theme.red1} size={24} />
</div>
<AutoColumn gap="8px">
<ThemedText.Body fontWeight={500}>
<Trans>
Failed to switch networks from the Uniswap Interface. In order to use Uniswap on {chainInfo.label}, you must
change the network in your wallet.
</Trans>
</ThemedText.Body>
</AutoColumn>
</RowNoFlex>
)
}

View File

@@ -4,8 +4,9 @@ import { animated } from 'react-spring'
import { useSpring } from 'react-spring/web'
import styled, { ThemeContext } from 'styled-components/macro'
import { PopupContent } from '../../state/application/actions'
import { useRemovePopup } from '../../state/application/hooks'
import { PopupContent } from '../../state/application/reducer'
import FailedNetworkSwitchPopup from './FailedNetworkSwitchPopup'
import TransactionPopup from './TransactionPopup'
const StyledClose = styled(X)`
@@ -77,6 +78,8 @@ export default function PopupItem({
txn: { hash },
} = content
popupContent = <TransactionPopup hash={hash} />
} else if ('failedSwitchNetwork' in content) {
popupContent = <FailedNetworkSwitchPopup chainId={content.failedSwitchNetwork} />
}
const faderStyle = useSpring({

View File

@@ -4,8 +4,8 @@ import styled, { ThemeContext } from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTransaction } from '../../state/transactions/hooks'
import { TYPE } from '../../theme'
import { ExternalLink } from '../../theme/components'
import { ThemedText } from '../../theme'
import { ExternalLink } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { TransactionSummary } from '../AccountDetails/TransactionSummary'
import { AutoColumn } from '../Column'
@@ -30,9 +30,9 @@ export default function TransactionPopup({ hash }: { hash: string }) {
{success ? <CheckCircle color={theme.green1} size={24} /> : <AlertCircle color={theme.red1} size={24} />}
</div>
<AutoColumn gap="8px">
<TYPE.body fontWeight={500}>
<ThemedText.Body fontWeight={500}>
<TransactionSummary info={tx.info} />
</TYPE.body>
</ThemedText.Body>
{chainId && (
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}>
View on Explorer

View File

@@ -14,7 +14,7 @@ import { useColor } from '../../hooks/useColor'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTokenBalance } from '../../state/wallet/hooks'
import { ExternalLink, TYPE } from '../../theme'
import { ExternalLink, ThemedText } from '../../theme'
import { currencyId } from '../../utils/currencyId'
import { unwrappedToken } from '../../utils/unwrappedToken'
import { ButtonEmpty, ButtonPrimary, ButtonSecondary } from '../Button'
@@ -142,7 +142,7 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
</GreyCard>
) : (
<LightCard>
<TYPE.subHeader style={{ textAlign: 'center' }}>
<ThemedText.SubHeader style={{ textAlign: 'center' }}>
<span role="img" aria-label="wizard-icon">
</span>{' '}
@@ -150,7 +150,7 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
By adding liquidity you&apos;ll earn 0.3% of all trades on this pair proportional to your share of the
pool. Fees are added to the pool, accrue in real time and can be claimed by withdrawing your liquidity.
</Trans>{' '}
</TYPE.subHeader>
</ThemedText.SubHeader>
</LightCard>
)}
</>

View File

@@ -1,4 +1,5 @@
import { Trans } from '@lingui/macro'
import { ButtonText } from 'components/Button'
import PositionListItem from 'components/PositionListItem'
import React from 'react'
import styled from 'styled-components/macro'
@@ -14,9 +15,7 @@ const DesktopHeader = styled.div`
@media screen and (min-width: ${MEDIA_WIDTHS.upToSmall}px) {
align-items: center;
display: flex;
display: grid;
grid-template-columns: 1fr 1fr;
justify-content: space-between;
& > div:last-child {
text-align: right;
margin-right: 12px;
@@ -36,9 +35,15 @@ const MobileHeader = styled.div`
type PositionListProps = React.PropsWithChildren<{
positions: PositionDetails[]
setUserHideClosedPositions: any
userHideClosedPositions: boolean
}>
export default function PositionList({ positions }: PositionListProps) {
export default function PositionList({
positions,
setUserHideClosedPositions,
userHideClosedPositions,
}: PositionListProps) {
return (
<>
<DesktopHeader>
@@ -46,9 +51,9 @@ export default function PositionList({ positions }: PositionListProps) {
<Trans>Your positions</Trans>
{positions && ' (' + positions.length + ')'}
</div>
<div>
<Trans>Status</Trans>
</div>
<ButtonText style={{ opacity: 0.6 }} onClick={() => setUserHideClosedPositions(!userHideClosedPositions)}>
<Trans>Hide closed positions</Trans>
</ButtonText>
</DesktopHeader>
<MobileHeader>
<Trans>Your positions</Trans>

View File

@@ -19,7 +19,7 @@ import { PositionDetails } from 'types/position'
import { formatTickPrice } from 'utils/formatTickPrice'
import { unwrappedToken } from 'utils/unwrappedToken'
import { DAI, USDC, USDT, WBTC, WETH9_EXTENDED } from '../../constants/tokens'
import { DAI, USDC, USDT, WBTC, WRAPPED_NATIVE_CURRENCY } from '../../constants/tokens'
const LinkRow = styled(Link)`
align-items: center;
@@ -156,7 +156,7 @@ export function getPriceOrderingFromPositionForUI(position?: Position): {
}
// if token1 is an ETH-/BTC-stable asset, set it as the base token
const bases = [...Object.values(WETH9_EXTENDED), WBTC]
const bases = [...Object.values(WRAPPED_NATIVE_CURRENCY), WBTC]
if (bases.some((base) => base.equals(token1))) {
return {
priceLower: position.token0PriceUpper.invert(),

View File

@@ -13,7 +13,7 @@ import JSBI from 'jsbi'
import { ReactNode, useCallback, useContext, useState } from 'react'
import { Bound } from 'state/mint/v3/actions'
import { ThemeContext } from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { formatTickPrice } from 'utils/formatTickPrice'
import { unwrappedToken } from 'utils/unwrappedToken'
@@ -70,9 +70,9 @@ export const PositionPreview = ({
size={24}
margin={true}
/>
<TYPE.label ml="10px" fontSize="24px">
<ThemedText.Label ml="10px" fontSize="24px">
{currency0?.symbol} / {currency1?.symbol}
</TYPE.label>
</ThemedText.Label>
</RowFixed>
<RangeBadge removed={removed} inRange={inRange} />
</RowBetween>
@@ -82,36 +82,36 @@ export const PositionPreview = ({
<RowBetween>
<RowFixed>
<CurrencyLogo currency={currency0} />
<TYPE.label ml="8px">{currency0?.symbol}</TYPE.label>
<ThemedText.Label ml="8px">{currency0?.symbol}</ThemedText.Label>
</RowFixed>
<RowFixed>
<TYPE.label mr="8px">{position.amount0.toSignificant(4)}</TYPE.label>
<ThemedText.Label mr="8px">{position.amount0.toSignificant(4)}</ThemedText.Label>
</RowFixed>
</RowBetween>
<RowBetween>
<RowFixed>
<CurrencyLogo currency={currency1} />
<TYPE.label ml="8px">{currency1?.symbol}</TYPE.label>
<ThemedText.Label ml="8px">{currency1?.symbol}</ThemedText.Label>
</RowFixed>
<RowFixed>
<TYPE.label mr="8px">{position.amount1.toSignificant(4)}</TYPE.label>
<ThemedText.Label mr="8px">{position.amount1.toSignificant(4)}</ThemedText.Label>
</RowFixed>
</RowBetween>
<Break />
<RowBetween>
<TYPE.label>
<ThemedText.Label>
<Trans>Fee Tier</Trans>
</TYPE.label>
<TYPE.label>
</ThemedText.Label>
<ThemedText.Label>
<Trans>{position?.pool?.fee / 10000}%</Trans>
</TYPE.label>
</ThemedText.Label>
</RowBetween>
</AutoColumn>
</LightCard>
<AutoColumn gap="md">
<RowBetween>
{title ? <TYPE.main>{title}</TYPE.main> : <div />}
{title ? <ThemedText.Main>{title}</ThemedText.Main> : <div />}
<RateToggle
currencyA={sorted ? currency0 : currency1}
currencyB={sorted ? currency1 : currency0}
@@ -122,57 +122,57 @@ export const PositionPreview = ({
<RowBetween>
<LightCard width="48%" padding="8px">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">
<ThemedText.Main fontSize="12px">
<Trans>Min Price</Trans>
</TYPE.main>
<TYPE.mediumHeader textAlign="center">{`${formatTickPrice(
</ThemedText.Main>
<ThemedText.MediumHeader textAlign="center">{`${formatTickPrice(
priceLower,
ticksAtLimit,
Bound.LOWER
)}`}</TYPE.mediumHeader>
<TYPE.main textAlign="center" fontSize="12px">
)}`}</ThemedText.MediumHeader>
<ThemedText.Main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
</ThemedText.Main>
<ThemedText.Small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
<Trans>Your position will be 100% composed of {baseCurrency?.symbol} at this price</Trans>
</TYPE.small>
</ThemedText.Small>
</AutoColumn>
</LightCard>
<LightCard width="48%" padding="8px">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">
<ThemedText.Main fontSize="12px">
<Trans>Max Price</Trans>
</TYPE.main>
<TYPE.mediumHeader textAlign="center">{`${formatTickPrice(
</ThemedText.Main>
<ThemedText.MediumHeader textAlign="center">{`${formatTickPrice(
priceUpper,
ticksAtLimit,
Bound.UPPER
)}`}</TYPE.mediumHeader>
<TYPE.main textAlign="center" fontSize="12px">
)}`}</ThemedText.MediumHeader>
<ThemedText.Main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
</ThemedText.Main>
<ThemedText.Small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
<Trans>Your position will be 100% composed of {quoteCurrency?.symbol} at this price</Trans>
</TYPE.small>
</ThemedText.Small>
</AutoColumn>
</LightCard>
</RowBetween>
<LightCard padding="12px ">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">
<ThemedText.Main fontSize="12px">
<Trans>Current price</Trans>
</TYPE.main>
<TYPE.mediumHeader>{`${price.toSignificant(5)} `}</TYPE.mediumHeader>
<TYPE.main textAlign="center" fontSize="12px">
</ThemedText.Main>
<ThemedText.MediumHeader>{`${price.toSignificant(5)} `}</ThemedText.MediumHeader>
<ThemedText.Main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
</ThemedText.Main>
</AutoColumn>
</LightCard>
</AutoColumn>

View File

@@ -0,0 +1,179 @@
import { Trans } from '@lingui/macro'
import Card, { DarkGreyCard } from 'components/Card'
import Row, { AutoRow, RowBetween } from 'components/Row'
import { useEffect, useRef } from 'react'
import { ArrowDown, Info, X } from 'react-feather'
import ReactGA from 'react-ga'
import styled from 'styled-components/macro'
import { ExternalLink, ThemedText } from 'theme'
import { isMobile } from 'utils/userAgent'
import { useModalOpen, useTogglePrivacyPolicy } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { AutoColumn } from '../Column'
import Modal from '../Modal'
const Wrapper = styled.div`
max-height: 70vh;
overflow: auto;
padding: 0 1rem;
`
const StyledExternalCard = styled(Card)`
background-color: ${({ theme }) => theme.primary5};
padding: 0.5rem;
width: 100%;
:hover,
:focus,
:active {
background-color: ${({ theme }) => theme.primary4};
}
`
const HoverText = styled.div`
text-decoration: none;
color: ${({ theme }) => theme.text1};
display: flex;
align-items: center;
:hover {
cursor: pointer;
}
`
const StyledLinkOut = styled(ArrowDown)`
transform: rotate(230deg);
`
const EXTERNAL_APIS = [
{
name: 'Auto Router',
description: <Trans>The app fetches the optimal trade route from a Uniswap Labs server.</Trans>,
},
{
name: 'Infura',
description: <Trans>The app fetches on-chain data and constructs contract calls with an Infura API.</Trans>,
},
{
name: 'TRM Labs',
description: (
<>
<Trans>
The app securely collects your wallet address and shares it with TRM Labs Inc. for risk and compliance
reasons.
</Trans>{' '}
<ExternalLink href="https://help.uniswap.org/en/articles/5675203-terms-of-service-faq">
<Trans>Learn more</Trans>
</ExternalLink>
</>
),
},
{
name: 'Google Analytics',
description: <Trans>The app logs anonymized usage statistics in order to improve over time.</Trans>,
},
{
name: 'The Graph',
description: <Trans>The app fetches blockchain data from The Graphs hosted service.</Trans>,
},
]
export function PrivacyPolicyModal() {
const node = useRef<HTMLDivElement>()
const open = useModalOpen(ApplicationModal.PRIVACY_POLICY)
const toggle = useTogglePrivacyPolicy()
useEffect(() => {
if (!open) return
ReactGA.event({
category: 'Modal',
action: 'Show Legal',
})
}, [open])
return (
<Modal isOpen={open} onDismiss={() => toggle()}>
<AutoColumn gap="12px" ref={node as any}>
<RowBetween padding="1rem 1rem 0.5rem 1rem">
<ThemedText.MediumHeader>
<Trans>Legal & Privacy</Trans>
</ThemedText.MediumHeader>
<HoverText onClick={() => toggle()}>
<X size={24} />
</HoverText>
</RowBetween>
<PrivacyPolicy />
</AutoColumn>
</Modal>
)
}
export function PrivacyPolicy() {
return (
<Wrapper
draggable="true"
onTouchMove={(e) => {
// prevent modal gesture handler from dismissing modal when content is scrolling
if (isMobile) {
e.stopPropagation()
}
}}
>
<AutoColumn gap="16px">
<AutoColumn gap="8px" style={{ width: '100%' }}>
<StyledExternalCard>
<ExternalLink href={'https://uniswap.org/terms-of-service'}>
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<ThemedText.Main fontSize={14} color={'primaryText1'}>
<Trans>Uniswap Labs&apos; Terms of Service</Trans>
</ThemedText.Main>
</AutoRow>
<StyledLinkOut size={20} />
</RowBetween>
</ExternalLink>
</StyledExternalCard>
<StyledExternalCard>
<ExternalLink href={'https://uniswap.org/disclaimer/'}>
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<ThemedText.Main fontSize={14} color={'primaryText1'}>
<Trans>Protocol Disclaimer</Trans>
</ThemedText.Main>
</AutoRow>
<StyledLinkOut size={20} />
</RowBetween>
</ExternalLink>
</StyledExternalCard>
</AutoColumn>
<ThemedText.Main fontSize={14}>
<Trans>This app uses the following third-party APIs:</Trans>
</ThemedText.Main>
<AutoColumn gap="12px">
{EXTERNAL_APIS.map(({ name, description }, i) => (
<DarkGreyCard key={i}>
<AutoColumn gap="8px">
<AutoRow gap="4px">
<Info size={18} />
<ThemedText.Main fontSize={14} color={'text1'}>
{name}
</ThemedText.Main>
</AutoRow>
<ThemedText.Main fontSize={14}>{description}</ThemedText.Main>
</AutoColumn>
</DarkGreyCard>
))}
<Row justify="center" marginBottom="1rem">
<ExternalLink href="https://help.uniswap.org/en/articles/5675203-terms-of-service-faq">
<Trans>Learn more</Trans>
</ExternalLink>
</Row>
</AutoColumn>
</AutoColumn>
</Wrapper>
)
}

View File

@@ -2,7 +2,7 @@ import { useContext } from 'react'
import styled from 'styled-components/macro'
import { ThemeContext } from 'styled-components/macro'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { AutoColumn } from '../Column'
const Wrapper = styled(AutoColumn)`
@@ -65,7 +65,7 @@ export default function ProgressCircles({ steps, disabled = false, ...rest }: Pr
<Circle confirmed={step} disabled={disabled || (!steps[i - 1] && i !== 0)}>
{step ? '✓' : i + 1 + '.'}
</Circle>
<TYPE.main color={theme.text4}>|</TYPE.main>
<ThemedText.Main color={theme.text4}>|</ThemedText.Main>
</CircleRow>
)
})}

View File

@@ -4,7 +4,7 @@ import { AutoRow } from 'components/Row'
import React from 'react'
import ReactGA from 'react-ga'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
const Button = styled(ButtonOutlined).attrs(() => ({
padding: '8px',
@@ -26,9 +26,9 @@ export default function PresetsButtons({ setFullRange }: { setFullRange: () => v
})
}}
>
<TYPE.body fontSize={12}>
<ThemedText.Body fontSize={12}>
<Trans>Full Range</Trans>
</TYPE.body>
</ThemedText.Body>
</Button>
</AutoRow>
)

View File

@@ -1,3 +1,4 @@
import { Protocol } from '@uniswap/router-sdk'
import { Currency, Percent } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk'
import { DAI, USDC, WBTC } from 'constants/tokens'
@@ -7,16 +8,21 @@ import RoutingDiagram, { RoutingDiagramEntry } from './RoutingDiagram'
const percent = (strings: TemplateStringsArray) => new Percent(parseInt(strings[0]), 100)
const singleRoute: RoutingDiagramEntry = { percent: percent`100`, path: [[USDC, DAI, FeeAmount.LOW]] }
const singleRoute: RoutingDiagramEntry = {
percent: percent`100`,
path: [[USDC, DAI, FeeAmount.LOW]],
protocol: Protocol.V3,
}
const multiRoute: RoutingDiagramEntry[] = [
{ percent: percent`75`, path: [[USDC, DAI, FeeAmount.LOW]] },
{ percent: percent`75`, path: [[USDC, DAI, FeeAmount.LOWEST]], protocol: Protocol.V2 },
{
percent: percent`25`,
path: [
[USDC, WBTC, FeeAmount.MEDIUM],
[WBTC, DAI, FeeAmount.HIGH],
],
protocol: Protocol.V3,
},
]

View File

@@ -1,3 +1,5 @@
import { Trans } from '@lingui/macro'
import { Protocol } from '@uniswap/router-sdk'
import { Currency, Percent } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk'
import Badge from 'components/Badge'
@@ -7,22 +9,24 @@ import Row, { AutoRow } from 'components/Row'
import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList'
import { Box } from 'rebass'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText, Z_INDEX } from 'theme'
import { ReactComponent as DotLine } from '../../assets/svg/dot_line.svg'
import { MouseoverTooltip } from '../Tooltip'
export interface RoutingDiagramEntry {
percent: Percent
path: [Currency, Currency, FeeAmount][]
protocol: Protocol
}
const Wrapper = styled(Box)`
align-items: center;
background-color: ${({ theme }) => theme.bg0};
width: 400px;
width: 100%;
`
const RouteContainerRow = styled(Row)`
display: grid;
grid-gap: 8px;
grid-template-columns: 24px 1fr 24px;
`
@@ -36,22 +40,47 @@ const RouteRow = styled(Row)`
const PoolBadge = styled(Badge)`
display: flex;
padding: 0.25rem 0.5rem;
padding: 4px 4px;
`
const DottedLine = styled.div`
border-color: ${({ theme }) => theme.bg4};
border-top-style: dotted;
border-width: 4px;
height: 0px;
display: flex;
align-items: center;
position: absolute;
width: calc(100%);
z-index: 1;
opacity: 0.5;
`
const DotColor = styled(DotLine)`
path {
stroke: ${({ theme }) => theme.bg4};
}
`
const OpaqueBadge = styled(Badge)`
background-color: ${({ theme }) => theme.bg2};
z-index: 2;
border-radius: 8px;
display: grid;
font-size: 12px;
grid-gap: 4px;
grid-auto-flow: column;
justify-content: start;
padding: 4px 6px 4px 4px;
z-index: ${Z_INDEX.sticky};
`
const ProtocolBadge = styled(Badge)`
background-color: ${({ theme }) => theme.bg3};
border-radius: 4px;
color: ${({ theme }) => theme.text2};
font-size: 10px;
padding: 2px 4px;
z-index: ${Z_INDEX.sticky + 1};
`
const BadgeText = styled(ThemedText.Small)`
word-break: normal;
`
export default function RoutingDiagram({
@@ -68,27 +97,31 @@ export default function RoutingDiagram({
return (
<Wrapper>
{routes.map(({ percent, path }, index) => (
{routes.map((entry, index) => (
<RouteContainerRow key={index}>
<CurrencyLogo currency={tokenIn} />
<Route percent={percent} path={path} />
<CurrencyLogo currency={tokenOut} />
<CurrencyLogo currency={tokenIn} size={'20px'} />
<Route entry={entry} />
<CurrencyLogo currency={tokenOut} size={'20px'} />
</RouteContainerRow>
))}
</Wrapper>
)
}
function Route({ percent, path }: { percent: RoutingDiagramEntry['percent']; path: RoutingDiagramEntry['path'] }) {
function Route({ entry: { percent, path, protocol } }: { entry: RoutingDiagramEntry }) {
return (
<RouteRow>
<DottedLine />
<DottedLine>
<DotColor />
</DottedLine>
<OpaqueBadge>
<TYPE.small fontSize={12} style={{ wordBreak: 'normal' }}>
<ProtocolBadge>
<BadgeText fontSize={12}>{protocol.toUpperCase()}</BadgeText>
</ProtocolBadge>
<BadgeText fontSize={14} style={{ minWidth: 'auto' }}>
{percent.toSignificant(2)}%
</TYPE.small>
</BadgeText>
</OpaqueBadge>
<AutoRow gap="1px" width="100%" style={{ justifyContent: 'space-evenly', zIndex: 2 }}>
{path.map(([currency0, currency1, feeAmount], index) => (
<Pool key={index} currency0={currency0} currency1={currency1} feeAmount={feeAmount} />
@@ -102,12 +135,17 @@ function Pool({ currency0, currency1, feeAmount }: { currency0: Currency; curren
const tokenInfo0 = useTokenInfoFromActiveList(currency0)
const tokenInfo1 = useTokenInfoFromActiveList(currency1)
// TODO - link pool icon to info.uniswap.org via query params
return (
<PoolBadge>
<Box margin="0 5px 0 10px">
<DoubleCurrencyLogo currency0={tokenInfo1} currency1={tokenInfo0} size={20} />
</Box>
<TYPE.small fontSize={12}>{feeAmount / 10000}%</TYPE.small>
</PoolBadge>
<MouseoverTooltip
text={<Trans>{tokenInfo0?.symbol + '/' + tokenInfo1?.symbol + ' ' + feeAmount / 10000}% pool</Trans>}
>
<PoolBadge>
<Box margin="0 4px 0 12px">
<DoubleCurrencyLogo currency0={tokenInfo1} currency1={tokenInfo0} size={20} />
</Box>
<ThemedText.Small fontSize={14}>{feeAmount / 10000}%</ThemedText.Small>
</PoolBadge>
</MouseoverTooltip>
)
}

View File

@@ -3,24 +3,39 @@
exports[`renders multi route 1`] = `
<DocumentFragment>
<div
class="RoutingDiagram__Wrapper-sc-o1ook0-0 fUoVYh css-vurnku"
class="RoutingDiagram__Wrapper-sc-o1ook0-0 ePDWDk css-vurnku"
>
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteContainerRow-sc-o1ook0-1 lmTMKd itvFNV iiQQUx"
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteContainerRow-sc-o1ook0-1 lmTMKd itvFNV ibRCpr"
>
CurrencyLogo currency=USDC
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteRow-sc-o1ook0-2 lmTMKd itvFNV fzMiot"
>
<div
class="RoutingDiagram__DottedLine-sc-o1ook0-4 gwivhA"
/>
class="RoutingDiagram__DottedLine-sc-o1ook0-4 kkXINS"
>
<svg
class="RoutingDiagram__DotColor-sc-o1ook0-5 kgYqrO"
>
dot_line.svg
</svg>
</div>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-5 gayll cvyxdH"
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-6 gayll OurGh"
>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab css-15li2d9"
style="word-break: normal;"
class="Badge-sc-1mhw5si-0 RoutingDiagram__ProtocolBadge-sc-o1ook0-7 gayll bNVqMw"
>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-15li2d9"
>
V2
</div>
</div>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-1aekuku"
style="min-width: auto;"
>
75%
</div>
@@ -30,40 +45,42 @@ exports[`renders multi route 1`] = `
style="justify-content: space-evenly; z-index: 2;"
width="100%"
>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__PoolBadge-sc-o1ook0-3 gayll bRJvWg"
>
<div
class="css-1t7xebc"
>
DoubleCurrencyLogo currency0=DAI currency1=USDC
</div>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab css-15li2d9"
>
0.05%
</div>
</div>
Popover
</div>
</div>
CurrencyLogo currency=DAI
</div>
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteContainerRow-sc-o1ook0-1 lmTMKd itvFNV iiQQUx"
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteContainerRow-sc-o1ook0-1 lmTMKd itvFNV ibRCpr"
>
CurrencyLogo currency=USDC
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteRow-sc-o1ook0-2 lmTMKd itvFNV fzMiot"
>
<div
class="RoutingDiagram__DottedLine-sc-o1ook0-4 gwivhA"
/>
class="RoutingDiagram__DottedLine-sc-o1ook0-4 kkXINS"
>
<svg
class="RoutingDiagram__DotColor-sc-o1ook0-5 kgYqrO"
>
dot_line.svg
</svg>
</div>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-5 gayll cvyxdH"
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-6 gayll OurGh"
>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab css-15li2d9"
style="word-break: normal;"
class="Badge-sc-1mhw5si-0 RoutingDiagram__ProtocolBadge-sc-o1ook0-7 gayll bNVqMw"
>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-15li2d9"
>
V3
</div>
</div>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-1aekuku"
style="min-width: auto;"
>
25%
</div>
@@ -73,34 +90,7 @@ exports[`renders multi route 1`] = `
style="justify-content: space-evenly; z-index: 2;"
width="100%"
>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__PoolBadge-sc-o1ook0-3 gayll bRJvWg"
>
<div
class="css-1t7xebc"
>
DoubleCurrencyLogo currency0=WBTC currency1=USDC
</div>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab css-15li2d9"
>
0.3%
</div>
</div>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__PoolBadge-sc-o1ook0-3 gayll bRJvWg"
>
<div
class="css-1t7xebc"
>
DoubleCurrencyLogo currency0=DAI currency1=WBTC
</div>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab css-15li2d9"
>
1%
</div>
</div>
PopoverPopover
</div>
</div>
CurrencyLogo currency=DAI
@@ -112,24 +102,39 @@ exports[`renders multi route 1`] = `
exports[`renders single route 1`] = `
<DocumentFragment>
<div
class="RoutingDiagram__Wrapper-sc-o1ook0-0 fUoVYh css-vurnku"
class="RoutingDiagram__Wrapper-sc-o1ook0-0 ePDWDk css-vurnku"
>
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteContainerRow-sc-o1ook0-1 lmTMKd itvFNV iiQQUx"
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteContainerRow-sc-o1ook0-1 lmTMKd itvFNV ibRCpr"
>
CurrencyLogo currency=USDC
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteRow-sc-o1ook0-2 lmTMKd itvFNV fzMiot"
>
<div
class="RoutingDiagram__DottedLine-sc-o1ook0-4 gwivhA"
/>
class="RoutingDiagram__DottedLine-sc-o1ook0-4 kkXINS"
>
<svg
class="RoutingDiagram__DotColor-sc-o1ook0-5 kgYqrO"
>
dot_line.svg
</svg>
</div>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-5 gayll cvyxdH"
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-6 gayll OurGh"
>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab css-15li2d9"
style="word-break: normal;"
class="Badge-sc-1mhw5si-0 RoutingDiagram__ProtocolBadge-sc-o1ook0-7 gayll bNVqMw"
>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-15li2d9"
>
V3
</div>
</div>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-1aekuku"
style="min-width: auto;"
>
100%
</div>
@@ -139,20 +144,7 @@ exports[`renders single route 1`] = `
style="justify-content: space-evenly; z-index: 2;"
width="100%"
>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__PoolBadge-sc-o1ook0-3 gayll bRJvWg"
>
<div
class="css-1t7xebc"
>
DoubleCurrencyLogo currency0=DAI currency1=USDC
</div>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab css-15li2d9"
>
0.05%
</div>
</div>
Popover
</div>
</div>
CurrencyLogo currency=DAI
@@ -164,7 +156,7 @@ exports[`renders single route 1`] = `
exports[`renders when no routes are provided 1`] = `
<DocumentFragment>
<div
class="RoutingDiagram__Wrapper-sc-o1ook0-0 fUoVYh css-vurnku"
class="RoutingDiagram__Wrapper-sc-o1ook0-0 ePDWDk css-vurnku"
/>
</DocumentFragment>
`;

View File

@@ -0,0 +1,71 @@
import { Trans } from '@lingui/macro'
import { Token } from '@uniswap/sdk-core'
import { ButtonPrimary } from 'components/Button'
import { AlertCircle, ArrowLeft } from 'react-feather'
import styled from 'styled-components/macro'
import { CloseIcon, ThemedText } from 'theme'
import TokenImportCard from './TokenImportCard'
const Wrapper = styled.div`
align-items: center;
display: flex;
flex-direction: column;
flex: 1 1 auto;
height: 100%;
width: 100%;
`
const Button = styled(ButtonPrimary)`
margin-top: 1em;
padding: 10px 1em;
`
const Content = styled.div`
padding: 1em;
`
const Copy = styled(ThemedText.Body)`
text-align: center;
margin: 0 2em 1em !important;
font-weight: 400;
font-size: 16px;
`
const Header = styled.div`
align-items: center;
display: flex;
gap: 14px;
justify-content: space-between;
padding: 20px;
width: 100%;
`
const Icon = styled(AlertCircle)`
stroke: ${({ theme }) => theme.text2};
width: 48px;
height: 48px;
`
interface BlockedTokenProps {
onBack: (() => void) | undefined
onDismiss: (() => void) | undefined
blockedTokens: Token[]
}
const BlockedToken = ({ onBack, onDismiss, blockedTokens }: BlockedTokenProps) => (
<Wrapper>
<Header>
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div />}
<ThemedText.MediumHeader>
<Trans>Token not supported</Trans>
</ThemedText.MediumHeader>
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div />}
</Header>
<Icon />
<Content>
<Copy>
<Trans>This token is not supported in the Uniswap Labs app</Trans>
</Copy>
<TokenImportCard token={blockedTokens[0]} />
<Button disabled>
<Trans>Import</Trans>
</Button>
</Content>
</Wrapper>
)
export default BlockedToken

View File

@@ -1,10 +1,9 @@
import { Trans } from '@lingui/macro'
import { Currency } from '@uniswap/sdk-core'
import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import QuestionHelper from 'components/QuestionHelper'
import { AutoRow } from 'components/Row'
import { COMMON_BASES } from 'constants/routing'
import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
import { currencyId } from 'utils/currencyId'
@@ -45,12 +44,6 @@ export default function CommonBases({
return bases.length > 0 ? (
<MobileWrapper gap="md">
<AutoRow>
<Text fontWeight={500} fontSize={14}>
<Trans>Common bases</Trans>
</Text>
<QuestionHelper text={<Trans>These tokens are commonly paired with other tokens.</Trans>} />
</AutoRow>
<AutoRow gap="4px">
{bases.map((currency: Currency) => {
const isSelected = selectedCurrency?.equals(currency)
@@ -60,7 +53,7 @@ export default function CommonBases({
disable={isSelected}
key={currencyId(currency)}
>
<CurrencyLogo currency={currency} style={{ marginRight: 8 }} />
<CurrencyLogoFromList currency={currency} />
<Text fontWeight={500} fontSize={16}>
{currency.symbol}
</Text>
@@ -71,3 +64,10 @@ export default function CommonBases({
</MobileWrapper>
) : null
}
/** helper component to retrieve a base currency from the active token lists */
function CurrencyLogoFromList({ currency }: { currency: Currency }) {
const token = useTokenInfoFromActiveList(currency)
return <CurrencyLogo currency={token} style={{ marginRight: 8 }} />
}

View File

@@ -14,7 +14,7 @@ import { useActiveWeb3React } from '../../hooks/web3'
import { useCombinedActiveList } from '../../state/lists/hooks'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
import { useCurrencyBalance } from '../../state/wallet/hooks'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { isTokenOnList } from '../../utils'
import Column from '../Column'
import CurrencyLogo from '../CurrencyLogo'
@@ -135,13 +135,13 @@ function CurrencyRow({
<Text title={currency.name} fontWeight={500}>
{currency.symbol}
</Text>
<TYPE.darkGray ml="0px" fontSize={'12px'} fontWeight={300}>
<ThemedText.DarkGray ml="0px" fontSize={'12px'} fontWeight={300}>
{!currency.isNative && !isOnSelectedList && customAdded ? (
<Trans>{currency.name} Added by user</Trans>
) : (
currency.name
)}
</TYPE.darkGray>
</ThemedText.DarkGray>
</Column>
<TokenTags currency={currency} />
{showCurrencyAmount && (
@@ -167,9 +167,9 @@ function BreakLineComponent({ style }: { style: CSSProperties }) {
<RowBetween>
<RowFixed>
<TokenListLogoWrapper src={TokenListLogo} />
<TYPE.main ml="6px" fontSize="12px" color={theme.text1}>
<ThemedText.Main ml="6px" fontSize="12px" color={theme.text1}>
<Trans>Expanded results from inactive Token Lists</Trans>
</TYPE.main>
</ThemedText.Main>
</RowFixed>
<QuestionHelper
text={

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro'
import { Currency, Token } from '@uniswap/sdk-core'
import useDebounce from 'hooks/useDebounce'
@@ -12,10 +13,15 @@ import { FixedSizeList } from 'react-window'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
import { ExtendedEther } from '../../constants/tokens'
import { useAllTokens, useIsUserAddedToken, useSearchInactiveTokenLists, useToken } from '../../hooks/Tokens'
import {
useAllTokens,
useIsUserAddedToken,
useNativeCurrency,
useSearchInactiveTokenLists,
useToken,
} from '../../hooks/Tokens'
import { useActiveWeb3React } from '../../hooks/web3'
import { ButtonText, CloseIcon, IconWrapper, TYPE } from '../../theme'
import { ButtonText, CloseIcon, IconWrapper, ThemedText } from '../../theme'
import { isAddress } from '../../utils'
import Column from '../Column'
import Row, { RowBetween, RowFixed } from '../Row'
@@ -111,15 +117,17 @@ export function CurrencySearch({
const filteredSortedTokens = useSortedTokensByQuery(sortedTokens, debouncedQuery)
const ether = useMemo(() => chainId && ExtendedEther.onChain(chainId), [chainId])
const native = useNativeCurrency()
const filteredSortedTokensWithETH: Currency[] = useMemo(() => {
if (!native) return filteredSortedTokens
const s = debouncedQuery.toLowerCase().trim()
if (s === '' || s === 'e' || s === 'et' || s === 'eth') {
return ether ? [ether, ...filteredSortedTokens] : filteredSortedTokens
if (native.symbol?.toLowerCase()?.indexOf(s) !== -1) {
return native ? [native, ...filteredSortedTokens] : filteredSortedTokens
}
return filteredSortedTokens
}, [debouncedQuery, ether, filteredSortedTokens])
}, [debouncedQuery, native, filteredSortedTokens])
const handleCurrencySelect = useCallback(
(currency: Currency) => {
@@ -147,8 +155,8 @@ export function CurrencySearch({
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
const s = debouncedQuery.toLowerCase().trim()
if (s === 'eth' && ether) {
handleCurrencySelect(ether)
if (s === native?.symbol?.toLowerCase()) {
handleCurrencySelect(native)
} else if (filteredSortedTokensWithETH.length > 0) {
if (
filteredSortedTokensWithETH[0].symbol?.toLowerCase() === debouncedQuery.trim().toLowerCase() ||
@@ -159,7 +167,7 @@ export function CurrencySearch({
}
}
},
[debouncedQuery, ether, filteredSortedTokensWithETH, handleCurrencySelect]
[debouncedQuery, native, filteredSortedTokensWithETH, handleCurrencySelect]
)
// menu ui
@@ -223,9 +231,9 @@ export function CurrencySearch({
</div>
) : (
<Column style={{ padding: '20px', height: '100%' }}>
<TYPE.main color={theme.text3} textAlign="center" mb="20px">
<ThemedText.Main color={theme.text3} textAlign="center" mb="20px">
<Trans>No results found.</Trans>
</TYPE.main>
</ThemedText.Main>
</Column>
)}
<Footer>
@@ -235,9 +243,9 @@ export function CurrencySearch({
<IconWrapper size="16px" marginRight="6px" stroke={theme.primaryText1}>
<Edit />
</IconWrapper>
<TYPE.main color={theme.primaryText1}>
<ThemedText.Main color={theme.primaryText1}>
<Trans>Manage Token Lists</Trans>
</TYPE.main>
</ThemedText.Main>
</RowFixed>
</ButtonText>
</Row>

View File

@@ -66,12 +66,19 @@ export default function CurrencySearchModal({
const [importList, setImportList] = useState<TokenList | undefined>()
const [listURL, setListUrl] = useState<string | undefined>()
const showImportView = useCallback(() => setModalView(CurrencyModalView.importToken), [setModalView])
const showManageView = useCallback(() => setModalView(CurrencyModalView.manage), [setModalView])
const handleBackImport = useCallback(
() => setModalView(prevView && prevView !== CurrencyModalView.importToken ? prevView : CurrencyModalView.search),
[setModalView, prevView]
)
// change min height if not searching
const minHeight = modalView === CurrencyModalView.importToken || modalView === CurrencyModalView.importList ? 40 : 80
return (
<Modal isOpen={isOpen} onDismiss={onDismiss} maxHeight={80} minHeight={minHeight}>
{modalView === CurrencyModalView.search ? (
let content = null
switch (modalView) {
case CurrencyModalView.search:
content = (
<CurrencySearch
isOpen={isOpen}
onDismiss={onDismiss}
@@ -81,23 +88,32 @@ export default function CurrencySearchModal({
showCommonBases={showCommonBases}
showCurrencyAmount={showCurrencyAmount}
disableNonToken={disableNonToken}
showImportView={() => setModalView(CurrencyModalView.importToken)}
showImportView={showImportView}
setImportToken={setImportToken}
showManageView={() => setModalView(CurrencyModalView.manage)}
showManageView={showManageView}
/>
) : modalView === CurrencyModalView.importToken && importToken ? (
<ImportToken
tokens={[importToken]}
onDismiss={onDismiss}
list={importToken instanceof WrappedTokenInfo ? importToken.list : undefined}
onBack={() =>
setModalView(prevView && prevView !== CurrencyModalView.importToken ? prevView : CurrencyModalView.search)
}
handleCurrencySelect={handleCurrencySelect}
/>
) : modalView === CurrencyModalView.importList && importList && listURL ? (
<ImportList list={importList} listURL={listURL} onDismiss={onDismiss} setModalView={setModalView} />
) : modalView === CurrencyModalView.manage ? (
)
break
case CurrencyModalView.importToken:
if (importToken) {
content = (
<ImportToken
tokens={[importToken]}
onDismiss={onDismiss}
list={importToken instanceof WrappedTokenInfo ? importToken.list : undefined}
onBack={handleBackImport}
handleCurrencySelect={handleCurrencySelect}
/>
)
}
break
case CurrencyModalView.importList:
if (importList && listURL) {
content = <ImportList list={importList} listURL={listURL} onDismiss={onDismiss} setModalView={setModalView} />
}
break
case CurrencyModalView.manage:
content = (
<Manage
onDismiss={onDismiss}
setModalView={setModalView}
@@ -105,9 +121,12 @@ export default function CurrencySearchModal({
setImportList={setImportList}
setListUrl={setListUrl}
/>
) : (
''
)}
)
break
}
return (
<Modal isOpen={isOpen} onDismiss={onDismiss} maxHeight={80} minHeight={minHeight}>
{content}
</Modal>
)
}

View File

@@ -16,9 +16,9 @@ import { useAppDispatch } from 'state/hooks'
import { enableList, removeList } from 'state/lists/actions'
import { useAllLists } from 'state/lists/hooks'
import styled from 'styled-components/macro'
import { CloseIcon, TYPE } from 'theme'
import { CloseIcon, ThemedText } from 'theme'
import { ExternalLink } from '../../theme/components'
import { ExternalLink } from '../../theme'
import { CurrencyModalView } from './CurrencySearchModal'
import { Checkbox, PaddedColumn, TextDot } from './styleds'
@@ -81,9 +81,9 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
<PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
<RowBetween>
<ArrowLeft style={{ cursor: 'pointer' }} onClick={() => setModalView(CurrencyModalView.manage)} />
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Import List</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<CloseIcon onClick={onDismiss} />
</RowBetween>
</PaddedColumn>
@@ -96,18 +96,18 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
{list.logoURI && <ListLogo logoURI={list.logoURI} size="40px" />}
<AutoColumn gap="sm" style={{ marginLeft: '20px' }}>
<RowFixed>
<TYPE.body fontWeight={600} mr="6px">
<ThemedText.Body fontWeight={600} mr="6px">
{list.name}
</TYPE.body>
</ThemedText.Body>
<TextDot />
<TYPE.main fontSize={'16px'} ml="6px">
<ThemedText.Main fontSize={'16px'} ml="6px">
<Trans>{list.tokens.length} tokens</Trans>
</TYPE.main>
</ThemedText.Main>
</RowFixed>
<ExternalLink href={`https://tokenlists.org/token-list?url=${listURL}`}>
<TYPE.main fontSize={'12px'} color={theme.blue1}>
<ThemedText.Main fontSize={'12px'} color={theme.blue1}>
{listURL}
</TYPE.main>
</ThemedText.Main>
</ExternalLink>
</AutoColumn>
</RowFixed>
@@ -116,22 +116,22 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
<Card style={{ backgroundColor: transparentize(0.8, theme.red1) }}>
<AutoColumn justify="center" style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
<AlertTriangle stroke={theme.red1} size={32} />
<TYPE.body fontWeight={500} fontSize={20} color={theme.red1}>
<ThemedText.Body fontWeight={500} fontSize={20} color={theme.red1}>
<Trans>Import at your own risk</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
<AutoColumn style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
<TYPE.body fontWeight={500} color={theme.red1}>
<ThemedText.Body fontWeight={500} color={theme.red1}>
<Trans>
By adding this list you are implicitly trusting that the data is correct. Anyone can create a list,
including creating fake versions of existing lists and lists that claim to represent projects that do
not have one.
</Trans>
</TYPE.body>
<TYPE.body fontWeight={600} color={theme.red1}>
</ThemedText.Body>
<ThemedText.Body fontWeight={600} color={theme.red1}>
<Trans>If you purchase a token from this list, you may not be able to sell it back.</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
<AutoRow justify="center" style={{ cursor: 'pointer' }} onClick={() => setConfirmed(!confirmed)}>
<Checkbox
@@ -140,9 +140,9 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
checked={confirmed}
onChange={() => setConfirmed(!confirmed)}
/>
<TYPE.body ml="10px" fontSize="16px" color={theme.red1} fontWeight={500}>
<ThemedText.Body ml="10px" fontSize="16px" color={theme.red1} fontWeight={500}>
<Trans>I understand</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoRow>
</Card>
@@ -156,9 +156,9 @@ export function ImportList({ listURL, list, setModalView, onDismiss }: ImportPro
<Trans>Import</Trans>
</ButtonPrimary>
{addError ? (
<TYPE.error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
<ThemedText.Error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
{addError}
</TYPE.error>
</ThemedText.Error>
) : null}
</AutoColumn>
{/* </Card> */}

View File

@@ -10,7 +10,7 @@ import useTheme from 'hooks/useTheme'
import { CSSProperties } from 'react'
import { CheckCircle } from 'react-feather'
import styled from 'styled-components/macro'
import { TYPE } from 'theme'
import { ThemedText } from 'theme'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
@@ -67,16 +67,16 @@ export default function ImportRow({
<CurrencyLogo currency={token} size={'24px'} style={{ opacity: dim ? '0.6' : '1' }} />
<AutoColumn gap="4px" style={{ opacity: dim ? '0.6' : '1' }}>
<AutoRow>
<TYPE.body fontWeight={500}>{token.symbol}</TYPE.body>
<TYPE.darkGray ml="8px" fontWeight={300}>
<ThemedText.Body fontWeight={500}>{token.symbol}</ThemedText.Body>
<ThemedText.DarkGray ml="8px" fontWeight={300}>
<NameOverflow title={token.name}>{token.name}</NameOverflow>
</TYPE.darkGray>
</ThemedText.DarkGray>
</AutoRow>
{list && list.logoURI && (
<RowFixed>
<TYPE.small mr="4px" color={theme.text3}>
<ThemedText.Small mr="4px" color={theme.text3}>
<Trans>via {list.name} </Trans>
</TYPE.small>
</ThemedText.Small>
<ListLogo logoURI={list.logoURI} size="12px" />
</RowFixed>
)}
@@ -97,9 +97,9 @@ export default function ImportRow({
) : (
<RowFixed style={{ minWidth: 'fit-content' }}>
<CheckIcon />
<TYPE.main color={theme.green1}>
<ThemedText.Main color={theme.green1}>
<Trans>Active</Trans>
</TYPE.main>
</ThemedText.Main>
</RowFixed>
)}
</TokenSection>

View File

@@ -2,23 +2,19 @@ import { Plural, Trans } from '@lingui/macro'
import { Currency, Token } from '@uniswap/sdk-core'
import { TokenList } from '@uniswap/token-lists'
import { ButtonPrimary } from 'components/Button'
import Card from 'components/Card'
import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import ListLogo from 'components/ListLogo'
import { RowBetween, RowFixed } from 'components/Row'
import { RowBetween } from 'components/Row'
import { SectionBreak } from 'components/swap/styleds'
import { useUnsupportedTokens } from 'hooks/Tokens'
import useTheme from 'hooks/useTheme'
import { useActiveWeb3React } from 'hooks/web3'
import { transparentize } from 'polished'
import { AlertCircle, ArrowLeft } from 'react-feather'
import { useAddUserToken } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { CloseIcon, TYPE } from 'theme'
import { CloseIcon, ThemedText } from 'theme'
import { ExternalLink } from '../../theme/components'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import BlockedToken from './BlockedToken'
import { PaddedColumn } from './styleds'
import TokenImportCard from './TokenImportCard'
const Wrapper = styled.div`
position: relative;
@@ -26,21 +22,6 @@ const Wrapper = styled.div`
overflow: auto;
`
const WarningWrapper = styled(Card)<{ highWarning: boolean }>`
background-color: ${({ theme, highWarning }) =>
highWarning ? transparentize(0.8, theme.red1) : transparentize(0.8, theme.yellow2)};
width: fit-content;
`
const AddressText = styled(TYPE.blue)`
font-size: 12px;
word-break: break-all;
${({ theme }) => theme.mediaWidth.upToSmall`
font-size: 10px;
`}
`
interface ImportProps {
tokens: Token[]
list?: TokenList
@@ -49,21 +30,26 @@ interface ImportProps {
handleCurrencySelect?: (currency: Currency) => void
}
export function ImportToken({ tokens, list, onBack, onDismiss, handleCurrencySelect }: ImportProps) {
export function ImportToken(props: ImportProps) {
const { tokens, list, onBack, onDismiss, handleCurrencySelect } = props
const theme = useTheme()
const { chainId } = useActiveWeb3React()
const addToken = useAddUserToken()
const unsupportedTokens = useUnsupportedTokens()
const unsupportedSet = new Set(Object.keys(unsupportedTokens))
const intersection = new Set(tokens.filter((token) => unsupportedSet.has(token.address)))
if (intersection.size > 0) {
return <BlockedToken onBack={onBack} onDismiss={onDismiss} blockedTokens={Array.from(intersection)} />
}
return (
<Wrapper>
<PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
<RowBetween>
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div />}
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Plural value={tokens.length} one="Import token" other="Import tokens" />
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div />}
</RowBetween>
</PaddedColumn>
@@ -71,59 +57,16 @@ export function ImportToken({ tokens, list, onBack, onDismiss, handleCurrencySel
<AutoColumn gap="md" style={{ marginBottom: '32px', padding: '1rem' }}>
<AutoColumn justify="center" style={{ textAlign: 'center', gap: '16px', padding: '1rem' }}>
<AlertCircle size={48} stroke={theme.text2} strokeWidth={1} />
<TYPE.body fontWeight={400} fontSize={16}>
<ThemedText.Body fontWeight={400} fontSize={16}>
<Trans>
This token doesn&apos;t appear on the active token list(s). Make sure this is the token that you want to
trade.
</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
{tokens.map((token) => {
return (
<Card
backgroundColor={theme.bg2}
key={'import' + token.address}
className=".token-warning-container"
padding="2rem"
>
<AutoColumn gap="10px" justify="center">
<CurrencyLogo currency={token} size={'32px'} />
<AutoColumn gap="4px" justify="center">
<TYPE.body ml="8px" mr="8px" fontWeight={500} fontSize={20}>
{token.symbol}
</TYPE.body>
<TYPE.darkGray fontWeight={400} fontSize={14}>
{token.name}
</TYPE.darkGray>
</AutoColumn>
{chainId && (
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}>
<AddressText fontSize={12}>{token.address}</AddressText>
</ExternalLink>
)}
{list !== undefined ? (
<RowFixed>
{list.logoURI && <ListLogo logoURI={list.logoURI} size="16px" />}
<TYPE.small ml="6px" fontSize={14} color={theme.text3}>
<Trans>via {list.name} token list</Trans>
</TYPE.small>
</RowFixed>
) : (
<WarningWrapper $borderRadius="4px" padding="4px" highWarning={true}>
<RowFixed>
<AlertCircle stroke={theme.red1} size="10px" />
<TYPE.body color={theme.red1} ml="4px" fontSize="10px" fontWeight={500}>
<Trans>Unknown Source</Trans>
</TYPE.body>
</RowFixed>
</WarningWrapper>
)}
</AutoColumn>
</Card>
)
})}
{tokens.map((token) => (
<TokenImportCard token={token} list={list} key={'import' + token.address} />
))}
<ButtonPrimary
altDisabledStyle={true}
$borderRadius="20px"

View File

@@ -16,7 +16,8 @@ import { PaddedColumn, Separator } from './styleds'
const Wrapper = styled.div`
width: 100%;
position: relative;
padding-bottom: 80px;
display: flex;
flex-flow: column;
`
const ToggleWrapper = styled(RowBetween)`

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro'
import { TokenList } from '@uniswap/token-lists'
import Card from 'components/Card'
@@ -17,7 +18,7 @@ import useTheme from '../../hooks/useTheme'
import useToggle from '../../hooks/useToggle'
import { acceptListUpdate, disableList, enableList, removeList } from '../../state/lists/actions'
import { useActiveListUrls, useAllLists, useIsListActive } from '../../state/lists/hooks'
import { ExternalLink, IconWrapper, LinkStyledButton, TYPE } from '../../theme'
import { ExternalLink, IconWrapper, LinkStyledButton, ThemedText } from '../../theme'
import listVersionLabel from '../../utils/listVersionLabel'
import { parseENSAddress } from '../../utils/parseENSAddress'
import uriToHttp from '../../utils/uriToHttp'
@@ -30,7 +31,8 @@ import { CurrencyModalView } from './CurrencySearchModal'
import { PaddedColumn, SearchInput, Separator, SeparatorDark } from './styleds'
const Wrapper = styled(Column)`
height: 100%;
flex: 1;
overflow-y: hidden;
`
const UnpaddedLinkStyledButton = styled(LinkStyledButton)`
@@ -74,7 +76,7 @@ const StyledTitleText = styled.div<{ active: boolean }>`
color: ${({ theme, active }) => (active ? theme.white : theme.text2)};
`
const StyledListUrlText = styled(TYPE.main)<{ active: boolean }>`
const StyledListUrlText = styled(ThemedText.Main)<{ active: boolean }>`
font-size: 12px;
color: ${({ theme, active }) => (active ? theme.white : theme.text2)};
`
@@ -228,7 +230,7 @@ const ListContainer = styled.div`
padding: 1rem;
height: 100%;
overflow: auto;
padding-bottom: 80px;
flex: 1;
`
export function ManageLists({
@@ -360,9 +362,9 @@ export function ManageLists({
/>
</Row>
{addError ? (
<TYPE.error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
<ThemedText.Error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
{addError}
</TYPE.error>
</ThemedText.Error>
) : null}
</PaddedColumn>
{tempList && (
@@ -372,10 +374,10 @@ export function ManageLists({
<RowFixed>
{tempList.logoURI && <ListLogo logoURI={tempList.logoURI} size="40px" />}
<AutoColumn gap="4px" style={{ marginLeft: '20px' }}>
<TYPE.body fontWeight={600}>{tempList.name}</TYPE.body>
<TYPE.main fontSize={'12px'}>
<ThemedText.Body fontWeight={600}>{tempList.name}</ThemedText.Body>
<ThemedText.Main fontSize={'12px'}>
<Trans>{tempList.tokens.length} tokens</Trans>
</TYPE.main>
</ThemedText.Main>
</AutoColumn>
</RowFixed>
{isImported ? (
@@ -383,9 +385,9 @@ export function ManageLists({
<IconWrapper stroke={theme.text2} size="16px" marginRight={'10px'}>
<CheckCircle />
</IconWrapper>
<TYPE.body color={theme.text2}>
<ThemedText.Body color={theme.text2}>
<Trans>Loaded</Trans>
</TYPE.body>
</ThemedText.Body>
</RowFixed>
) : (
<ButtonPrimary

View File

@@ -9,7 +9,7 @@ import { useActiveWeb3React } from 'hooks/web3'
import { RefObject, useCallback, useMemo, useRef, useState } from 'react'
import { useRemoveUserAddedToken, useUserAddedTokens } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { ButtonText, ExternalLink, ExternalLinkIcon, TrashIcon, TYPE } from 'theme'
import { ButtonText, ExternalLink, ExternalLinkIcon, ThemedText, TrashIcon } from 'theme'
import { isAddress } from 'utils'
import useTheme from '../../hooks/useTheme'
@@ -81,9 +81,9 @@ export default function ManageTokens({
<RowFixed>
<CurrencyLogo currency={token} size={'20px'} />
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}>
<TYPE.main ml={'10px'} fontWeight={600}>
<ThemedText.Main ml={'10px'} fontWeight={600}>
{token.symbol}
</TYPE.main>
</ThemedText.Main>
</ExternalLink>
</RowFixed>
<RowFixed>
@@ -111,9 +111,9 @@ export default function ManageTokens({
/>
</Row>
{searchQuery !== '' && !isAddressSearch && (
<TYPE.error error={true}>
<ThemedText.Error error={true}>
<Trans>Enter valid token address</Trans>
</TYPE.error>
</ThemedText.Error>
)}
{searchToken && (
<Card backgroundColor={theme.bg2} padding="10px 0">
@@ -129,14 +129,14 @@ export default function ManageTokens({
<Separator />
<PaddedColumn gap="lg" style={{ overflow: 'auto', marginBottom: '10px' }}>
<RowBetween>
<TYPE.main fontWeight={600}>
<ThemedText.Main fontWeight={600}>
<Trans>{userAddedTokens?.length} Custom Tokens</Trans>
</TYPE.main>
</ThemedText.Main>
{userAddedTokens.length > 0 && (
<ButtonText onClick={handleRemoveAll}>
<TYPE.blue>
<ThemedText.Blue>
<Trans>Clear all</Trans>
</TYPE.blue>
</ThemedText.Blue>
</ButtonText>
)}
</RowBetween>
@@ -144,9 +144,9 @@ export default function ManageTokens({
</PaddedColumn>
</Column>
<Footer>
<TYPE.darkGray>
<ThemedText.DarkGray>
<Trans>Tip: Custom tokens are stored locally in your browser</Trans>
</TYPE.darkGray>
</ThemedText.DarkGray>
</Footer>
</Wrapper>
)

View File

@@ -0,0 +1,76 @@
import { Trans } from '@lingui/macro'
import { Token } from '@uniswap/sdk-core'
import { TokenList } from '@uniswap/token-lists'
import Card from 'components/Card'
import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import ListLogo from 'components/ListLogo'
import { RowFixed } from 'components/Row'
import { useActiveWeb3React } from 'hooks/web3'
import { transparentize } from 'polished'
import { AlertCircle } from 'react-feather'
import styled, { useTheme } from 'styled-components/macro'
import { ExternalLink, ThemedText } from 'theme'
import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink'
const WarningWrapper = styled(Card)<{ highWarning: boolean }>`
background-color: ${({ theme, highWarning }) =>
highWarning ? transparentize(0.8, theme.red1) : transparentize(0.8, theme.yellow2)};
width: fit-content;
`
const AddressText = styled(ThemedText.Blue)`
font-size: 12px;
word-break: break-all;
${({ theme }) => theme.mediaWidth.upToSmall`
font-size: 10px;
`}
`
interface TokenImportCardProps {
list?: TokenList
token: Token
}
const TokenImportCard = ({ list, token }: TokenImportCardProps) => {
const theme = useTheme()
const { chainId } = useActiveWeb3React()
return (
<Card backgroundColor={theme.bg2} padding="2rem">
<AutoColumn gap="10px" justify="center">
<CurrencyLogo currency={token} size={'32px'} />
<AutoColumn gap="4px" justify="center">
<ThemedText.Body ml="8px" mr="8px" fontWeight={500} fontSize={20}>
{token.symbol}
</ThemedText.Body>
<ThemedText.DarkGray fontWeight={400} fontSize={14}>
{token.name}
</ThemedText.DarkGray>
</AutoColumn>
{chainId && (
<ExternalLink href={getExplorerLink(chainId, token.address, ExplorerDataType.ADDRESS)}>
<AddressText fontSize={12}>{token.address}</AddressText>
</ExternalLink>
)}
{list !== undefined ? (
<RowFixed>
{list.logoURI && <ListLogo logoURI={list.logoURI} size="16px" />}
<ThemedText.Small ml="6px" fontSize={14} color={theme.text3}>
<Trans>via {list.name} token list</Trans>
</ThemedText.Small>
</RowFixed>
) : (
<WarningWrapper $borderRadius="4px" padding="4px" highWarning={true}>
<RowFixed>
<AlertCircle stroke={theme.red1} size="10px" />
<ThemedText.Body color={theme.red1} ml="4px" fontSize="10px" fontWeight={500}>
<Trans>Unknown Source</Trans>
</ThemedText.Body>
</RowFixed>
</WarningWrapper>
)}
</AutoColumn>
</Card>
)
}
export default TokenImportCard

View File

@@ -1,18 +1,19 @@
// eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro'
import { Percent } from '@uniswap/sdk-core'
import { SupportedChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import { useContext, useRef, useState } from 'react'
import { Settings, X } from 'react-feather'
import ReactGA from 'react-ga'
import { Text } from 'rebass'
import { AUTO_ROUTER_SUPPORTED_CHAINS } from 'state/routing/clientSideSmartOrderRouter/constants'
import styled, { ThemeContext } from 'styled-components/macro'
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
import { ApplicationModal } from '../../state/application/actions'
import { useModalOpen, useToggleSettingsMenu } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { useClientSideRouter, useExpertModeManager } from '../../state/user/hooks'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { ButtonError } from '../Button'
import { AutoColumn } from '../Column'
import Modal from '../Modal'
@@ -26,7 +27,7 @@ const StyledMenuIcon = styled(Settings)`
width: 20px;
> * {
stroke: ${({ theme }) => theme.text2};
stroke: ${({ theme }) => theme.text1};
}
:hover {
@@ -198,16 +199,13 @@ export default function SettingsTab({ placeholderSlippage }: { placeholderSlippa
<Text fontWeight={600} fontSize={14}>
<Trans>Interface Settings</Trans>
</Text>
{chainId === SupportedChainId.MAINNET && (
{chainId && AUTO_ROUTER_SUPPORTED_CHAINS.includes(chainId) && (
<RowBetween>
<RowFixed>
<TYPE.black fontWeight={400} fontSize={14} color={theme.text2}>
<Trans>Auto Router</Trans>
</TYPE.black>
<QuestionHelper
text={<Trans>Use the Uniswap Labs API to get better pricing through a more efficient route.</Trans>}
/>
<ThemedText.Black fontWeight={400} fontSize={14} color={theme.text2}>
<Trans>Auto Router API</Trans>
</ThemedText.Black>
<QuestionHelper text={<Trans>Use the Uniswap Labs API to get faster quotes.</Trans>} />
</RowFixed>
<Toggle
id="toggle-optimized-router-button"
@@ -222,12 +220,11 @@ export default function SettingsTab({ placeholderSlippage }: { placeholderSlippa
/>
</RowBetween>
)}
<RowBetween>
<RowFixed>
<TYPE.black fontWeight={400} fontSize={14} color={theme.text2}>
<ThemedText.Black fontWeight={400} fontSize={14} color={theme.text2}>
<Trans>Expert Mode</Trans>
</TYPE.black>
</ThemedText.Black>
<QuestionHelper
text={
<Trans>Allow high price impact trades and skip the confirm screen. Use at your own risk.</Trans>

View File

@@ -5,9 +5,9 @@ import styled from 'styled-components/macro'
import { DEFAULT_LOCALE, LOCALE_LABEL, SupportedLocale } from '../../constants/locales'
import { navigatorLocale, useActiveLocale } from '../../hooks/useActiveLocale'
import { StyledInternalLink, TYPE } from '../../theme'
import { StyledInternalLink, ThemedText } from '../../theme'
const Container = styled(TYPE.small)`
const Container = styled(ThemedText.Small)`
opacity: 0.6;
:hover {
opacity: 1;

View File

@@ -1,7 +1,7 @@
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
const Wrapper = styled.button<{ isActive?: boolean; activeElement?: boolean }>`
border-radius: 20px;
@@ -25,7 +25,7 @@ const ToggleElement = styled.span<{ isActive?: boolean; bgColor?: string }>`
}
`
const StatusText = styled(TYPE.main)<{ isActive?: boolean }>`
const StatusText = styled(ThemedText.Main)<{ isActive?: boolean }>`
margin: 0 10px;
width: 24px;
color: ${({ theme, isActive }) => (isActive ? theme.text1 : theme.text3)};

View File

@@ -5,7 +5,7 @@ import styled from 'styled-components/macro'
import Popover, { PopoverProps } from '../Popover'
export const TooltipContainer = styled.div`
width: 256px;
max-width: 256px;
padding: 0.6rem 1rem;
font-weight: 400;
word-break: break-word;
@@ -25,6 +25,7 @@ interface TooltipContentProps extends Omit<PopoverProps, 'content'> {
onOpen?: () => void
// whether to wrap the content in a `TooltipContainer`
wrap?: boolean
disableHover?: boolean // disable the hover and content display
}
export default function Tooltip({ text, ...rest }: TooltipProps) {
@@ -52,6 +53,7 @@ export function MouseoverTooltipContent({
content,
children,
onOpen: openCallback = undefined,
disableHover,
...rest
}: Omit<TooltipContentProps, 'show'>) {
const [show, setShow] = useState(false)
@@ -61,7 +63,7 @@ export function MouseoverTooltipContent({
}, [openCallback])
const close = useCallback(() => setShow(false), [setShow])
return (
<TooltipContent {...rest} show={show} content={content}>
<TooltipContent {...rest} show={show} content={disableHover ? null : content}>
<div
style={{ display: 'inline-block', lineHeight: 0, padding: '0.25rem' }}
onMouseEnter={open}

View File

@@ -13,7 +13,7 @@ import Circle from '../../assets/images/blue-loader.svg'
import MetaMaskLogo from '../../assets/images/metamask.png'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink } from '../../theme'
import { CloseIcon, CustomLightSpinner } from '../../theme/components'
import { CloseIcon, CustomLightSpinner } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { TransactionSummary } from '../AccountDetails/TransactionSummary'
import { ButtonLight, ButtonPrimary } from '../Button'
@@ -284,11 +284,11 @@ function L2Content({
</Text>
</ExternalLink>
) : (
<div style={{ height: '17px' }}></div>
<div style={{ height: '17px' }} />
)}
<Text color={theme.text3} style={{ margin: '20px 0 0 0' }} fontSize={'14px'}>
{!secondsToConfirm ? (
<div style={{ height: '24px' }}></div>
<div style={{ height: '24px' }} />
) : (
<div>
<Trans>Transaction completed in </Trans>

View File

@@ -1,14 +1,15 @@
import { t, Trans } from '@lingui/macro'
import { Trans } from '@lingui/macro'
import { Percent } from '@uniswap/sdk-core'
import { L2_CHAIN_IDS } from 'constants/chains'
import { DEFAULT_DEADLINE_FROM_NOW } from 'constants/misc'
import { useActiveWeb3React } from 'hooks/web3'
import ms from 'ms.macro'
import { darken } from 'polished'
import { useContext, useState } from 'react'
import { useSetUserSlippageTolerance, useUserSlippageTolerance, useUserTransactionTTL } from 'state/user/hooks'
import styled, { ThemeContext } from 'styled-components/macro'
import { TYPE } from '../../theme'
import { ThemedText } from '../../theme'
import { AutoColumn } from '../Column'
import QuestionHelper from '../QuestionHelper'
import { RowBetween, RowFixed } from '../Row'
@@ -85,7 +86,7 @@ const OptionCustom = styled(FancyButton)<{ active?: boolean; warning?: boolean }
const SlippageEmojiContainer = styled.span`
color: #f3841e;
${({ theme }) => theme.mediaWidth.upToSmall`
display: none;
display: none;
`}
`
@@ -93,6 +94,8 @@ interface TransactionSettingsProps {
placeholderSlippage: Percent // varies according to the context in which the settings dialog is placed
}
const THREE_DAYS_IN_SECONDS = ms`3 days` / 1000
export default function TransactionSettings({ placeholderSlippage }: TransactionSettingsProps) {
const { chainId } = useActiveWeb3React()
const theme = useContext(ThemeContext)
@@ -142,7 +145,7 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction
} else {
try {
const parsed: number = Math.floor(Number.parseFloat(value) * 60)
if (!Number.isInteger(parsed) || parsed < 60 || parsed > 180 * 60) {
if (!Number.isInteger(parsed) || parsed < 60 || parsed > THREE_DAYS_IN_SECONDS) {
setDeadlineError(DeadlineError.InvalidInput)
} else {
setDeadline(parsed)
@@ -160,9 +163,9 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction
<AutoColumn gap="md">
<AutoColumn gap="sm">
<RowFixed>
<TYPE.black fontWeight={400} fontSize={14} color={theme.text2}>
<ThemedText.Black fontWeight={400} fontSize={14} color={theme.text2}>
<Trans>Slippage tolerance</Trans>
</TYPE.black>
</ThemedText.Black>
<QuestionHelper
text={
<Trans>Your transaction will revert if the price changes unfavorably by more than this percentage.</Trans>
@@ -229,11 +232,11 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction
{showCustomDeadlineRow && (
<AutoColumn gap="sm">
<RowFixed>
<TYPE.black fontSize={14} fontWeight={400} color={theme.text2}>
<ThemedText.Black fontSize={14} fontWeight={400} color={theme.text2}>
<Trans>Transaction deadline</Trans>
</TYPE.black>
</ThemedText.Black>
<QuestionHelper
text={t`Your transaction will revert if it is pending for more than this period of time.`}
text={<Trans>Your transaction will revert if it is pending for more than this period of time.</Trans>}
/>
</RowFixed>
<RowFixed>
@@ -255,9 +258,9 @@ export default function TransactionSettings({ placeholderSlippage }: Transaction
color={deadlineError ? 'red' : ''}
/>
</OptionCustom>
<TYPE.body style={{ paddingLeft: '8px' }} fontSize={14}>
<ThemedText.Body style={{ paddingLeft: '8px' }} fontSize={14}>
<Trans>minutes</Trans>
</TYPE.body>
</ThemedText.Body>
</RowFixed>
</AutoColumn>
)}

View File

@@ -2,8 +2,12 @@ import { Trans } from '@lingui/macro'
import { AbstractConnector } from '@web3-react/abstract-connector'
import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core'
import { WalletConnectConnector } from '@web3-react/walletconnect-connector'
import { AutoRow } from 'components/Row'
import { AutoColumn } from 'components/Column'
import { PrivacyPolicy } from 'components/PrivacyPolicy'
import Row, { AutoRow, RowBetween } from 'components/Row'
import { useWalletConnectMonitoringEventCallback } from 'hooks/useMonitoringEventCallback'
import { useEffect, useState } from 'react'
import { ArrowLeft, ArrowRight, Info } from 'react-feather'
import ReactGA from 'react-ga'
import styled from 'styled-components/macro'
@@ -13,12 +17,12 @@ import { fortmatic, injected, portis } from '../../connectors'
import { OVERLAY_READY } from '../../connectors/Fortmatic'
import { SUPPORTED_WALLETS } from '../../constants/wallet'
import usePrevious from '../../hooks/usePrevious'
import { ApplicationModal } from '../../state/application/actions'
import { useModalOpen, useWalletModalToggle } from '../../state/application/hooks'
import { ExternalLink, TYPE } from '../../theme'
import { ApplicationModal } from '../../state/application/reducer'
import { ExternalLink, ThemedText } from '../../theme'
import { isMobile } from '../../utils/userAgent'
import AccountDetails from '../AccountDetails'
import { LightCard } from '../Card'
import Card, { LightCard } from '../Card'
import Modal from '../Modal'
import Option from './Option'
import PendingView from './PendingView'
@@ -105,11 +109,22 @@ const HoverText = styled.div`
}
`
const LinkCard = styled(Card)`
background-color: ${({ theme }) => theme.bg1};
color: ${({ theme }) => theme.text3};
:hover {
cursor: pointer;
filter: brightness(0.9);
}
`
const WALLET_VIEWS = {
OPTIONS: 'options',
OPTIONS_SECONDARY: 'options_secondary',
ACCOUNT: 'account',
PENDING: 'pending',
LEGAL: 'legal',
}
export default function WalletModal({
@@ -125,6 +140,7 @@ export default function WalletModal({
const { active, account, connector, activate, error } = useWeb3React()
const [walletView, setWalletView] = useState(WALLET_VIEWS.ACCOUNT)
const previousWalletView = usePrevious(walletView)
const [pendingWallet, setPendingWallet] = useState<AbstractConnector | undefined>()
@@ -135,6 +151,8 @@ export default function WalletModal({
const previousAccount = usePrevious(account)
const logMonitoringEvent = useWalletConnectMonitoringEventCallback()
// close on connection, when logged out before
useEffect(() => {
if (account && !previousAccount && walletModalOpen) {
@@ -177,18 +195,23 @@ export default function WalletModal({
setWalletView(WALLET_VIEWS.PENDING)
// if the connector is walletconnect and the user has already tried to connect, manually reset the connector
if (connector instanceof WalletConnectConnector && connector.walletConnectProvider?.wc?.uri) {
if (connector instanceof WalletConnectConnector) {
connector.walletConnectProvider = undefined
}
connector &&
activate(connector, undefined, true).catch((error) => {
if (error instanceof UnsupportedChainIdError) {
activate(connector) // a little janky...can't use setError because the connector isn't set
} else {
setPendingError(true)
}
})
activate(connector, undefined, true)
.then(async () => {
const walletAddress = await connector.getAccount()
logMonitoringEvent({ walletAddress })
})
.catch((error) => {
if (error instanceof UnsupportedChainIdError) {
activate(connector) // a little janky...can't use setError because the connector isn't set
} else {
setPendingError(true)
}
})
}
// close wallet modal if fortmatic modal is active
@@ -306,6 +329,30 @@ export default function WalletModal({
</UpperSection>
)
}
if (walletView === WALLET_VIEWS.LEGAL) {
return (
<UpperSection>
<HeaderRow>
<HoverText
onClick={() => {
setWalletView(
(previousWalletView === WALLET_VIEWS.LEGAL ? WALLET_VIEWS.ACCOUNT : previousWalletView) ??
WALLET_VIEWS.ACCOUNT
)
}}
>
<ArrowLeft />
</HoverText>
<Row justify="center">
<ThemedText.MediumHeader>
<Trans>Legal & Privacy</Trans>
</ThemedText.MediumHeader>
</Row>
</HeaderRow>
<PrivacyPolicy />
</UpperSection>
)
}
if (account && walletView === WALLET_VIEWS.ACCOUNT) {
return (
<AccountDetails
@@ -330,40 +377,53 @@ export default function WalletModal({
setWalletView(WALLET_VIEWS.ACCOUNT)
}}
>
<Trans>Back</Trans>
<ArrowLeft />
</HoverText>
</HeaderRow>
) : (
<HeaderRow>
<HoverText>
<Trans>Connect to a wallet</Trans>
<Trans>Connect a wallet</Trans>
</HoverText>
</HeaderRow>
)}
<ContentWrapper>
<LightCard style={{ marginBottom: '16px' }}>
<AutoRow style={{ flexWrap: 'nowrap' }}>
<TYPE.main fontSize={14}>
<Trans>
By connecting a wallet, you agree to Uniswap Labs{' '}
<ExternalLink href="https://uniswap.org/terms-of-service/">Terms of Service</ExternalLink> and
acknowledge that you have read and understand the{' '}
<ExternalLink href="https://uniswap.org/disclaimer/">Uniswap protocol disclaimer</ExternalLink>.
</Trans>
</TYPE.main>
</AutoRow>
</LightCard>
{walletView === WALLET_VIEWS.PENDING ? (
<PendingView
connector={pendingWallet}
error={pendingError}
setPendingError={setPendingError}
tryActivation={tryActivation}
/>
) : (
<OptionGrid>{getOptions()}</OptionGrid>
)}
<AutoColumn gap="16px">
<LightCard>
<AutoRow style={{ flexWrap: 'nowrap' }}>
<ThemedText.Black fontSize={14}>
<Trans>
By connecting a wallet, you agree to Uniswap Labs{' '}
<ExternalLink href="https://uniswap.org/terms-of-service/">Terms of Service</ExternalLink> and
acknowledge that you have read and understand the Uniswap{' '}
<ExternalLink href="https://uniswap.org/disclaimer/">Protocol Disclaimer</ExternalLink>.
</Trans>
</ThemedText.Black>
</AutoRow>
</LightCard>
{walletView === WALLET_VIEWS.PENDING ? (
<PendingView
connector={pendingWallet}
error={pendingError}
setPendingError={setPendingError}
tryActivation={tryActivation}
/>
) : (
<OptionGrid>{getOptions()}</OptionGrid>
)}
<LinkCard padding=".5rem" $borderRadius=".75rem" onClick={() => setWalletView(WALLET_VIEWS.LEGAL)}>
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<ThemedText.Label fontSize={14}>
<Trans>How this app uses APIs</Trans>
</ThemedText.Label>
</AutoRow>
<ArrowRight size={16} />
</RowBetween>
</LinkCard>
</AutoColumn>
</ContentWrapper>
</UpperSection>
)

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro'
import { AbstractConnector } from '@web3-react/abstract-connector'
import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core'
@@ -5,12 +6,8 @@ import { darken } from 'polished'
import { useMemo } from 'react'
import { Activity } from 'react-feather'
import styled, { css } from 'styled-components/macro'
import { Connector } from 'widgets-web3-react/types'
import CoinbaseWalletIcon from '../../assets/images/coinbaseWalletIcon.svg'
import FortmaticIcon from '../../assets/images/fortmaticIcon.png'
import PortisIcon from '../../assets/images/portisIcon.png'
import WalletConnectIcon from '../../assets/images/walletConnectIcon.svg'
import { fortmatic, injected, portis, walletconnect, walletlink } from '../../connectors'
import { NetworkContextName } from '../../constants/misc'
import useENSName from '../../hooks/useENSName'
import { useHasSocks } from '../../hooks/useSocksBalance'
@@ -19,7 +16,7 @@ import { isTransactionRecent, useAllTransactions } from '../../state/transaction
import { TransactionDetails } from '../../state/transactions/reducer'
import { shortenAddress } from '../../utils'
import { ButtonSecondary } from '../Button'
import Identicon from '../Identicon'
import StatusIcon from '../Identicon/StatusIcon'
import Loader from '../Loader'
import { RowBetween } from '../Row'
import WalletModal from '../WalletModal'
@@ -39,9 +36,12 @@ const Web3StatusGeneric = styled(ButtonSecondary)`
width: 100%;
align-items: center;
padding: 0.5rem;
border-radius: 12px;
border-radius: 14px;
cursor: pointer;
user-select: none;
height: 36px;
margin-right: 2px;
margin-left: 1px;
:focus {
outline: none;
}
@@ -86,7 +86,7 @@ const Web3StatusConnect = styled(Web3StatusGeneric)<{ faded?: boolean }>`
`
const Web3StatusConnected = styled(Web3StatusGeneric)<{ pending?: boolean }>`
background-color: ${({ pending, theme }) => (pending ? theme.primary1 : theme.bg0)};
background-color: ${({ pending, theme }) => (pending ? theme.primary1 : theme.bg1)};
border: 1px solid ${({ pending, theme }) => (pending ? theme.primary1 : theme.bg1)};
color: ${({ pending, theme }) => (pending ? theme.white : theme.text1)};
font-weight: 500;
@@ -131,36 +131,12 @@ function Sock() {
)
}
// eslint-disable-next-line react/prop-types
function StatusIcon({ connector }: { connector: AbstractConnector }) {
if (connector === injected) {
return <Identicon />
} else if (connector === walletconnect) {
return (
<IconWrapper size={16}>
<img src={WalletConnectIcon} alt={'WalletConnect'} />
</IconWrapper>
)
} else if (connector === walletlink) {
return (
<IconWrapper size={16}>
<img src={CoinbaseWalletIcon} alt={'CoinbaseWallet'} />
</IconWrapper>
)
} else if (connector === fortmatic) {
return (
<IconWrapper size={16}>
<img src={FortmaticIcon} alt={'Fortmatic'} />
</IconWrapper>
)
} else if (connector === portis) {
return (
<IconWrapper size={16}>
<img src={PortisIcon} alt={'Portis'} />
</IconWrapper>
)
}
return null
function WrappedStatusIcon({ connector }: { connector: AbstractConnector | Connector }) {
return (
<IconWrapper size={16}>
<StatusIcon connector={connector} />
</IconWrapper>
)
}
function Web3StatusInner() {
@@ -197,7 +173,7 @@ function Web3StatusInner() {
<Text>{ENSName || shortenAddress(account)}</Text>
</>
)}
{!hasPendingTransactions && connector && <StatusIcon connector={connector} />}
{!hasPendingTransactions && connector && <WrappedStatusIcon connector={connector} />}
</Web3StatusConnected>
)
} else if (error) {
@@ -211,7 +187,7 @@ function Web3StatusInner() {
return (
<Web3StatusConnect id="connect-wallet" onClick={toggleWalletModal} faded={!account}>
<Text>
<Trans>Connect to a wallet</Trans>
<Trans>Connect Wallet</Trans>
</Text>
</Web3StatusConnect>
)

View File

@@ -24,7 +24,8 @@ export default function GoogleAnalyticsReporter({ location: { pathname, search }
const { chainId } = useActiveWeb3React()
useEffect(() => {
ReactGA.set({ ['Chain ID']: chainId ?? 0 })
// cd1 - custom dimension 1 - chainId
ReactGA.set({ cd1: chainId ?? 0 })
}, [chainId])
useEffect(() => {

View File

@@ -11,7 +11,7 @@ import useENS from '../../hooks/useENS'
import { useActiveWeb3React } from '../../hooks/web3'
import { useClaimCallback, useUserHasAvailableClaim, useUserUnclaimedAmount } from '../../state/claim/hooks'
import { useIsTransactionPending } from '../../state/transactions/hooks'
import { CloseIcon, CustomLightSpinner, ExternalLink, TYPE, UniTokenAnimated } from '../../theme'
import { CloseIcon, CustomLightSpinner, ExternalLink, ThemedText, UniTokenAnimated } from '../../theme'
import { shortenAddress } from '../../utils'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import AddressInputPanel from '../AddressInputPanel'
@@ -105,29 +105,29 @@ export default function AddressClaimModal({ isOpen, onDismiss }: { isOpen: boole
<CardNoise />
<CardSection gap="md">
<RowBetween>
<TYPE.white fontWeight={500}>
<ThemedText.White fontWeight={500}>
<Trans>Claim UNI Token</Trans>
</TYPE.white>
</ThemedText.White>
<CloseIcon onClick={wrappedOnDismiss} style={{ zIndex: 99 }} stroke="white" />
</RowBetween>
<TYPE.white fontWeight={700} fontSize={36}>
<ThemedText.White fontWeight={700} fontSize={36}>
<Trans>{unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI</Trans>
</TYPE.white>
</ThemedText.White>
</CardSection>
<Break />
</ModalUpper>
<AutoColumn gap="md" style={{ padding: '1rem', paddingTop: '0' }} justify="center">
<TYPE.subHeader fontWeight={500}>
<ThemedText.SubHeader fontWeight={500}>
<Trans>
Enter an address to trigger a UNI claim. If the address has any claimable UNI it will be sent to them on
submission.
</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
<AddressInputPanel value={typed} onChange={handleRecipientType} />
{parsedAddress && !hasAvailableClaim && (
<TYPE.error error={true}>
<ThemedText.Error error={true}>
<Trans>Address has no available claim</Trans>
</TYPE.error>
</ThemedText.Error>
)}
<ButtonPrimary
disabled={!isAddress(parsedAddress ?? '') || !hasAvailableClaim}
@@ -159,23 +159,23 @@ export default function AddressClaimModal({ isOpen, onDismiss }: { isOpen: boole
</ConfirmedIcon>
<AutoColumn gap="100px" justify={'center'}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader fontWeight={600} color="black">
<ThemedText.LargeHeader fontWeight={600} color="black">
{claimConfirmed ? <Trans>Claimed</Trans> : <Trans>Claiming</Trans>}
</TYPE.largeHeader>
</ThemedText.LargeHeader>
{!claimConfirmed && (
<Text fontSize={36} color={'#ff007a'} fontWeight={800}>
<Trans>{unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI</Trans>
</Text>
)}
{parsedAddress && (
<TYPE.largeHeader fontWeight={600} color="black">
<ThemedText.LargeHeader fontWeight={600} color="black">
<Trans>for {shortenAddress(parsedAddress)}</Trans>
</TYPE.largeHeader>
</ThemedText.LargeHeader>
)}
</AutoColumn>
{claimConfirmed && (
<>
<TYPE.subHeader fontWeight={500} color="black">
<ThemedText.SubHeader fontWeight={500} color="black">
<span role="img" aria-label="party-hat">
🎉{' '}
</span>
@@ -183,13 +183,13 @@ export default function AddressClaimModal({ isOpen, onDismiss }: { isOpen: boole
<span role="img" aria-label="party-hat">
🎉
</span>
</TYPE.subHeader>
</ThemedText.SubHeader>
</>
)}
{attempting && !hash && (
<TYPE.subHeader color="black">
<ThemedText.SubHeader color="black">
<Trans>Confirm this transaction in your wallet</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
)}
{attempting && hash && !claimConfirmed && chainId && hash && (
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)} style={{ zIndex: 99 }}>

View File

@@ -9,11 +9,11 @@ import styled from 'styled-components/macro'
import Circle from '../../assets/images/blue-loader.svg'
import tokenLogo from '../../assets/images/token-logo.png'
import { useActiveWeb3React } from '../../hooks/web3'
import { ApplicationModal } from '../../state/application/actions'
import { useModalOpen, useToggleSelfClaimModal } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { useClaimCallback, useUserClaimData, useUserUnclaimedAmount } from '../../state/claim/hooks'
import { useUserHasSubmittedClaim } from '../../state/transactions/hooks'
import { CloseIcon, CustomLightSpinner, ExternalLink, TYPE, UniTokenAnimated } from '../../theme'
import { CloseIcon, CustomLightSpinner, ExternalLink, ThemedText, UniTokenAnimated } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { ButtonPrimary } from '../Button'
import { AutoColumn, ColumnCenter } from '../Column'
@@ -100,63 +100,63 @@ export default function ClaimModal() {
<CardNoise />
<CardSection gap="md">
<RowBetween>
<TYPE.white fontWeight={500}>
<ThemedText.White fontWeight={500}>
<Trans>Claim UNI</Trans>
</TYPE.white>
</ThemedText.White>
<CloseIcon onClick={toggleClaimModal} style={{ zIndex: 99 }} color="white" />
</RowBetween>
<TYPE.white fontWeight={700} fontSize={36}>
<ThemedText.White fontWeight={700} fontSize={36}>
<Trans>{unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI</Trans>
</TYPE.white>
</ThemedText.White>
</CardSection>
<Break />
<CardSection gap="sm">
{userClaimData?.flags?.isSOCKS && (
<RowBetween>
<TYPE.subHeader color="white">SOCKS</TYPE.subHeader>
<TYPE.subHeader color="white">
<ThemedText.SubHeader color="white">SOCKS</ThemedText.SubHeader>
<ThemedText.SubHeader color="white">
<Trans>{SOCKS_AMOUNT} UNI</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</RowBetween>
)}
{userClaimData?.flags?.isLP &&
unclaimedAmount &&
JSBI.greaterThanOrEqual(unclaimedAmount.quotient, nonLPAmount) && (
<RowBetween>
<TYPE.subHeader color="white">
<ThemedText.SubHeader color="white">
<Trans>Liquidity</Trans>
</TYPE.subHeader>
<TYPE.subHeader color="white">
</ThemedText.SubHeader>
<ThemedText.SubHeader color="white">
<Trans>
{unclaimedAmount
.subtract(CurrencyAmount.fromRawAmount(unclaimedAmount.currency, nonLPAmount))
.toFixed(0, { groupSeparator: ',' })}{' '}
UNI
</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</RowBetween>
)}
{userClaimData?.flags?.isUser && (
<RowBetween>
<TYPE.subHeader color="white">
<ThemedText.SubHeader color="white">
<Trans>User</Trans>
</TYPE.subHeader>
<TYPE.subHeader color="white">
</ThemedText.SubHeader>
<ThemedText.SubHeader color="white">
<Trans>{USER_AMOUNT} UNI</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</RowBetween>
)}
</CardSection>
</ModalUpper>
<AutoColumn gap="md" style={{ padding: '1rem', paddingTop: '0' }} justify="center">
<TYPE.subHeader fontWeight={500}>
<ThemedText.SubHeader fontWeight={500}>
<Trans>
As a member of the Uniswap community you may claim UNI to be used for voting and governance.
<br />
<br />
<ExternalLink href="https://uniswap.org/blog/uni">Read more about UNI</ExternalLink>
</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
<ButtonPrimary
disabled={!isAddress(account ?? '')}
padding="16px 16px"
@@ -187,9 +187,9 @@ export default function ClaimModal() {
</ConfirmedIcon>
<AutoColumn gap="100px" justify={'center'}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader fontWeight={600} color="black">
<ThemedText.LargeHeader fontWeight={600} color="black">
{claimConfirmed ? <Trans>Claimed!</Trans> : <Trans>Claiming</Trans>}
</TYPE.largeHeader>
</ThemedText.LargeHeader>
{!claimConfirmed && (
<Text fontSize={36} color={'#ff007a'} fontWeight={800}>
<Trans>{unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI</Trans>
@@ -198,7 +198,7 @@ export default function ClaimModal() {
</AutoColumn>
{claimConfirmed && (
<>
<TYPE.subHeader fontWeight={500} color="black">
<ThemedText.SubHeader fontWeight={500} color="black">
<Trans>
<span role="img" aria-label="party-hat">
🎉{' '}
@@ -208,13 +208,13 @@ export default function ClaimModal() {
🎉
</span>
</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
</>
)}
{attempting && !claimSubmitted && (
<TYPE.subHeader color="black">
<ThemedText.SubHeader color="black">
<Trans>Confirm this transaction in your wallet</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
)}
{attempting && claimSubmitted && !claimConfirmed && chainId && claimTxn?.hash && (
<ExternalLink

View File

@@ -1,6 +1,6 @@
import { TransactionResponse } from '@ethersproject/providers'
import { t, Trans } from '@lingui/macro'
import { useState } from 'react'
import { Trans } from '@lingui/macro'
import { ReactNode, useState } from 'react'
import styled from 'styled-components/macro'
import { useStakingContract } from '../../hooks/useContract'
@@ -8,7 +8,7 @@ import { useActiveWeb3React } from '../../hooks/web3'
import { StakingInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'
import { CloseIcon, TYPE } from '../../theme'
import { CloseIcon, ThemedText } from '../../theme'
import { ButtonError } from '../Button'
import { AutoColumn } from '../Column'
import Modal from '../Modal'
@@ -61,12 +61,12 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta
}
}
let error: string | undefined
let error: ReactNode | undefined
if (!account) {
error = t`Connect Wallet`
error = <Trans>Connect Wallet</Trans>
}
if (!stakingInfo?.stakedAmount) {
error = error ?? t`Enter an amount`
error = error ?? <Trans>Enter an amount</Trans>
}
return (
@@ -74,24 +74,24 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta
{!attempting && !hash && (
<ContentWrapper gap="lg">
<RowBetween>
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Claim</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<CloseIcon onClick={wrappedOnDismiss} />
</RowBetween>
{stakingInfo?.earnedAmount && (
<AutoColumn justify="center" gap="md">
<TYPE.body fontWeight={600} fontSize={36}>
<ThemedText.Body fontWeight={600} fontSize={36}>
{stakingInfo?.earnedAmount?.toSignificant(6)}
</TYPE.body>
<TYPE.body>
</ThemedText.Body>
<ThemedText.Body>
<Trans>Unclaimed UNI</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
)}
<TYPE.subHeader style={{ textAlign: 'center' }}>
<ThemedText.SubHeader style={{ textAlign: 'center' }}>
<Trans>When you claim without withdrawing your liquidity remains in the mining pool.</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
<ButtonError disabled={!!error} error={!!error && !!stakingInfo?.stakedAmount} onClick={onClaimReward}>
{error ?? <Trans>Claim</Trans>}
</ButtonError>
@@ -100,21 +100,21 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta
{attempting && !hash && (
<LoadingView onDismiss={wrappedOnDismiss}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.body fontSize={20}>
<ThemedText.Body fontSize={20}>
<Trans>Claiming {stakingInfo?.earnedAmount?.toSignificant(6)} UNI</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</LoadingView>
)}
{hash && (
<SubmittedView onDismiss={wrappedOnDismiss} hash={hash}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Transaction Submitted</Trans>
</TYPE.largeHeader>
<TYPE.body fontSize={20}>
</ThemedText.LargeHeader>
<ThemedText.Body fontSize={20}>
<Trans>Claimed UNI!</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</SubmittedView>
)}

View File

@@ -9,7 +9,7 @@ import { useTotalSupply } from '../../hooks/useTotalSupply'
import useUSDCPrice from '../../hooks/useUSDCPrice'
import { useV2Pair } from '../../hooks/useV2Pairs'
import { StakingInfo } from '../../state/stake/hooks'
import { StyledInternalLink, TYPE } from '../../theme'
import { StyledInternalLink, ThemedText } from '../../theme'
import { currencyId } from '../../utils/currencyId'
import { unwrappedToken } from '../../utils/unwrappedToken'
import { ButtonPrimary } from '../Button'
@@ -115,9 +115,9 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
<TopSection>
<DoubleCurrencyLogo currency0={currency0} currency1={currency1} size={24} />
<TYPE.white fontWeight={600} fontSize={24} style={{ marginLeft: '8px' }}>
<ThemedText.White fontWeight={600} fontSize={24} style={{ marginLeft: '8px' }}>
{currency0.symbol}-{currency1.symbol}
</TYPE.white>
</ThemedText.White>
<StyledInternalLink to={`/uni/${currencyId(currency0)}/${currencyId(currency1)}`} style={{ width: '100%' }}>
<ButtonPrimary padding="8px" $borderRadius="8px">
@@ -128,22 +128,22 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
<StatContainer>
<RowBetween>
<TYPE.white>
<ThemedText.White>
<Trans>Total deposited</Trans>
</TYPE.white>
<TYPE.white>
</ThemedText.White>
<ThemedText.White>
{valueOfTotalStakedAmountInUSDC ? (
<Trans>${valueOfTotalStakedAmountInUSDC.toFixed(0, { groupSeparator: ',' })}</Trans>
) : (
<Trans>{valueOfTotalStakedAmountInWETH?.toSignificant(4, { groupSeparator: ',' }) ?? '-'} ETH</Trans>
)}
</TYPE.white>
</ThemedText.White>
</RowBetween>
<RowBetween>
<TYPE.white>
<ThemedText.White>
<Trans>Pool rate</Trans>
</TYPE.white>
<TYPE.white>
</ThemedText.White>
<ThemedText.White>
{stakingInfo ? (
stakingInfo.active ? (
<Trans>
@@ -156,7 +156,7 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
) : (
'-'
)}
</TYPE.white>
</ThemedText.White>
</RowBetween>
</StatContainer>
@@ -164,13 +164,13 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
<>
<Break />
<BottomSection showBackground={true}>
<TYPE.black color={'white'} fontWeight={500}>
<ThemedText.Black color={'white'} fontWeight={500}>
<span>
<Trans>Your rate</Trans>
</span>
</TYPE.black>
</ThemedText.Black>
<TYPE.black style={{ textAlign: 'right' }} color={'white'} fontWeight={500}>
<ThemedText.Black style={{ textAlign: 'right' }} color={'white'} fontWeight={500}>
<span role="img" aria-label="wizard-icon" style={{ marginRight: '0.5rem' }}>
</span>
@@ -188,7 +188,7 @@ export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo })
) : (
'-'
)}
</TYPE.black>
</ThemedText.Black>
</BottomSection>
</>
)}

View File

@@ -13,7 +13,7 @@ import { useActiveWeb3React } from '../../hooks/web3'
import { StakingInfo, useDerivedStakeInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'
import { CloseIcon, TYPE } from '../../theme'
import { CloseIcon, ThemedText } from '../../theme'
import { formatCurrencyAmount } from '../../utils/formatCurrencyAmount'
import { maxAmountSpend } from '../../utils/maxAmountSpend'
import { ButtonConfirmed, ButtonError } from '../Button'
@@ -159,9 +159,9 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
{!attempting && !hash && (
<ContentWrapper gap="lg">
<RowBetween>
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Deposit</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<CloseIcon onClick={wrappedOnDismiss} />
</RowBetween>
<CurrencyInputPanel
@@ -178,19 +178,19 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
<HypotheticalRewardRate dim={!hypotheticalRewardRate.greaterThan('0')}>
<div>
<TYPE.black fontWeight={600}>
<ThemedText.Black fontWeight={600}>
<Trans>Weekly Rewards</Trans>
</TYPE.black>
</ThemedText.Black>
</div>
<TYPE.black>
<ThemedText.Black>
<Trans>
{hypotheticalRewardRate
.multiply((60 * 60 * 24 * 7).toString())
.toSignificant(4, { groupSeparator: ',' })}{' '}
UNI / week
</Trans>
</TYPE.black>
</ThemedText.Black>
</HypotheticalRewardRate>
<RowBetween>
@@ -216,24 +216,24 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
{attempting && !hash && (
<LoadingView onDismiss={wrappedOnDismiss}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Depositing Liquidity</Trans>
</TYPE.largeHeader>
<TYPE.body fontSize={20}>
</ThemedText.LargeHeader>
<ThemedText.Body fontSize={20}>
<Trans>{parsedAmount?.toSignificant(4)} UNI-V2</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</LoadingView>
)}
{attempting && hash && (
<SubmittedView onDismiss={wrappedOnDismiss} hash={hash}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Transaction Submitted</Trans>
</TYPE.largeHeader>
<TYPE.body fontSize={20}>
</ThemedText.LargeHeader>
<ThemedText.Body fontSize={20}>
<Trans>Deposited {parsedAmount?.toSignificant(4)} UNI-V2</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</SubmittedView>
)}

View File

@@ -1,6 +1,6 @@
import { TransactionResponse } from '@ethersproject/providers'
import { t, Trans } from '@lingui/macro'
import { useState } from 'react'
import { Trans } from '@lingui/macro'
import { ReactNode, useState } from 'react'
import styled from 'styled-components/macro'
import { useStakingContract } from '../../hooks/useContract'
@@ -8,7 +8,7 @@ import { useActiveWeb3React } from '../../hooks/web3'
import { StakingInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'
import { CloseIcon, TYPE } from '../../theme'
import { CloseIcon, ThemedText } from '../../theme'
import { ButtonError } from '../Button'
import { AutoColumn } from '../Column'
import FormattedCurrencyAmount from '../FormattedCurrencyAmount'
@@ -63,12 +63,12 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki
}
}
let error: string | undefined
let error: ReactNode | undefined
if (!account) {
error = t`Connect a wallet`
error = <Trans>Connect a wallet</Trans>
}
if (!stakingInfo?.stakedAmount) {
error = error ?? t`Enter an amount`
error = error ?? <Trans>Enter an amount</Trans>
}
return (
@@ -76,34 +76,34 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki
{!attempting && !hash && (
<ContentWrapper gap="lg">
<RowBetween>
<TYPE.mediumHeader>
<ThemedText.MediumHeader>
<Trans>Withdraw</Trans>
</TYPE.mediumHeader>
</ThemedText.MediumHeader>
<CloseIcon onClick={wrappedOndismiss} />
</RowBetween>
{stakingInfo?.stakedAmount && (
<AutoColumn justify="center" gap="md">
<TYPE.body fontWeight={600} fontSize={36}>
<ThemedText.Body fontWeight={600} fontSize={36}>
{<FormattedCurrencyAmount currencyAmount={stakingInfo.stakedAmount} />}
</TYPE.body>
<TYPE.body>
</ThemedText.Body>
<ThemedText.Body>
<Trans>Deposited liquidity:</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
)}
{stakingInfo?.earnedAmount && (
<AutoColumn justify="center" gap="md">
<TYPE.body fontWeight={600} fontSize={36}>
<ThemedText.Body fontWeight={600} fontSize={36}>
{<FormattedCurrencyAmount currencyAmount={stakingInfo?.earnedAmount} />}
</TYPE.body>
<TYPE.body>
</ThemedText.Body>
<ThemedText.Body>
<Trans>Unclaimed UNI</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
)}
<TYPE.subHeader style={{ textAlign: 'center' }}>
<ThemedText.SubHeader style={{ textAlign: 'center' }}>
<Trans>When you withdraw, your UNI is claimed and your liquidity is removed from the mining pool.</Trans>
</TYPE.subHeader>
</ThemedText.SubHeader>
<ButtonError disabled={!!error} error={!!error && !!stakingInfo?.stakedAmount} onClick={onWithdraw}>
{error ?? <Trans>Withdraw & Claim</Trans>}
</ButtonError>
@@ -112,27 +112,27 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki
{attempting && !hash && (
<LoadingView onDismiss={wrappedOndismiss}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.body fontSize={20}>
<ThemedText.Body fontSize={20}>
<Trans>Withdrawing {stakingInfo?.stakedAmount?.toSignificant(4)} UNI-V2</Trans>
</TYPE.body>
<TYPE.body fontSize={20}>
</ThemedText.Body>
<ThemedText.Body fontSize={20}>
<Trans>Claiming {stakingInfo?.earnedAmount?.toSignificant(4)} UNI</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</LoadingView>
)}
{hash && (
<SubmittedView onDismiss={wrappedOndismiss} hash={hash}>
<AutoColumn gap="12px" justify={'center'}>
<TYPE.largeHeader>
<ThemedText.LargeHeader>
<Trans>Transaction Submitted</Trans>
</TYPE.largeHeader>
<TYPE.body fontSize={20}>
</ThemedText.LargeHeader>
<ThemedText.Body fontSize={20}>
<Trans>Withdrew UNI-V2!</Trans>
</TYPE.body>
<TYPE.body fontSize={20}>
</ThemedText.Body>
<ThemedText.Body fontSize={20}>
<Trans>Claimed UNI!</Trans>
</TYPE.body>
</ThemedText.Body>
</AutoColumn>
</SubmittedView>
)}

View File

@@ -1,22 +1,28 @@
import { Trans } from '@lingui/macro'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import Card from 'components/Card'
import { LoadingRows } from 'components/Loader/styled'
import { useActiveWeb3React } from 'hooks/web3'
import { useContext, useMemo } from 'react'
import { ThemeContext } from 'styled-components/macro'
import { InterfaceTrade } from 'state/routing/types'
import styled, { ThemeContext } from 'styled-components/macro'
import { TYPE } from '../../theme'
import { Separator, ThemedText } from '../../theme'
import { computeRealizedLPFeePercent } from '../../utils/prices'
import { AutoColumn } from '../Column'
import { RowBetween, RowFixed } from '../Row'
import FormattedPriceImpact from './FormattedPriceImpact'
import { TransactionDetailsLabel } from './styleds'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from './GasEstimateBadge'
const StyledCard = styled(Card)`
padding: 0;
`
interface AdvancedSwapDetailsProps {
trade?: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
trade?: InterfaceTrade<Currency, Currency, TradeType>
allowedSlippage: Percent
syncing?: boolean
hideRouteDiagram?: boolean
}
function TextWithLoadingPlaceholder({
@@ -39,74 +45,78 @@ function TextWithLoadingPlaceholder({
export function AdvancedSwapDetails({ trade, allowedSlippage, syncing = false }: AdvancedSwapDetailsProps) {
const theme = useContext(ThemeContext)
const { chainId } = useActiveWeb3React()
const { realizedLPFee, priceImpact } = useMemo(() => {
if (!trade) return { realizedLPFee: undefined, priceImpact: undefined }
const { expectedOutputAmount, priceImpact } = useMemo(() => {
if (!trade) return { expectedOutputAmount: undefined, priceImpact: undefined }
const expectedOutputAmount = trade.outputAmount
const realizedLpFeePercent = computeRealizedLPFeePercent(trade)
const realizedLPFee = trade.inputAmount.multiply(realizedLpFeePercent)
const priceImpact = trade.priceImpact.subtract(realizedLpFeePercent)
return { priceImpact, realizedLPFee }
return { expectedOutputAmount, priceImpact }
}, [trade])
return !trade ? null : (
<AutoColumn gap="8px">
<TransactionDetailsLabel fontWeight={500} fontSize={14}>
<Trans>Transaction Details</Trans>
</TransactionDetailsLabel>
<RowBetween>
<RowFixed>
<TYPE.subHeader color={theme.text1}>
<Trans>Liquidity Provider Fee</Trans>
</TYPE.subHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={65}>
<TYPE.black textAlign="right" fontSize={14}>
{realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${realizedLPFee.currency.symbol}` : '-'}
</TYPE.black>
</TextWithLoadingPlaceholder>
</RowBetween>
<RowBetween>
<RowFixed>
<TYPE.subHeader color={theme.text1}>
<Trans>Price Impact</Trans>
</TYPE.subHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={50}>
<TYPE.black textAlign="right" fontSize={14}>
<FormattedPriceImpact priceImpact={priceImpact} />
</TYPE.black>
</TextWithLoadingPlaceholder>
</RowBetween>
<RowBetween>
<RowFixed>
<TYPE.subHeader color={theme.text1}>
<Trans>Allowed Slippage</Trans>
</TYPE.subHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={45}>
<TYPE.black textAlign="right" fontSize={14}>
{allowedSlippage.toFixed(2)}%
</TYPE.black>
</TextWithLoadingPlaceholder>
</RowBetween>
<RowBetween>
<RowFixed>
<TYPE.subHeader color={theme.text1}>
{trade.tradeType === TradeType.EXACT_INPUT ? <Trans>Minimum received</Trans> : <Trans>Maximum sent</Trans>}
</TYPE.subHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={70}>
<TYPE.black textAlign="right" fontSize={14}>
{trade.tradeType === TradeType.EXACT_INPUT
? `${trade.minimumAmountOut(allowedSlippage).toSignificant(6)} ${trade.outputAmount.currency.symbol}`
: `${trade.maximumAmountIn(allowedSlippage).toSignificant(6)} ${trade.inputAmount.currency.symbol}`}
</TYPE.black>
</TextWithLoadingPlaceholder>
</RowBetween>
</AutoColumn>
<StyledCard>
<AutoColumn gap="8px">
<RowBetween>
<RowFixed>
<ThemedText.SubHeader color={theme.text1}>
<Trans>Expected Output</Trans>
</ThemedText.SubHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={65}>
<ThemedText.Black textAlign="right" fontSize={14}>
{expectedOutputAmount
? `${expectedOutputAmount.toSignificant(6)} ${expectedOutputAmount.currency.symbol}`
: '-'}
</ThemedText.Black>
</TextWithLoadingPlaceholder>
</RowBetween>
<RowBetween>
<RowFixed>
<ThemedText.SubHeader color={theme.text1}>
<Trans>Price Impact</Trans>
</ThemedText.SubHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={50}>
<ThemedText.Black textAlign="right" fontSize={14}>
<FormattedPriceImpact priceImpact={priceImpact} />
</ThemedText.Black>
</TextWithLoadingPlaceholder>
</RowBetween>
<Separator />
<RowBetween>
<RowFixed style={{ marginRight: '20px' }}>
<ThemedText.SubHeader color={theme.text3}>
{trade.tradeType === TradeType.EXACT_INPUT ? (
<Trans>Minimum received</Trans>
) : (
<Trans>Maximum sent</Trans>
)}{' '}
<Trans>after slippage</Trans> ({allowedSlippage.toFixed(2)}%)
</ThemedText.SubHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={70}>
<ThemedText.Black textAlign="right" fontSize={14} color={theme.text3}>
{trade.tradeType === TradeType.EXACT_INPUT
? `${trade.minimumAmountOut(allowedSlippage).toSignificant(6)} ${trade.outputAmount.currency.symbol}`
: `${trade.maximumAmountIn(allowedSlippage).toSignificant(6)} ${trade.inputAmount.currency.symbol}`}
</ThemedText.Black>
</TextWithLoadingPlaceholder>
</RowBetween>
{!trade?.gasUseEstimateUSD || !chainId || !SUPPORTED_GAS_ESTIMATE_CHAIN_IDS.includes(chainId) ? null : (
<RowBetween>
<ThemedText.SubHeader color={theme.text3}>
<Trans>Network Fee</Trans>
</ThemedText.SubHeader>
<TextWithLoadingPlaceholder syncing={syncing} width={50}>
<ThemedText.Black textAlign="right" fontSize={14} color={theme.text3}>
~${trade.gasUseEstimateUSD.toFixed(2)}
</ThemedText.Black>
</TextWithLoadingPlaceholder>
</RowBetween>
)}
</AutoColumn>
</StyledCard>
)
}

View File

@@ -1,8 +1,8 @@
import { Trans } from '@lingui/macro'
import { Trade } from '@uniswap/router-sdk'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { ReactNode, useCallback, useMemo } from 'react'
import { InterfaceTrade } from 'state/routing/types'
import TransactionConfirmationModal, {
ConfirmationModalContent,
@@ -16,9 +16,7 @@ import SwapModalHeader from './SwapModalHeader'
* @param args either a pair of V2 trades or a pair of V3 trades
*/
function tradeMeaningfullyDiffers(
...args:
| [V2Trade<Currency, Currency, TradeType>, V2Trade<Currency, Currency, TradeType>]
| [V3Trade<Currency, Currency, TradeType>, V3Trade<Currency, Currency, TradeType>]
...args: [Trade<Currency, Currency, TradeType>, Trade<Currency, Currency, TradeType>]
): boolean {
const [tradeA, tradeB] = args
return (
@@ -44,8 +42,8 @@ export default function ConfirmSwapModal({
txHash,
}: {
isOpen: boolean
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined
originalTrade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | undefined
trade: InterfaceTrade<Currency, Currency, TradeType> | undefined
originalTrade: Trade<Currency, Currency, TradeType> | undefined
attemptingTxn: boolean
txHash: string | undefined
recipient: string | null
@@ -56,15 +54,7 @@ export default function ConfirmSwapModal({
onDismiss: () => void
}) {
const showAcceptChanges = useMemo(
() =>
Boolean(
(trade instanceof V2Trade &&
originalTrade instanceof V2Trade &&
tradeMeaningfullyDiffers(trade, originalTrade)) ||
(trade instanceof V3Trade &&
originalTrade instanceof V3Trade &&
tradeMeaningfullyDiffers(trade, originalTrade))
),
() => Boolean(trade && originalTrade && tradeMeaningfullyDiffers(trade, originalTrade)),
[originalTrade, trade]
)

Some files were not shown because too many files have changed in this diff Show More