Compare commits

...

114 Commits

Author SHA1 Message Date
Crowdin Bot
d1e0812684 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-26 03:53:51 +00:00
Zach Pomerantz
98e62b4f93 Revert "chore(i18n): synchronize translations from crowdin [skip ci]"
This reverts commit 9fb0d424c2.
2022-01-25 19:46:36 -08:00
Crowdin Bot
9fb0d424c2 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-26 01:31:09 +00:00
Zach Pomerantz
8d145b908e feat: pending approval ui (#3186)
* feat: track approval txs

* refactor: update transactions

* feat: pending approval ui

* chore: fix pending approval doc

* fix: clarify optimized trade

* fix: use relative path for data uri assets
2022-01-25 16:24:36 -08:00
Zach Pomerantz
c7633d910b refactor: track txs (#3185)
* feat: track approval txs

* refactor: update transactions

* chore: add ms to deps

* test: rm stale test

* fix: comment usage of trade for optimized trade
2022-01-25 18:55:27 -05:00
Crowdin Bot
1f89a46a3f chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-25 20:07:16 +00:00
Crowdin Bot
8d54b01878 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-25 19:07:17 +00:00
Zach Pomerantz
ffe334ccbf feat: update summary view with real values (#3179)
* refactor: isolate approval callback hooks

* fix: use approval callback from trade

* chore: pass optimized trade to summary

* start review screen UI updates

* chore: pass optimized trade to summary

* fix: pass Trade to summary

* remove uneeded value type

* remove uneeded styling

* code cleanup

* code styling, update props

* fix fixture bug, code style updates

* bug fix in details array

* update logic in details

Co-authored-by: ianlapham <ianlapham@gmail.com>
2022-01-25 13:48:52 -05:00
Zach Pomerantz
ffe2bd315e fix: track swap approvals (#3183)
* fix: track swap approvals

* fix: type ambiguous return value
2022-01-24 17:52:45 -08:00
Zach Pomerantz
cee4b8c77a fix: disable swap button w/o account (#3177)
* fix: disable swap button w/o account

* nit: indent less
2022-01-24 15:28:48 -08:00
Tina
3153db9f73 feat: add chainId (network) as url parameter (#3057)
* read from query param and change networks if necessary

* dont open network selector menu on url param change

* prompt network change when url changes

* keep url, network in sync

* use chain name instead of id in url param

* only prompt network switch if url chain doesnt match
2022-01-24 15:23:34 -08:00
Ian Lapham
bbdb5f3f56 feat: update slippage tolerance to use auto or custom (#3166)
* update slippage tolerance to use auto or custom

* remove attempted styling for other PR

* back out UI changes, small naming updates

* remove UI work

* small code style changes, fix typo

* update comment to doc comment
2022-01-24 17:56:12 -05:00
Crowdin Bot
7f9c56b68c chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-24 20:08:12 +00:00
Crowdin Bot
2b69974fdc chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-24 19:06:44 +00:00
Zach Pomerantz
5236065769 refactor: isolate approval callback hooks (#3172)
* refactor: isolate approval callback hooks

* fix: use approval callback from trade
2022-01-24 10:56:24 -08:00
Justin Domingue
52128a2dcd chore: reset local tick data state on input change (#3176) 2022-01-24 11:10:33 -05:00
Justin Domingue
c9642c6cd0 feat: use TickLens on chains where subgraph is not functional (#3149) 2022-01-24 09:12:07 -05:00
Crowdin Bot
b878d764e5 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-23 18:09:33 +00:00
Will Hennessy
6a4f067ac0 Display message if not mainnet (#3151) 2022-01-23 12:31:40 -05:00
Crowdin Bot
e9407bb6bd chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-22 15:07:19 +00:00
Crowdin Bot
8d822fd0e0 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-22 10:08:02 +00:00
Zach Pomerantz
6404ee6e0b fix: default tokens on chainId change only (#3169) 2022-01-21 13:14:50 -08:00
Crowdin Bot
8ac3ed1128 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-21 10:07:23 +00:00
Zach Pomerantz
b501974a76 feat: polish select (#3160)
* feat: filter selected currency from select

* test: use infura urls

* fix: load native with chain

* fix: use currencyId for key

* feat: switch currencies when selecting other

* fix: resolve merge conflict name
2022-01-20 16:15:23 -08:00
Zach Pomerantz
567fb0181c fix: chain mismatched currencies (#3163) 2022-01-20 16:12:42 -08:00
Crowdin Bot
8a37c427e6 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-21 00:11:38 +00:00
Ian Lapham
034b3e3e58 feat: Update swap state structure and attach to UI (#3155)
* refactor: mv settings state to own file

* chore: add default exports

* refactor: update swap state to match biz logic

* feat: copy biz logic to widgets

* Hook up UI to updated swap state

* fix: decimal inputs

* fix max slippage

* fix error in settings

* fix: typing errors

* revert: useBestTrade changes

* fix: use client side trade for widgets

* fix: exhaustive deps

* chore: add router-sdk

* fix: gate old web3 on widget env

* fix building errors

* update trade imports

* update hook naming for swap amount and currencies

* small changes

Co-authored-by: Zach Pomerantz <zzmp@uniswap.org>
2022-01-20 18:51:45 -05:00
Ian Lapham
053000e5fc fix: update address listt (#3159) 2022-01-20 14:50:27 -05:00
Crowdin Bot
b77e7deb49 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-20 03:06:53 +00:00
Crowdin Bot
c3321ae793 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-19 22:06:45 +00:00
Jordan Frankfurt
5dec0cf72b show wrong chain message instead of throwing on incorrect chain connection (#3153) 2022-01-19 15:52:41 -06:00
Zach Pomerantz
1efda07e7a refactor: mv try parse currency amount to lib utils (#3152) 2022-01-19 14:34:01 -05:00
Crowdin Bot
fd819260f9 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-19 16:11:52 +00:00
Jordan Frankfurt
8e3b2cb4b8 feat(widgets): add error reporting component, INTEGRATION ERROR type, and Missing provider error (#3110)
* add error reporting component, INTEGRATION ERROR type, and Missing provider error

* rename reporter to generator

* pr feedback

* refactor provider check

* add chainId, convenienceFee, and width errors

* pr feedback and convenienceFeeRecipient address enforcement

* fix imports for utils
2022-01-19 09:38:21 -06:00
Zach Pomerantz
d54783a324 fix: memoize more swap (#2950)
* fix: memoize derived swap info

* fix: memoize current block timestamp

* fix: memoize price impact

* fix: memoize debounced value updates

* fix: nits
2022-01-18 18:40:23 -05:00
Zach Pomerantz
850a20f6ad feat: include native currency in widget select (#3124)
* fix: token image for chains / natives

* feat: include native currency in select

- Updates widgets swap state to use Currency (and deals with downstream updates)
- Refactors logoURI code to a new lib/hooks/useCurrencyLogoURIs
- Adds native currency to useQueryTokenList

NB: This does not build because tests must be updated to use Currency (they currently use mock tokens)

* test: update fixtures to use real currency

* fix: data uri color extraction

* fix: token img state

* fix: use new array
2022-01-18 12:11:22 -08:00
Zach Pomerantz
99f681818f refactor: mv token hooks to lib (#3122)
* refactor: mv useNativeCurrency to lib/hooks

* refactor: mv useCurrency logic to lib/hooks
2022-01-14 11:30:04 -08:00
Crowdin Bot
1127e74357 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-14 19:07:20 +00:00
Ian Lapham
27843f6189 update end timestamp for survey (#3121) 2022-01-14 11:46:13 -07:00
Ian Lapham
1b10c88c51 feat: add survey popup for survey monkey (#3116)
* add survey popup for survey monkey

* update useEffect and add 24 hour window

* upate % logic

* update logic to show after duration

* update timestamp conditional

* small changes
2022-01-14 11:33:31 -07:00
Crowdin Bot
5d97cbf6ad chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-14 08:11:26 +00:00
Crowdin Bot
064a73ca1b chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-14 07:07:17 +00:00
Zach Pomerantz
e5a1cb4276 chore: replace microbundle with rollup (#3115)
* refactor: mv gas estimate chains out of component

* chore: replace microbundle with rollup

* chore: use ts rollup config

* chore: rename lib to widgets

* chore: add rollup doc comment

* feat: rollup typings

* fix: retain tsconfig decl dir
2022-01-13 17:11:27 -08:00
Zach Pomerantz
e68e1afd9d feat: sort the widget token select (#3114)
* refactor: mv token list utils to lib

* refactor: mv balance hooks to lib

* feat: interactive token select
2022-01-13 14:37:47 -08:00
Zach Pomerantz
8784a761d6 feat: add multicall to widget (#3112)
* feat: mv block number to atom

* fix: add block updater

* fix: fast forward dep

* refactor: mv multicall to lib

* feat: add multicall to widget

* chore: update widget deps

* nit: pluralize updaters

* chore: minimize deps
2022-01-13 08:54:08 -08:00
Zach Pomerantz
7aa0f500d6 feat: mv block number to atom (#3108)
* feat: mv block number to atom

* fix: add block updater

* fix: fast forward dep
2022-01-12 19:36:08 -08:00
Jordan Frankfurt
06a8151ede Revert "add error reporting component, INTEGRATION ERROR type, and Missing provider error (#3107)" (#3109)
This reverts commit ac2642fedc.
2022-01-12 14:24:23 -06:00
Jordan Frankfurt
ac2642fedc add error reporting component, INTEGRATION ERROR type, and Missing provider error (#3107) 2022-01-12 13:29:59 -06:00
Zach Pomerantz
ac962fb00d refactor: separate useActiveWeb3React (#3106) 2022-01-12 11:18:11 -08:00
Zach Pomerantz
f3bcf64144 refactor: split chain info from chains (#3105) 2022-01-12 10:46:41 -08:00
Zach Pomerantz
711b2ca85c chore: import @ethersprojects directly (#3104)
* Revert "chore: import from ethers"

This reverts commit 6d9c0855d2.

* Revert "fix: use provider JsonRpcProvider"

This reverts commit dcbbab5e4d.

* chore: depend on @ethersprojects directly
2022-01-12 10:06:22 -08:00
willpote
aa97ec01d3 chore: bump sor to 2.5.10 (#3091) 2022-01-11 17:26:42 -05:00
Crowdin Bot
83b70f3aa6 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-11 21:06:53 +00:00
Noah Zinsmeister
e37dd77680 Revert "bump to beta (#3090)"
This reverts commit aa37b23126.
2022-01-11 16:00:52 -05:00
Noah Zinsmeister
aa37b23126 bump to beta (#3090) 2022-01-11 15:30:45 -05:00
Jordan Frankfurt
5a90f13a03 chore(deps): bump walletconnect (#3097) 2022-01-11 14:16:35 -06:00
Will Hennessy
8c213f9001 Update wrong network message (#3089)
fixes https://github.com/Uniswap/interface/issues/2740
2022-01-11 14:16:19 -06:00
Jordan Frankfurt
5722902f96 add polygon to supported walletlink chainIds (#3096) 2022-01-11 14:15:09 -06:00
Zach Pomerantz
27412e49d5 chore: import from ethers (#3094)
* chore: rm lodash

* chore: improve styled-components lint

* chore: import from ethers

* fix: use provider JsonRpcProvider
2022-01-11 11:32:20 -08:00
Zach Pomerantz
90dfdc6bef feat: populate the widget token selector (#3080)
* feat: swap defaults

* refactor: mv token list utils to lib

* feat: expand fetchTokenList to include inlined

* feat: simple widget token list

* fix: token img props

* feat: use token list in selector

* fix: update useColor for optional logoURI

* fix: avoid leaking deps

* chore: add state to lib build

* chore: mv devDeps to deps for lib

* fix: microbundle css import

* fix: match ethers versions

* fix: use color callback

* chore: clean up token info type

* chore: widget type simplification

* refactor: share token map code

* test: include list in token select fixture

* fix: no tokens without chain id
2022-01-11 09:28:02 -08:00
Jordan Frankfurt
4f896361be fix(widgets): correctly position the arrows (#3083)
* correctly position the arrows

* update reverse button css and remove popover logic

* px->em
2022-01-11 09:50:39 -06:00
yj
c9bc166c1a fix: Add {id} replacement for ERC-1155 (#3068)
* Add `{id}` replacement for ERC-1155

For issue #3010

* Update useENSAvatar.ts

Add leading zero pad to 64 hex chars

* Update useENSAvatar.ts

Following review comments
2022-01-10 23:20:04 -05:00
Noah Zinsmeister
cecbf770c6 w3r version bumps (#3086) 2022-01-10 14:43:17 -05:00
Jordan Frankfurt
a7041ea700 undo accidental package version reversion (#3084) 2022-01-10 12:17:56 -06:00
Ian Lapham
5413303d24 update addresses (#3082) 2022-01-08 17:36:18 -05:00
dependabot[bot]
103e18496f chore(deps-dev): bump @uniswap/default-token-list from 2.2.0 to 3.0.0 (#3076)
Bumps [@uniswap/default-token-list](https://github.com/Uniswap/default-token-list) from 2.2.0 to 3.0.0.
- [Release notes](https://github.com/Uniswap/default-token-list/releases)
- [Commits](https://github.com/Uniswap/default-token-list/compare/v2.2.0...v3.0.0)

---
updated-dependencies:
- dependency-name: "@uniswap/default-token-list"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-07 11:13:41 -05:00
Crowdin Bot
0e678465cb chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-06 11:07:11 +00:00
Crowdin Bot
6b68baaa4d chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-06 10:06:28 +00:00
Crowdin Bot
3c5e3744f1 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-06 05:09:06 +00:00
Crowdin Bot
d93b6f795e chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-06 04:07:29 +00:00
Jordan Frankfurt
f145a56f4a fix: web3-react-fixes (#3066) (#3075)
* add empty connector

add url connector

* naming

Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
2022-01-05 20:48:33 -06:00
Ian Lapham
7622290557 update state org and get latest (#3073) 2022-01-05 16:17:13 -05:00
Crowdin Bot
226544402a chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-05 20:06:38 +00:00
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
392 changed files with 22822 additions and 10475 deletions

2
.env
View File

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

View File

@@ -58,10 +58,6 @@
"error",
{
"paths": [
{
"name": "lodash",
"message": "Please import from 'lodash/module' directly to support tree-shaking."
},
{
"name": "ethers",
"message": "Please import from '@ethersproject/module' directly to support tree-shaking."

40
.github/workflows/bundle.yaml vendored Normal file
View File

@@ -0,0 +1,40 @@
name: Widgets
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
name: Build
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: Build
run: yarn widgets:build

6
.gitignore vendored
View File

@@ -3,8 +3,12 @@
# 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
# dependencies
@@ -16,7 +20,7 @@
# production
/build
# bundle
# widgets
/dist
# misc

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

@@ -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"
}
}
}

25
cosmos.override.js Normal file
View File

@@ -0,0 +1,25 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { DefinePlugin } = require('webpack')
// Renders the cosmos fixtures in isolation, instead of using public/index.html.
module.exports = (webpackConfig) => ({
...webpackConfig,
plugins: webpackConfig.plugins.map((plugin) => {
if (plugin instanceof HtmlWebpackPlugin) {
return new HtmlWebpackPlugin({
templateContent: '<body></body>',
})
}
if (plugin instanceof DefinePlugin) {
return new DefinePlugin({
...plugin.definitions,
'process.env': {
...plugin.definitions['process.env'],
REACT_APP_IS_WIDGET: true,
},
})
}
return plugin
}),
})

View File

@@ -46,11 +46,13 @@ const linguiConfig = {
'vi-VN',
'zh-CN',
'zh-TW',
'pseudo',
],
orderBy: 'messageId',
rootDir: '.',
runtimeConfigModule: ['@lingui/core', 'i18n'],
sourceLocale: 'en-US',
pseudoLocale: 'pseudo',
}
export default linguiConfig

View File

@@ -18,14 +18,16 @@
"@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",
"@metamask/jazzicon": "^2.0.0",
"@popperjs/core": "^2.4.4",
"@reach/dialog": "^0.10.3",
"@reach/portal": "^0.10.3",
"@react-hook/window-scroll": "^1.3.0",
"@reduxjs/toolkit": "^1.6.1",
"@rollup/plugin-eslint": "^8.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-replace": "^3.0.1",
"@rollup/plugin-url": "^6.1.0",
"@svgr/rollup": "^6.2.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@testing-library/react-hooks": "^7.0.2",
@@ -54,79 +56,64 @@
"@types/wcag-contrast": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
"@uniswap/default-token-list": "^2.1.0",
"@uniswap/default-token-list": "^3.0.0",
"@uniswap/governance": "^1.0.2",
"@uniswap/liquidity-staker": "^1.0.2",
"@uniswap/merkle-distributor": "1.0.1",
"@uniswap/sdk-core": "^3.0.1",
"@uniswap/token-lists": "^1.0.0-beta.27",
"@uniswap/smart-order-router": "^2.5.10",
"@uniswap/v2-core": "1.0.0",
"@uniswap/v2-periphery": "^1.1.0-beta.0",
"@uniswap/v2-sdk": "^3.0.0-alpha.2",
"@uniswap/v3-core": "1.0.0",
"@uniswap/v3-periphery": "^1.1.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.8",
"ajv": "^6.12.3",
"array.prototype.flat": "^1.2.4",
"array.prototype.flatmap": "^1.2.4",
"cids": "^1.0.0",
"copy-to-clipboard": "^3.2.0",
"cross-env": "^7.0.3",
"cypress": "^7.7.0",
"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",
"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-cosmos": "^5.6.6",
"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",
"rollup": "^2.63.0",
"rollup-plugin-dts": "^4.1.0",
"rollup-plugin-scss": "^3.0.0",
"rollup-plugin-typescript2": "^0.31.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",
@@ -134,7 +121,7 @@
"workbox-routing": "^6.1.0"
},
"resolutions": {
"@walletconnect/ethereum-provider": "1.6.5"
"@walletconnect/ethereum-provider": "1.7.1"
},
"scripts": {
"contracts:compile:abi": "typechain --target ethers-v5 --out-dir src/abis/types \"./src/abis/**/*.json\"",
@@ -144,13 +131,14 @@
"prei18n:extract": "touch src/locales/en-US.po",
"i18n:extract": "lingui extract --locale en-US",
"i18n:compile": "yarn i18n:extract && lingui compile",
"i18n:pseudo": "lingui extract --locale pseudo && lingui compile",
"postinstall": "yarn contracts:compile && yarn graphql:generate && yarn i18n:compile",
"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"
"widgets:start": "cosmos",
"widgets:build": "rollup --config --failAfterWarnings --configPlugin typescript2"
},
"browserslist": {
"production": [
@@ -165,5 +153,63 @@
]
},
"license": "GPL-3.0-or-later",
"dependencies": {}
"dependencies": {
"@ethersproject/abi": "^5.4.1",
"@ethersproject/abstract-provider": "^5.4.1",
"@ethersproject/address": "^5.4.0",
"@ethersproject/bignumber": "^5.4.2",
"@ethersproject/bytes": "^5.4.0",
"@ethersproject/constants": "^5.4.0",
"@ethersproject/contracts": "^5.4.1",
"@ethersproject/hash": "^5.4.0",
"@ethersproject/providers": "^5.4.5",
"@ethersproject/solidity": "^5.4.0",
"@ethersproject/strings": "^5.4.0",
"@ethersproject/units": "^5.4.0",
"@ethersproject/wallet": "^5.4.0",
"@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",
"@uniswap/router-sdk": "^1.0.3",
"@uniswap/sdk-core": "^3.0.1",
"@uniswap/token-lists": "^1.0.0-beta.27",
"@uniswap/v2-sdk": "^3.0.1",
"@uniswap/v3-sdk": "^3.7.1",
"@web3-react/core": "^6.0.9",
"ajv": "^6.12.3",
"cids": "^1.0.0",
"immer": "^9.0.6",
"jotai": "^1.3.7",
"jsbi": "^3.1.4",
"make-plural": "^7.0.0",
"ms.macro": "^2.0.0",
"multicodec": "^3.0.1",
"multihashes": "^4.0.2",
"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-redux": "^7.2.2",
"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.16-alpha.0",
"widgets-web3-react/eip1193": "npm:@web3-react/eip1193@8.0.16-alpha.0",
"widgets-web3-react/empty": "npm:@web3-react/empty@8.0.17-alpha.0",
"widgets-web3-react/metamask": "npm:@web3-react/metamask@8.0.16-alpha.0",
"widgets-web3-react/types": "npm:@web3-react/types@8.0.16-alpha.0",
"widgets-web3-react/url": "npm:@web3-react/url@8.0.17-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);

63
rollup.config.ts Normal file
View File

@@ -0,0 +1,63 @@
/**
* Bundles the widgets library, which is released independently of the interface application.
* This library lives in src/lib, but shares code with the interface application.
*/
import eslint from '@rollup/plugin-eslint'
import json from '@rollup/plugin-json'
import replace from '@rollup/plugin-replace'
import url from '@rollup/plugin-url'
import svgr from '@svgr/rollup'
import dts from 'rollup-plugin-dts'
import sass from 'rollup-plugin-scss'
import typescript from 'rollup-plugin-typescript2'
import { dependencies } from './package.json'
const deps = Object.keys(dependencies)
const replacements = {
'process.env.REACT_APP_IS_WIDGET': true,
}
const library = {
input: 'src/lib/index.tsx',
output: [
{
file: 'dist/widgets.js',
format: 'cjs',
inlineDynamicImports: true,
sourcemap: true,
},
{
file: 'dist/widgets.esm.js',
format: 'esm',
inlineDynamicImports: true,
sourcemap: true,
},
],
// necessary because some nested imports (eg jotai/*) would otherwise not resolve.
external: (source: string) => Boolean(deps.find((dep) => source === dep || source.startsWith(dep + '/'))),
plugins: [
eslint({ include: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'] }),
json(), // imports json
replace({ ...replacements, preventAssignment: true }),
url(), // imports files (including svgs) as data URIs
svgr({ exportType: 'named', svgo: false }), // imports svgs as React components
sass(), // imports sass styles
typescript({ tsconfig: './tsconfig.lib.json', useTsconfigDeclarationDir: true }),
],
}
const typings = {
input: 'dist/dts/lib/index.d.ts',
output: {
file: 'dist/widgets.d.ts',
format: 'es',
},
external: (source: string) => source.endsWith('.scss'),
plugins: [dts({ compilerOptions: { baseUrl: 'dist/dts' } })],
}
const config = [library, typings]
export default config

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

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 572 KiB

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

@@ -1,7 +1,7 @@
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { CheckCircle, Triangle } from 'react-feather'
import styled from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks/web3'
import { useAllTransactions } from '../../state/transactions/hooks'
import { ExternalLink } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'

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'
@@ -130,18 +131,33 @@ 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>
)
}

View File

@@ -1,14 +1,15 @@
import { Trans } from '@lingui/macro'
import { AbstractConnector } from '@web3-react/abstract-connector'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
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 { ReactComponent as Close } from '../../assets/images/x.svg'
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, ThemedText } from '../../theme'
import { shortenAddress } from '../../utils'
@@ -176,7 +177,7 @@ const IconWrapper = styled.div<{ size?: number }>`
`};
`
function WrappedStatusIcon({ connector }: { connector: AbstractConnector }) {
function WrappedStatusIcon({ connector }: { connector: AbstractConnector | Connector }) {
return (
<IconWrapper size={16}>
<StatusIcon connector={connector} />

View File

@@ -1,11 +1,11 @@
import { Trans } from '@lingui/macro'
// eslint-disable-next-line no-restricted-imports
import { t } from '@lingui/macro'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
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, ThemedText } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { AutoColumn } from '../Column'

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

@@ -1,8 +1,7 @@
import { Trans } from '@lingui/macro'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { ReactNode, useMemo } from 'react'
import { useActiveWeb3React } from '../../hooks/web3'
// SDN OFAC addresses
const BLOCKED_ADDRESSES: string[] = [
'0x7Db418b5D567A4e0E8c59Ad71BE1FcE48f3E6107',
@@ -20,6 +19,19 @@ const BLOCKED_ADDRESSES: string[] = [
'0x8576aCC5C05D6Ce88f4e49bf65BdF0C62F91353C',
'0xC8a65Fadf0e0dDAf421F28FEAb69Bf6E2E589963',
'0x308eD4B7b49797e1A98D3818bFF6fe5385410370',
'0x67d40EE1A85bf4a4Bb7Ffae16De985e8427B',
'0x6f1ca141a28907f78ebaa64fb83a9088b02a83',
'0x6acdfba02d390b97ac2b2d42a63e85293bcc1',
'0x48549a34ae37b12f6a30566245176994e17c6',
'0x5512d943ed1f7c8a43f3435c85f7ab68b30121',
'0xc455f7fd3e0e12afd51fba5c106909934d8a0e',
'0x3cbded43efdaf0fc77b9c55f6fc9988fcc9b757d',
'0x67d40EE1A85bf4a4Bb7Ffae16De985e8427B6b45',
'0x6f1ca141a28907f78ebaa64fb83a9088b02a8352',
'0x6acdfba02d390b97ac2b2d42a63e85293bcc160e',
'0x48549a34ae37b12f6a30566245176994e17c6b4a',
'0x5512d943ed1f7c8a43f3435c85f7ab68b30121b0',
'0xc455f7fd3e0e12afd51fba5c106909934d8a0e4a',
]
export default function Blocklist({ children }: { children: ReactNode }) {

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;

View File

@@ -1,4 +1,6 @@
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'
@@ -6,6 +8,7 @@ import { useMemo } from 'react'
import useTheme from '../../hooks/useTheme'
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 (
<ThemedText.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,7 +43,9 @@ 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}
</ThemedText.Body>

View File

@@ -3,6 +3,7 @@ import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { darken } from 'polished'
import { ReactNode, useCallback, useState } from 'react'
import { Lock } from 'react-feather'
@@ -11,7 +12,6 @@ import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
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 { ThemedText } from '../../theme'
import { ButtonGray } from '../Button'
@@ -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 {
@@ -220,6 +223,15 @@ export default function CurrencyInputPanel({
)}
<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' }}>
<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}
</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,52 +1,19 @@
import { Currency } from '@uniswap/sdk-core'
import { SupportedChainId } from 'constants/chains'
import React, { useMemo } from 'react'
import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs'
import React from 'react'
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'
function chainIdToNetworkName(networkId: SupportedChainId): Network {
switch (networkId) {
case SupportedChainId.MAINNET:
return 'ethereum'
case SupportedChainId.ARBITRUM_ONE:
return 'arbitrum'
case SupportedChainId.OPTIMISM:
return 'optimism'
default:
return 'ethereum'
}
}
export const getTokenLogoURL = (
address: string,
chainId: SupportedChainId = SupportedChainId.MAINNET
): string | void => {
const networkName = chainIdToNetworkName(chainId)
const networksWithUrls = [SupportedChainId.ARBITRUM_ONE, SupportedChainId.MAINNET, SupportedChainId.OPTIMISM]
if (networksWithUrls.includes(chainId)) {
return `https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/${networkName}/assets/${address}/logo.png`
}
}
const StyledEthereumLogo = styled.img<{ size: string }>`
const StyledLogo = styled(Logo)<{ size: string; native: boolean }>`
width: ${({ size }) => size};
height: ${({ size }) => size};
box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075);
border-radius: 24px;
`
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 ${({ native }) => (native ? 'white' : 'black')};
-webkit-box-shadow: 0 0 1px ${({ native }) => (native ? 'white' : 'black')};
box-shadow: 0 0 1px ${({ native }) => (native ? 'white' : 'black')};
border: 0px solid rgba(255, 255, 255, 0);
`
export default function CurrencyLogo({
@@ -59,28 +26,16 @@ export default function CurrencyLogo({
size?: string
style?: React.CSSProperties
}) {
const uriLocations = useHttpLocations(currency instanceof WrappedTokenInfo ? currency.logoURI : undefined)
const logoURIs = useCurrencyLogoURIs(currency)
const srcs: string[] = useMemo(() => {
if (!currency || currency.isNative) return []
if (currency.isToken) {
const defaultUrls = []
const url = getTokenLogoURL(currency.address, currency.chainId)
if (url) {
defaultUrls.push(url)
}
if (currency instanceof WrappedTokenInfo) {
return [...uriLocations, ...defaultUrls]
}
return defaultUrls
}
return []
}, [currency, uriLocations])
if (currency?.isNative) {
return <StyledEthereumLogo src={EthereumLogo} alt="ethereum logo" size={size} style={style} {...rest} />
}
return <StyledLogo size={size} srcs={srcs} alt={`${currency?.symbol ?? 'token'} logo`} style={style} {...rest} />
return (
<StyledLogo
size={size}
native={currency?.isNative ?? false}
srcs={logoURIs}
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 { useActiveWeb3React } from 'hooks/web3'
import { SupportedChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
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

@@ -5,10 +5,10 @@ import { ButtonGray } from 'components/Button'
import Card from 'components/Card'
import { AutoColumn } from 'components/Column'
import { RowBetween } from 'components/Row'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
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, useMemo, useRef, useState } from 'react'
import ReactGA from 'react-ga'

View File

@@ -1,6 +1,7 @@
import { Trans } from '@lingui/macro'
import { CHAIN_INFO, L2ChainInfo, SupportedChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import { CHAIN_INFO, L2ChainInfo } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { AlertOctagon } from 'react-feather'
import styled from 'styled-components/macro'
import { ExternalLink, MEDIA_WIDTHS } from 'theme'

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,22 @@
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 } from 'constants/chainInfo'
import { CHAIN_IDS_TO_NAMES, SupportedChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
import { useActiveWeb3React } from 'hooks/web3'
import { useCallback, useRef } from 'react'
import useParsedQueryString from 'hooks/useParsedQueryString'
import usePrevious from 'hooks/usePrevious'
import { ParsedQs } from 'qs'
import { useCallback, useEffect, useRef } from 'react'
import { ArrowDownCircle, ChevronDown } from 'react-feather'
import { useHistory } from 'react-router-dom'
import { useModalOpen, useToggleModal } from 'state/application/hooks'
import { ApplicationModal } from 'state/application/reducer'
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 { replaceURLParam } from 'utils/routes'
import { useAppDispatch } from '../../state/hooks'
import { switchToNetwork } from '../../utils/switchToNetwork'
const ActiveRowLinkList = styled.div`
display: flex;
@@ -34,17 +34,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 +52,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 +74,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 +112,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 +134,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 +144,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 +159,165 @@ 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
}
const getParsedChainId = (parsedQs?: ParsedQs) => {
const chain = parsedQs?.chain
if (!chain || typeof chain !== 'string') return { urlChain: undefined, urlChainId: undefined }
return { urlChain: chain.toLowerCase(), urlChainId: getChainIdFromName(chain) }
}
const getChainIdFromName = (name: string) => {
const entry = Object.entries(CHAIN_IDS_TO_NAMES).find(([_, n]) => n === name)
const chainId = entry?.[0]
return chainId ? parseInt(chainId) : undefined
}
const getChainNameFromId = (id: string | number) => {
// casting here may not be right but fine to return undefined if it's not a supported chain ID
return CHAIN_IDS_TO_NAMES[id as SupportedChainId] || ''
}
export default function NetworkSelector() {
const { chainId, library } = useActiveWeb3React()
const parsedQs = useParsedQueryString()
const { urlChain, urlChainId } = getParsedChainId(parsedQs)
const prevChainId = usePrevious(chainId)
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 history = useHistory()
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()
const handleChainSwitch = useCallback(
(targetChain: number, skipToggle?: boolean) => {
if (!library) return
switchToNetwork({ library, chainId: targetChain })
.then(() => {
if (!skipToggle) {
toggle()
}
history.replace({
search: replaceURLParam(history.location.search, 'chain', getChainNameFromId(targetChain)),
})
})
.catch((error) => {
console.error('Failed to switch networks', error)
// we want app network <-> chainId param to be in sync, so if user changes the network by changing the URL
// but the request fails, revert the URL back to current chainId
if (chainId) {
history.replace({ search: replaceURLParam(history.location.search, 'chain', getChainNameFromId(chainId)) })
}
if (!skipToggle) {
toggle()
}
dispatch(addPopup({ content: { failedSwitchNetwork: targetChain }, key: `failed-network-switch` }))
})
},
[dispatch, library, toggle, history, chainId]
)
useEffect(() => {
// when network change originates from wallet or dropdown selector, just update URL
if (chainId && chainId !== prevChainId) {
history.replace({ search: replaceURLParam(history.location.search, 'chain', getChainNameFromId(chainId)) })
// otherwise assume network change originates from URL
} else if (urlChainId && urlChainId !== chainId) {
handleChainSwitch(urlChainId, true)
}
}, [showSelector, toggle])
}, [chainId, urlChainId, prevChainId, handleChainSwitch, history])
// set chain parameter on initial load if not there
useEffect(() => {
if (chainId && !urlChainId) {
history.replace({ search: replaceURLParam(history.location.search, 'chain', getChainNameFromId(chainId)) })
}
}, [chainId, history, urlChainId, urlChain])
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={handleChainSwitch} targetChain={SupportedChainId.MAINNET} />
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.POLYGON} />
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.OPTIMISM} />
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.ARBITRUM_ONE} />
</FlyoutMenu>
)}
</SelectorWrapper>

View File

@@ -1,14 +1,20 @@
import { CHAIN_INFO } from 'constants/chains'
import { Trans } from '@lingui/macro'
import { RowFixed } from 'components/Row'
import { CHAIN_INFO } from 'constants/chainInfo'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
import useGasPrice from 'hooks/useGasPrice'
import useMachineTimeMs from 'hooks/useMachineTime'
import { useActiveWeb3React } from 'hooks/web3'
import useTheme from 'hooks/useTheme'
import JSBI from 'jsbi'
import useBlockNumber from 'lib/hooks/useBlockNumber'
import ms from 'ms.macro'
import { useEffect, useState } from 'react'
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 { MouseoverTooltip } from '../Tooltip'
import { ChainConnectivityWarning } from './ChainConnectivityWarning'
const StyledPolling = styled.div<{ warning: boolean }>`
@@ -31,6 +37,14 @@ const StyledPollingNumber = styled(ThemedText.Small)<{ breathe: boolean; hoverin
:hover {
opacity: 1;
}
a {
color: unset;
}
a:hover {
text-decoration: none;
color: unset;
}
`
const StyledPollingDot = styled.div<{ warning: boolean }>`
width: 8px;
@@ -43,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);
@@ -81,6 +106,10 @@ export default function Polling() {
const [isHover, setIsHover] = useState(false)
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
@@ -105,19 +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) : ''}
>
<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={warning}>{isMounting && <Spinner warning={warning} />}</StyledPollingDot>{' '}
</StyledPolling>
</ExternalLink>
{warning && <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, ThemedText, 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>
<ThemedText.White color="white">
<Trans>Your UNI Breakdown</Trans>
</ThemedText.White>
<StyledClose stroke="white" onClick={() => setShowUniBalanceModal(false)} />
</RowBetween>
</CardSection>
<Break />
{account && (
<>
<CardSection gap="sm">
<AutoColumn gap="md" justify="center">
<UniTokenAnimated width="48px" src={tokenLogo} />{' '}
<ThemedText.White fontSize={48} fontWeight={600} color="white">
{total?.toFixed(2, { groupSeparator: ',' })}
</ThemedText.White>
</AutoColumn>
<AutoColumn gap="md">
<RowBetween>
<ThemedText.White color="white">
<Trans>Balance:</Trans>
</ThemedText.White>
<ThemedText.White color="white">{uniBalance?.toFixed(2, { groupSeparator: ',' })}</ThemedText.White>
</RowBetween>
<RowBetween>
<ThemedText.White color="white">
<Trans>Unclaimed:</Trans>
</ThemedText.White>
<ThemedText.White color="white">
{uniToClaim?.toFixed(4, { groupSeparator: ',' })}{' '}
{uniToClaim && uniToClaim.greaterThan('0') && (
<StyledInternalLink onClick={() => setShowUniBalanceModal(false)} to="/uni">
<Trans>(claim)</Trans>
</StyledInternalLink>
)}
</ThemedText.White>
</RowBetween>
</AutoColumn>
</CardSection>
<Break />
</>
)}
<CardSection gap="sm">
<AutoColumn gap="md">
<RowBetween>
<ThemedText.White color="white">
<Trans>UNI price:</Trans>
</ThemedText.White>
<ThemedText.White color="white">${uniPrice?.toFixed(2) ?? '-'}</ThemedText.White>
</RowBetween>
<RowBetween>
<ThemedText.White color="white">
<Trans>UNI in circulation:</Trans>
</ThemedText.White>
<ThemedText.White color="white">{circulation?.toFixed(0, { groupSeparator: ',' })}</ThemedText.White>
</RowBetween>
<RowBetween>
<ThemedText.White color="white">
<Trans>Total Supply</Trans>
</ThemedText.White>
<ThemedText.White color="white">{totalSupply?.toFixed(0, { groupSeparator: ',' })}</ThemedText.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

@@ -1,30 +1,29 @@
import { Trans } from '@lingui/macro'
import useScrollPosition from '@react-hook/window-scroll'
import { CHAIN_INFO, SupportedChainId } from 'constants/chains'
import { CHAIN_INFO } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
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, 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 +90,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 +122,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 +181,8 @@ const UniIcon = styled.div`
:hover {
transform: rotate(-5deg);
}
position: relative;
`
const activeClassName = 'ACTIVE'
@@ -202,11 +204,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 +233,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 +248,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 +258,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>
@@ -325,7 +330,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

@@ -1,4 +1,5 @@
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'
@@ -7,7 +8,7 @@ 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 }) {
export default function StatusIcon({ connector }: { connector: AbstractConnector | Connector }) {
switch (connector) {
case injected:
return <Identicon />

View File

@@ -1,10 +1,9 @@
import jazzicon from '@metamask/jazzicon'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useENSAvatar from 'hooks/useENSAvatar'
import { useLayoutEffect, useMemo, useRef, useState } from 'react'
import styled from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks/web3'
const StyledIdenticon = styled.div`
height: 1rem;
width: 1rem;
@@ -31,7 +30,11 @@ export default function Identicon() {
if (icon) {
current?.appendChild(icon)
return () => {
current?.removeChild(icon)
try {
current?.removeChild(icon)
} catch (e) {
console.error('Avatar icon not found')
}
}
}
return

View File

@@ -1,16 +1,10 @@
import { Currency } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk'
import { usePoolActiveLiquidity } from 'hooks/usePoolTickData'
import JSBI from 'jsbi'
import { TickProcessed, usePoolActiveLiquidity } from 'hooks/usePoolTickData'
import { useCallback, useMemo } from 'react'
import { ChartEntry } from './types'
export interface TickProcessed {
liquidityActive: JSBI
price0: string
}
export function useDensityChartData({
currencyA,
currencyB,

View File

@@ -4,6 +4,7 @@ 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 useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useLocationLinkProps } from 'hooks/useLocationLinkProps'
import React, { useEffect, useRef, useState } from 'react'
import {
@@ -25,7 +26,6 @@ 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 { useModalOpen, useToggleModal } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { ExternalLink } from '../../theme'
@@ -49,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 {

View File

@@ -1,10 +1,10 @@
import { Trans } from '@lingui/macro'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useContext } from 'react'
import { ArrowUpCircle } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
import Circle from '../../assets/images/blue-loader.svg'
import { useActiveWeb3React } from '../../hooks/web3'
import { CloseIcon, CustomLightSpinner, ThemedText } from '../../theme'
import { ExternalLink } from '../../theme/components'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'

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 { 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 { CHAIN_INFO } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
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 start 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

@@ -1,12 +1,12 @@
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useCallback, useEffect } from 'react'
import { Heart, X } from 'react-feather'
import ReactGA from 'react-ga'
import styled, { keyframes } from 'styled-components/macro'
import tokenLogo from '../../assets/images/token-logo.png'
import { useActiveWeb3React } from '../../hooks/web3'
import {
useModalOpen,
useShowClaimPopup,

View File

@@ -0,0 +1,35 @@
import { Trans } from '@lingui/macro'
import { CHAIN_INFO } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains'
import { useContext } from 'react'
import { AlertCircle } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
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

@@ -6,6 +6,7 @@ import styled, { ThemeContext } from 'styled-components/macro'
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

@@ -0,0 +1,106 @@
import { Trans } from '@lingui/macro'
import { AutoColumn } from 'components/Column'
import { RowFixed } from 'components/Row'
import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
import { useEffect } from 'react'
import { MessageCircle, X } from 'react-feather'
import ReactGA from 'react-ga'
import { useShowSurveyPopup } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { ExternalLink, ThemedText, Z_INDEX } from 'theme'
import BGImage from '../../assets/images/survey-orb.svg'
import useTheme from '../../hooks/useTheme'
const Wrapper = styled(AutoColumn)`
background: #edeef2;
position: relative;
border-radius: 12px;
padding: 18px;
max-width: 360px;
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
color: ${({ theme }) => theme.text1};
overflow: hidden;
${({ theme }) => theme.mediaWidth.upToSmall`
max-width: 100%;
`}
`
const BGOrb = styled.img`
position: absolute;
right: -64px;
top: -64px;
width: 180px;
z-index: ${Z_INDEX.sticky};
`
const WrappedCloseIcon = styled(X)`
position: absolute;
top: 10px;
right: 10px;
width: 20px;
height: 20px;
stroke: #7c7c80;
z-index: ${Z_INDEX.fixed};
:hover {
cursor: pointer;
opacity: 0.8;
}
`
const END_TIMESTAMP = 1642272346 // Jan 15th
export default function SurveyPopup() {
const theme = useTheme()
const [showPopup, setShowSurveyPopup] = useShowSurveyPopup()
// show popup to 1% of users
useEffect(() => {
// has not visited page during A/B testing if undefined
if (showPopup === undefined) {
if (Math.random() < 0.01) {
setShowSurveyPopup(true)
// log a case of succesful view
ReactGA.event({
category: 'Survey',
action: 'Saw Survey',
})
}
}
}, [setShowSurveyPopup, showPopup])
// limit survey to 24 hours based on timestamps
const timestamp = useCurrentBlockTimestamp()
const durationOver = timestamp ? timestamp.toNumber() > END_TIMESTAMP : false
return (
<>
{!showPopup || durationOver ? null : (
<Wrapper gap="10px">
<WrappedCloseIcon
onClick={() => {
ReactGA.event({
category: 'Survey',
action: 'Clicked Survey Link',
})
setShowSurveyPopup(false)
}}
/>
<BGOrb src={BGImage} />
<ExternalLink href="https://www.surveymonkey.com/r/YGWV9VD">
<RowFixed>
<MessageCircle stroke={theme.black} size="20px" strokeWidth="1px" />
<ThemedText.White fontWeight={600} color={theme.black} ml="6px">
<Trans>Tell us what you think </Trans>
</ThemedText.White>
</RowFixed>
</ExternalLink>
<ThemedText.Black style={{ zIndex: Z_INDEX.fixed }} fontWeight={400} fontSize="12px" color={theme.black}>
<Trans>Take a 10 minute survey to help us improve your experience in the Uniswap app.</Trans>
</ThemedText.Black>
</Wrapper>
)}
</>
)
}

View File

@@ -1,8 +1,8 @@
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useContext } from 'react'
import { AlertCircle, CheckCircle } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTransaction } from '../../state/transactions/hooks'
import { ThemedText } from '../../theme'
import { ExternalLink } from '../../theme'

View File

@@ -1,13 +1,14 @@
import { SupportedChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import styled from 'styled-components/macro'
import { MEDIA_WIDTHS } from 'theme'
import { useActivePopups } from '../../state/application/hooks'
import { useURLWarningVisible } from '../../state/user/hooks'
import { useShowSurveyPopup, useURLWarningVisible } from '../../state/user/hooks'
import { AutoColumn } from '../Column'
import ClaimPopup from './ClaimPopup'
import PopupItem from './PopupItem'
import SurveyPopup from './SurveyPopup'
const MobilePopupWrapper = styled.div<{ height: string | number }>`
position: relative;
@@ -59,6 +60,9 @@ export default function Popups() {
// get all popups
const activePopups = useActivePopups()
// show survey popup if user has not closed
const [showSurveyPopup] = useShowSurveyPopup()
const urlWarningActive = useURLWarningVisible()
// need extra padding if network is not L1 Ethereum
@@ -69,12 +73,14 @@ export default function Popups() {
<>
<FixedPopupColumn gap="20px" extraPadding={urlWarningActive} xlPadding={isNotOnMainnet}>
<ClaimPopup />
<SurveyPopup />
{activePopups.map((item) => (
<PopupItem key={item.key} content={item.content} popKey={item.key} removeAfterMs={item.removeAfterMs} />
))}
</FixedPopupColumn>
<MobilePopupWrapper height={activePopups?.length > 0 ? 'fit-content' : 0}>
<MobilePopupWrapper height={activePopups?.length > 0 || showSurveyPopup ? 'fit-content' : 0}>
<MobilePopupInner>
<SurveyPopup />
{activePopups // reverse so new items up front
.slice(0)
.reverse()

View File

@@ -1,6 +1,7 @@
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import JSBI from 'jsbi'
import { transparentize } from 'polished'
import { useState } from 'react'
@@ -12,7 +13,6 @@ import styled from 'styled-components/macro'
import { BIG_INT_ZERO } from '../../constants/misc'
import { useColor } from '../../hooks/useColor'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTokenBalance } from '../../state/wallet/hooks'
import { currencyId } from '../../utils/currencyId'
import { unwrappedToken } from '../../utils/unwrappedToken'

View File

@@ -1,6 +1,7 @@
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import JSBI from 'jsbi'
import { transparentize } from 'polished'
import { useState } from 'react'
@@ -12,7 +13,6 @@ import styled from 'styled-components/macro'
import { BIG_INT_ZERO } from '../../constants/misc'
import { useColor } from '../../hooks/useColor'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTokenBalance } from '../../state/wallet/hooks'
import { ExternalLink, ThemedText } from '../../theme'
import { currencyId } from '../../utils/currencyId'

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

@@ -58,9 +58,15 @@ const EXTERNAL_APIS = [
{
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>
<>
<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>
</>
),
},
{

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.LOWEST]] },
{ 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,24 +9,24 @@ import Row, { AutoRow } from 'components/Row'
import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList'
import { Box } from 'rebass'
import styled from 'styled-components/macro'
import { ThemedText } 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;
`
@@ -38,7 +40,7 @@ const RouteRow = styled(Row)`
const PoolBadge = styled(Badge)`
display: flex;
padding: 0.25rem 0.5rem;
padding: 4px 4px;
`
const DottedLine = styled.div`
@@ -58,7 +60,27 @@ const DotColor = styled(DotLine)`
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({
@@ -75,29 +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>
<DotColor />
</DottedLine>
<OpaqueBadge>
<ThemedText.Small fontSize={12} style={{ wordBreak: 'normal' }}>
<ProtocolBadge>
<BadgeText fontSize={12}>{protocol.toUpperCase()}</BadgeText>
</ProtocolBadge>
<BadgeText fontSize={14} style={{ minWidth: 'auto' }}>
{percent.toSignificant(2)}%
</ThemedText.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} />
@@ -111,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>
<ThemedText.Small fontSize={12}>{feeAmount / 10000}%</ThemedText.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,10 +3,10 @@
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
@@ -22,11 +22,20 @@ exports[`renders multi route 1`] = `
</svg>
</div>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-6 gayll khxosM"
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>
@@ -36,26 +45,13 @@ 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.01%
</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
@@ -71,11 +67,20 @@ exports[`renders multi route 1`] = `
</svg>
</div>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-6 gayll khxosM"
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>
@@ -85,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
@@ -124,10 +102,10 @@ 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
@@ -143,11 +121,20 @@ exports[`renders single route 1`] = `
</svg>
</div>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-6 gayll khxosM"
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>
@@ -157,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
@@ -182,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

@@ -1,8 +1,6 @@
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'
@@ -46,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)

View File

@@ -2,6 +2,7 @@ import { Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { LightGreyCard } from 'components/Card'
import QuestionHelper from 'components/QuestionHelper'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useTheme from 'hooks/useTheme'
import { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react'
import { FixedSizeList } from 'react-window'
@@ -10,7 +11,6 @@ import styled from 'styled-components/macro'
import TokenListLogo from '../../assets/svg/tokenlist.svg'
import { useIsUserAddedToken } from '../../hooks/Tokens'
import { useActiveWeb3React } from '../../hooks/web3'
import { useCombinedActiveList } from '../../state/lists/hooks'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
import { useCurrencyBalance } from '../../state/wallet/hooks'

View File

@@ -1,30 +1,31 @@
// eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro'
import { Currency, Token } from '@uniswap/sdk-core'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useDebounce from 'hooks/useDebounce'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
import useTheme from 'hooks/useTheme'
import useToggle from 'hooks/useToggle'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import { getTokenFilter } from 'lib/hooks/useTokenList/filtering'
import { tokenComparator, useSortTokensByQuery } from 'lib/hooks/useTokenList/sorting'
import { KeyboardEvent, RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Edit } from 'react-feather'
import ReactGA from 'react-ga'
import AutoSizer from 'react-virtualized-auto-sizer'
import { FixedSizeList } from 'react-window'
import { Text } from 'rebass'
import { useAllTokenBalances } from 'state/wallet/hooks'
import styled from 'styled-components/macro'
import { ExtendedEther } from '../../constants/tokens'
import { useAllTokens, useIsUserAddedToken, useSearchInactiveTokenLists, useToken } from '../../hooks/Tokens'
import { useActiveWeb3React } from '../../hooks/web3'
import { ButtonText, CloseIcon, IconWrapper, ThemedText } from '../../theme'
import { isAddress } from '../../utils'
import Column from '../Column'
import Row, { RowBetween, RowFixed } from '../Row'
import CommonBases from './CommonBases'
import CurrencyList from './CurrencyList'
import { filterTokens, useSortedTokensByQuery } from './filtering'
import ImportRow from './ImportRow'
import { useTokenComparator } from './sorting'
import { PaddedColumn, SearchInput, Separator } from './styleds'
const ContentWrapper = styled(Column)`
@@ -79,8 +80,6 @@ export function CurrencySearch({
const [searchQuery, setSearchQuery] = useState<string>('')
const debouncedQuery = useDebounce(searchQuery, 200)
const [invertSearchOrder] = useState<boolean>(false)
const allTokens = useAllTokens()
// if they input an address, use it
@@ -100,27 +99,28 @@ export function CurrencySearch({
}
}, [isAddressSearch])
const tokenComparator = useTokenComparator(invertSearchOrder)
const filteredTokens: Token[] = useMemo(() => {
return filterTokens(Object.values(allTokens), debouncedQuery)
return Object.values(allTokens).filter(getTokenFilter(debouncedQuery))
}, [allTokens, debouncedQuery])
const balances = useAllTokenBalances()
const sortedTokens: Token[] = useMemo(() => {
return filteredTokens.sort(tokenComparator)
}, [filteredTokens, tokenComparator])
return filteredTokens.sort(tokenComparator.bind(null, balances))
}, [balances, filteredTokens])
const filteredSortedTokens = useSortedTokensByQuery(sortedTokens, debouncedQuery)
const filteredSortedTokens = useSortTokensByQuery(debouncedQuery, sortedTokens)
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) => {
@@ -148,8 +148,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() ||
@@ -160,7 +160,7 @@ export function CurrencySearch({
}
}
},
[debouncedQuery, ether, filteredSortedTokensWithETH, handleCurrencySelect]
[debouncedQuery, native, filteredSortedTokensWithETH, handleCurrencySelect]
)
// menu ui

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

@@ -3,8 +3,10 @@ import { t, Trans } from '@lingui/macro'
import { TokenList } from '@uniswap/token-lists'
import Card from 'components/Card'
import { UNSUPPORTED_LIST_URLS } from 'constants/lists'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useListColor } from 'hooks/useColor'
import { useActiveWeb3React } from 'hooks/web3'
import parseENSAddress from 'lib/utils/parseENSAddress'
import uriToHttp from 'lib/utils/uriToHttp'
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { CheckCircle, Settings } from 'react-feather'
import ReactGA from 'react-ga'
@@ -20,8 +22,6 @@ import { acceptListUpdate, disableList, enableList, removeList } from '../../sta
import { useActiveListUrls, useAllLists, useIsListActive } from '../../state/lists/hooks'
import { ExternalLink, IconWrapper, LinkStyledButton, ThemedText } from '../../theme'
import listVersionLabel from '../../utils/listVersionLabel'
import { parseENSAddress } from '../../utils/parseENSAddress'
import uriToHttp from '../../utils/uriToHttp'
import { ButtonEmpty, ButtonPrimary } from '../Button'
import Column, { AutoColumn } from '../Column'
import ListLogo from '../ListLogo'
@@ -31,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)`
@@ -229,7 +230,7 @@ const ListContainer = styled.div`
padding: 1rem;
height: 100%;
overflow: auto;
padding-bottom: 80px;
flex: 1;
`
export function ManageLists({

View File

@@ -5,7 +5,7 @@ import Column from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import Row, { RowBetween, RowFixed } from 'components/Row'
import { useToken } from 'hooks/Tokens'
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { RefObject, useCallback, useMemo, useRef, useState } from 'react'
import { useRemoveUserAddedToken, useUserAddedTokens } from 'state/user/hooks'
import styled from 'styled-components/macro'

View File

@@ -6,7 +6,7 @@ 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 useActiveWeb3React from 'hooks/useActiveWeb3React'
import { transparentize } from 'polished'
import { AlertCircle } from 'react-feather'
import styled, { useTheme } from 'styled-components/macro'

View File

@@ -1,76 +0,0 @@
import { Token } from '@uniswap/sdk-core'
import { TokenInfo } from '@uniswap/token-lists'
import { useMemo } from 'react'
import { isAddress } from '../../utils'
const alwaysTrue = () => true
/**
* Create a filter function to apply to a token for whether it matches a particular search query
* @param search the search query to apply to the token
*/
export function createTokenFilterFunction<T extends Token | TokenInfo>(search: string): (tokens: T) => boolean {
const searchingAddress = isAddress(search)
if (searchingAddress) {
const lower = searchingAddress.toLowerCase()
return (t: T) => ('isToken' in t ? searchingAddress === t.address : lower === t.address.toLowerCase())
}
const lowerSearchParts = search
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0)
if (lowerSearchParts.length === 0) return alwaysTrue
const matchesSearch = (s: string): boolean => {
const sParts = s
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0)
return lowerSearchParts.every((p) => p.length === 0 || sParts.some((sp) => sp.startsWith(p) || sp.endsWith(p)))
}
return ({ name, symbol }: T): boolean => Boolean((symbol && matchesSearch(symbol)) || (name && matchesSearch(name)))
}
export function filterTokens<T extends Token | TokenInfo>(tokens: T[], search: string): T[] {
return tokens.filter(createTokenFilterFunction(search))
}
export function useSortedTokensByQuery(tokens: Token[] | undefined, searchQuery: string): Token[] {
return useMemo(() => {
if (!tokens) {
return []
}
const symbolMatch = searchQuery
.toLowerCase()
.split(/\s+/)
.filter((s) => s.length > 0)
if (symbolMatch.length > 1) {
return tokens
}
const exactMatches: Token[] = []
const symbolSubtrings: Token[] = []
const rest: Token[] = []
// sort tokens by exact match -> subtring on symbol match -> rest
tokens.map((token) => {
if (token.symbol?.toLowerCase() === symbolMatch[0]) {
return exactMatches.push(token)
} else if (token.symbol?.toLowerCase().startsWith(searchQuery.toLowerCase().trim())) {
return symbolSubtrings.push(token)
} else {
return rest.push(token)
}
})
return [...exactMatches, ...symbolSubtrings, ...rest]
}, [tokens, searchQuery])
}

View File

@@ -1,51 +0,0 @@
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { useMemo } from 'react'
import { useAllTokenBalances } from '../../state/wallet/hooks'
// compare two token amounts with highest one coming first
function balanceComparator(balanceA?: CurrencyAmount<Currency>, balanceB?: CurrencyAmount<Currency>) {
if (balanceA && balanceB) {
return balanceA.greaterThan(balanceB) ? -1 : balanceA.equalTo(balanceB) ? 0 : 1
} else if (balanceA && balanceA.greaterThan('0')) {
return -1
} else if (balanceB && balanceB.greaterThan('0')) {
return 1
}
return 0
}
function getTokenComparator(balances: {
[tokenAddress: string]: CurrencyAmount<Currency> | undefined
}): (tokenA: Token, tokenB: Token) => number {
return function sortTokens(tokenA: Token, tokenB: Token): number {
// -1 = a is first
// 1 = b is first
// sort by balances
const balanceA = balances[tokenA.address]
const balanceB = balances[tokenB.address]
const balanceComp = balanceComparator(balanceA, balanceB)
if (balanceComp !== 0) return balanceComp
if (tokenA.symbol && tokenB.symbol) {
// sort by symbol
return tokenA.symbol.toLowerCase() < tokenB.symbol.toLowerCase() ? -1 : 1
} else {
return tokenA.symbol ? -1 : tokenB.symbol ? -1 : 0
}
}
}
export function useTokenComparator(inverted: boolean): (tokenA: Token, tokenB: Token) => number {
const balances = useAllTokenBalances()
const comparator = useMemo(() => getTokenComparator(balances ?? {}), [balances])
return useMemo(() => {
if (inverted) {
return (tokenA: Token, tokenB: Token) => comparator(tokenA, tokenB) * -1
} else {
return comparator
}
}, [inverted, comparator])
}

View File

@@ -1,12 +1,12 @@
// 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 useActiveWeb3React from 'hooks/useActiveWeb3React'
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'
@@ -27,7 +27,7 @@ const StyledMenuIcon = styled(Settings)`
width: 20px;
> * {
stroke: ${({ theme }) => theme.text2};
stroke: ${({ theme }) => theme.text1};
}
:hover {
@@ -199,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>
<ThemedText.Black fontWeight={400} fontSize={14} color={theme.text2}>
<Trans>Auto Router</Trans>
<Trans>Auto Router API</Trans>
</ThemedText.Black>
<QuestionHelper
text={<Trans>Use the Uniswap Labs API to get better pricing through a more efficient route.</Trans>}
/>
<QuestionHelper text={<Trans>Use the Uniswap Labs API to get faster quotes.</Trans>} />
</RowFixed>
<Toggle
id="toggle-optimized-router-button"
@@ -223,7 +220,6 @@ export default function SettingsTab({ placeholderSlippage }: { placeholderSlippa
/>
</RowBetween>
)}
<RowBetween>
<RowFixed>
<ThemedText.Black fontWeight={400} fontSize={14} color={theme.text2}>

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

@@ -1,7 +1,9 @@
import { Trans } from '@lingui/macro'
import { Currency } from '@uniswap/sdk-core'
import Badge from 'components/Badge'
import { CHAIN_INFO, L2_CHAIN_IDS, SupportedL2ChainId } from 'constants/chains'
import { CHAIN_INFO } from 'constants/chainInfo'
import { L2_CHAIN_IDS, SupportedL2ChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useAddTokenToMetamask from 'hooks/useAddTokenToMetamask'
import { ReactNode, useContext } from 'react'
import { AlertCircle, AlertTriangle, ArrowUpCircle, CheckCircle } from 'react-feather'
@@ -11,7 +13,6 @@ import styled, { ThemeContext } from 'styled-components/macro'
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'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'

View File

@@ -2,7 +2,8 @@ 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 useActiveWeb3React from 'hooks/useActiveWeb3React'
import ms from 'ms.macro'
import { darken } from 'polished'
import { useContext, useState } from 'react'
import { useSetUserSlippageTolerance, useUserSlippageTolerance, useUserTransactionTTL } from 'state/user/hooks'
@@ -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)

View File

@@ -110,8 +110,8 @@ const HoverText = styled.div`
`
const LinkCard = styled(Card)`
background-color: ${({ theme }) => theme.primary1};
color: ${({ theme }) => theme.white};
background-color: ${({ theme }) => theme.bg1};
color: ${({ theme }) => theme.text3};
:hover {
cursor: pointer;
@@ -320,7 +320,7 @@ export default function WalletModal({
<ContentWrapper>
{error instanceof UnsupportedChainIdError ? (
<h5>
<Trans>Please connect to the appropriate Ethereum network.</Trans>
<Trans>Please connect to a supported network in the dropdown menu or in your wallet.</Trans>
</h5>
) : (
<Trans>Error connecting. Try refreshing the page.</Trans>
@@ -402,17 +402,6 @@ export default function WalletModal({
</ThemedText.Black>
</AutoRow>
</LightCard>
<LinkCard padding=".5rem" $borderRadius=".75rem" onClick={() => setWalletView(WALLET_VIEWS.LEGAL)}>
<RowBetween>
<AutoRow gap="4px">
<Info size={20} />
<ThemedText.White fontSize={14}>
<Trans>How this app uses APIs</Trans>
</ThemedText.White>
</AutoRow>
<ArrowRight size={16} />
</RowBetween>
</LinkCard>
{walletView === WALLET_VIEWS.PENDING ? (
<PendingView
connector={pendingWallet}
@@ -423,6 +412,17 @@ export default function WalletModal({
) : (
<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

@@ -6,6 +6,7 @@ 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 { NetworkContextName } from '../../constants/misc'
import useENSName from '../../hooks/useENSName'
@@ -35,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;
}
@@ -82,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;
@@ -127,7 +131,7 @@ function Sock() {
)
}
function WrappedStatusIcon({ connector }: { connector: AbstractConnector }) {
function WrappedStatusIcon({ connector }: { connector: AbstractConnector | Connector }) {
return (
<IconWrapper size={16}>
<StatusIcon connector={connector} />

View File

@@ -1,4 +1,4 @@
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useEffect } from 'react'
import ReactGA from 'react-ga'
import { RouteComponentProps } from 'react-router-dom'

View File

@@ -1,6 +1,7 @@
import { isAddress } from '@ethersproject/address'
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useState } from 'react'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
@@ -8,7 +9,6 @@ import styled from 'styled-components/macro'
import Circle from '../../assets/images/blue-loader.svg'
import tokenLogo from '../../assets/images/token-logo.png'
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, ThemedText, UniTokenAnimated } from '../../theme'

View File

@@ -1,6 +1,7 @@
import { isAddress } from '@ethersproject/address'
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import JSBI from 'jsbi'
import { useEffect, useState } from 'react'
import { Text } from 'rebass'
@@ -8,7 +9,6 @@ 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 { useModalOpen, useToggleSelfClaimModal } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { useClaimCallback, useUserClaimData, useUserUnclaimedAmount } from '../../state/claim/hooks'

View File

@@ -1,10 +1,10 @@
import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { ReactNode, useState } from 'react'
import styled from 'styled-components/macro'
import { useStakingContract } from '../../hooks/useContract'
import { useActiveWeb3React } from '../../hooks/web3'
import { StakingInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'

View File

@@ -2,6 +2,7 @@ import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useCallback, useState } from 'react'
import styled from 'styled-components/macro'
@@ -9,7 +10,6 @@ import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallbac
import { usePairContract, useStakingContract, useV2RouterContract } from '../../hooks/useContract'
import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
import { useActiveWeb3React } from '../../hooks/web3'
import { StakingInfo, useDerivedStakeInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'

View File

@@ -1,10 +1,10 @@
import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { ReactNode, useState } from 'react'
import styled from 'styled-components/macro'
import { useStakingContract } from '../../hooks/useContract'
import { useActiveWeb3React } from '../../hooks/web3'
import { StakingInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'

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 { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
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 { ThemedText } 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'
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>
<ThemedText.SubHeader color={theme.text1}>
<Trans>Liquidity Provider Fee</Trans>
</ThemedText.SubHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={65}>
<ThemedText.Black textAlign="right" fontSize={14}>
{realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${realizedLPFee.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>
<RowBetween>
<RowFixed>
<ThemedText.SubHeader color={theme.text1}>
<Trans>Allowed Slippage</Trans>
</ThemedText.SubHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={45}>
<ThemedText.Black textAlign="right" fontSize={14}>
{allowedSlippage.toFixed(2)}%
</ThemedText.Black>
</TextWithLoadingPlaceholder>
</RowBetween>
<RowBetween>
<RowFixed>
<ThemedText.SubHeader color={theme.text1}>
{trade.tradeType === TradeType.EXACT_INPUT ? <Trans>Minimum received</Trans> : <Trans>Maximum sent</Trans>}
</ThemedText.SubHeader>
</RowFixed>
<TextWithLoadingPlaceholder syncing={syncing} width={70}>
<ThemedText.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}`}
</ThemedText.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,9 @@
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 { tradeMeaningfullyDiffers } from 'utils/tradeMeaningFullyDiffer'
import TransactionConfirmationModal, {
ConfirmationModalContent,
@@ -11,25 +12,6 @@ import TransactionConfirmationModal, {
import SwapModalFooter from './SwapModalFooter'
import SwapModalHeader from './SwapModalHeader'
/**
* Returns true if the trade requires a confirmation of details before we can submit it
* @param args either a pair of V2 trades or a pair of V3 trades
*/
function tradeMeaningfullyDiffers(
...args:
| [V2Trade<Currency, Currency, TradeType>, V2Trade<Currency, Currency, TradeType>]
| [V3Trade<Currency, Currency, TradeType>, V3Trade<Currency, Currency, TradeType>]
): boolean {
const [tradeA, tradeB] = args
return (
tradeA.tradeType !== tradeB.tradeType ||
!tradeA.inputAmount.currency.equals(tradeB.inputAmount.currency) ||
!tradeA.inputAmount.equalTo(tradeB.inputAmount) ||
!tradeA.outputAmount.currency.equals(tradeB.outputAmount.currency) ||
!tradeA.outputAmount.equalTo(tradeB.outputAmount)
)
}
export default function ConfirmSwapModal({
trade,
originalTrade,
@@ -44,8 +26,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 +38,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]
)

View File

@@ -0,0 +1,102 @@
import { Trans } from '@lingui/macro'
import { Currency, TradeType } from '@uniswap/sdk-core'
import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer } from 'components/Loader/styled'
import { RowFixed } from 'components/Row'
import { MouseoverTooltipContent } from 'components/Tooltip'
import ReactGA from 'react-ga'
import { InterfaceTrade } from 'state/routing/types'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { ReactComponent as GasIcon } from '../../assets/images/gas-icon.svg'
import { ResponsiveTooltipContainer } from './styleds'
import SwapRoute from './SwapRoute'
const GasWrapper = styled(RowFixed)`
border-radius: 8px;
padding: 4px 6px;
height: 24px;
color: ${({ theme }) => theme.text3};
background-color: ${({ theme }) => theme.bg1};
font-size: 14px;
font-weight: 500;
user-select: none;
`
const StyledGasIcon = styled(GasIcon)`
margin-right: 4px;
height: 14px;
& > * {
stroke: ${({ theme }) => theme.text3};
}
`
export default function GasEstimateBadge({
trade,
loading,
showRoute,
disableHover,
}: {
trade: InterfaceTrade<Currency, Currency, TradeType> | undefined | null // dollar amount in active chain's stablecoin
loading: boolean
showRoute?: boolean // show route instead of gas estimation summary
disableHover?: boolean
}) {
const formattedGasPriceString = trade?.gasUseEstimateUSD
? trade.gasUseEstimateUSD.toFixed(2) === '0.00'
? '<$0.01'
: '$' + trade.gasUseEstimateUSD.toFixed(2)
: undefined
return (
<MouseoverTooltipContent
wrap={false}
disableHover={disableHover}
content={
loading ? null : (
<ResponsiveTooltipContainer
origin="top right"
style={{
padding: showRoute ? '0' : '12px',
border: 'none',
borderRadius: showRoute ? '16px' : '12px',
maxWidth: '400px',
}}
>
{showRoute ? (
trade ? (
<SwapRoute trade={trade} syncing={loading} fixedOpen={showRoute} />
) : null
) : (
<AutoColumn gap="4px" justify="center">
<ThemedText.Main fontSize="12px" textAlign="center">
<Trans>Estimated network fee</Trans>
</ThemedText.Main>
<ThemedText.Body textAlign="center" fontWeight={500} style={{ userSelect: 'none' }}>
<Trans>${trade?.gasUseEstimateUSD?.toFixed(2)}</Trans>
</ThemedText.Body>
<ThemedText.Main fontSize="10px" textAlign="center" maxWidth="140px" color="text3">
<Trans>Estimate may differ due to your wallet gas settings</Trans>
</ThemedText.Main>
</AutoColumn>
)}
</ResponsiveTooltipContainer>
)
}
placement="bottom"
onOpen={() =>
ReactGA.event({
category: 'Gas',
action: 'Gas Details Tooltip Open',
})
}
>
<LoadingOpacityContainer $loading={loading}>
<GasWrapper>
<StyledGasIcon />
{formattedGasPriceString ?? null}
</GasWrapper>
</LoadingOpacityContainer>
</MouseoverTooltipContent>
)
}

View File

@@ -1,5 +1,5 @@
import { Trans } from '@lingui/macro'
import { useRoutingAPIEnabled } from 'state/user/hooks'
import useAutoRouterSupported from 'hooks/useAutoRouterSupported'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
@@ -40,15 +40,15 @@ const StyledAutoRouterLabel = styled(ThemedText.Black)`
`
export function AutoRouterLogo() {
const routingAPIEnabled = useRoutingAPIEnabled()
const autoRouterSupported = useAutoRouterSupported()
return routingAPIEnabled ? <StyledAutoRouterIcon /> : <StyledStaticRouterIcon />
return autoRouterSupported ? <StyledAutoRouterIcon /> : <StyledStaticRouterIcon />
}
export function AutoRouterLabel() {
const routingAPIEnabled = useRoutingAPIEnabled()
const autoRouterSupported = useAutoRouterSupported()
return routingAPIEnabled ? (
return autoRouterSupported ? (
<StyledAutoRouterLabel fontSize={14}>Auto Router</StyledAutoRouterLabel>
) : (
<ThemedText.Black fontSize={14}>

View File

@@ -0,0 +1,203 @@
import { Trans } from '@lingui/macro'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import AnimatedDropdown from 'components/AnimatedDropdown'
import Card, { OutlineCard } from 'components/Card'
import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer } from 'components/Loader/styled'
import Row, { RowBetween, RowFixed } from 'components/Row'
import { MouseoverTooltipContent } from 'components/Tooltip'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { darken } from 'polished'
import { useState } from 'react'
import { ChevronDown, Info } from 'react-feather'
import { InterfaceTrade } from 'state/routing/types'
import styled, { keyframes, useTheme } from 'styled-components/macro'
import { HideSmall, ThemedText } from 'theme'
import { AdvancedSwapDetails } from './AdvancedSwapDetails'
import GasEstimateBadge from './GasEstimateBadge'
import { ResponsiveTooltipContainer } from './styleds'
import SwapRoute from './SwapRoute'
import TradePrice from './TradePrice'
const Wrapper = styled(Row)`
width: 100%;
justify-content: center;
`
const StyledInfoIcon = styled(Info)`
height: 16px;
width: 16px;
margin-right: 4px;
color: ${({ theme }) => theme.text3};
`
const StyledCard = styled(OutlineCard)`
padding: 12px;
border: 1px solid ${({ theme }) => theme.bg2};
`
const StyledHeaderRow = styled(RowBetween)<{ disabled: boolean; open: boolean }>`
padding: 4px 8px;
border-radius: 12px;
background-color: ${({ open, theme }) => (open ? theme.bg1 : 'transparent')};
align-items: center;
cursor: ${({ disabled }) => (disabled ? 'initial' : 'pointer')};
min-height: 40px;
:hover {
background-color: ${({ theme, disabled }) => (disabled ? theme.bg1 : darken(0.015, theme.bg1))};
}
`
const RotatingArrow = styled(ChevronDown)<{ open?: boolean }>`
transform: ${({ open }) => (open ? 'rotate(180deg)' : 'none')};
transition: transform 0.1s linear;
`
const StyledPolling = styled.div`
display: flex;
height: 16px;
width: 16px;
margin-right: 2px;
margin-left: 10px;
align-items: center;
color: ${({ theme }) => theme.text1};
transition: 250ms ease color;
${({ theme }) => theme.mediaWidth.upToMedium`
display: none;
`}
`
const StyledPollingDot = styled.div`
width: 8px;
height: 8px;
min-height: 8px;
min-width: 8px;
border-radius: 50%;
position: relative;
background-color: ${({ theme }) => theme.bg2};
transition: 250ms ease background-color;
`
const rotate360 = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`
const Spinner = styled.div`
animation: ${rotate360} 1s cubic-bezier(0.83, 0, 0.17, 1) infinite;
transform: translateZ(0);
border-top: 1px solid transparent;
border-right: 1px solid transparent;
border-bottom: 1px solid transparent;
border-left: 2px solid ${({ theme }) => theme.text1};
background: transparent;
width: 14px;
height: 14px;
border-radius: 50%;
position: relative;
transition: 250ms ease border-color;
left: -3px;
top: -3px;
`
interface SwapDetailsInlineProps {
trade: InterfaceTrade<Currency, Currency, TradeType> | undefined
syncing: boolean
loading: boolean
showInverted: boolean
setShowInverted: React.Dispatch<React.SetStateAction<boolean>>
allowedSlippage: Percent
}
export default function SwapDetailsDropdown({
trade,
syncing,
loading,
showInverted,
setShowInverted,
allowedSlippage,
}: SwapDetailsInlineProps) {
const theme = useTheme()
const { chainId } = useActiveWeb3React()
const [showDetails, setShowDetails] = useState(false)
return (
<Wrapper>
<AutoColumn gap={'8px'} style={{ width: '100%', marginBottom: '-8px' }}>
<StyledHeaderRow onClick={() => setShowDetails(!showDetails)} disabled={!trade} open={showDetails}>
<RowFixed style={{ position: 'relative' }}>
{loading || syncing ? (
<StyledPolling>
<StyledPollingDot>
<Spinner />
</StyledPollingDot>
</StyledPolling>
) : (
<HideSmall>
<MouseoverTooltipContent
wrap={false}
content={
<ResponsiveTooltipContainer origin="top right" style={{ padding: '0' }}>
<Card padding="12px">
<AdvancedSwapDetails trade={trade} allowedSlippage={allowedSlippage} syncing={syncing} />
</Card>
</ResponsiveTooltipContainer>
}
placement="bottom"
disableHover={showDetails}
>
<StyledInfoIcon color={trade ? theme.text3 : theme.bg3} />
</MouseoverTooltipContent>
</HideSmall>
)}
{trade ? (
<LoadingOpacityContainer $loading={syncing}>
<TradePrice
price={trade.executionPrice}
showInverted={showInverted}
setShowInverted={setShowInverted}
/>
</LoadingOpacityContainer>
) : loading || syncing ? (
<ThemedText.Main fontSize={14}>
<Trans>Fetching best price...</Trans>
</ThemedText.Main>
) : null}
</RowFixed>
<RowFixed>
{!trade?.gasUseEstimateUSD ||
showDetails ||
!chainId ||
!SUPPORTED_GAS_ESTIMATE_CHAIN_IDS.includes(chainId) ? null : (
<GasEstimateBadge
trade={trade}
loading={syncing || loading}
showRoute={!showDetails}
disableHover={showDetails}
/>
)}
<RotatingArrow stroke={trade ? theme.text3 : theme.bg3} open={Boolean(trade && showDetails)} />
</RowFixed>
</StyledHeaderRow>
<AnimatedDropdown open={showDetails}>
<AutoColumn gap={'8px'} style={{ padding: '0', paddingBottom: '8px' }}>
{trade ? (
<StyledCard>
<AdvancedSwapDetails trade={trade} allowedSlippage={allowedSlippage} syncing={syncing} />
</StyledCard>
) : null}
{trade ? <SwapRoute trade={trade} syncing={syncing} /> : null}
</AutoColumn>
</AnimatedDropdown>
</AutoColumn>
</Wrapper>
)
}

View File

@@ -1,7 +1,6 @@
import { Trans } from '@lingui/macro'
import { Trade } from '@uniswap/router-sdk'
import { Currency, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { ReactNode } from 'react'
import { Text } from 'rebass'
@@ -14,7 +13,7 @@ export default function SwapModalFooter({
swapErrorMessage,
disabledConfirm,
}: {
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
trade: Trade<Currency, Currency, TradeType>
onConfirm: () => void
swapErrorMessage: ReactNode | undefined
disabledConfirm: boolean

View File

@@ -1,10 +1,9 @@
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 { useContext, useState } from 'react'
import { AlertTriangle, ArrowDown } from 'react-feather'
import { Text } from 'rebass'
import { InterfaceTrade } from 'state/routing/types'
import styled, { ThemeContext } from 'styled-components/macro'
import { useUSDCValue } from '../../hooks/useUSDCPrice'
@@ -46,7 +45,7 @@ export default function SwapModalHeader({
showAcceptChanges,
onAcceptChanges,
}: {
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
trade: InterfaceTrade<Currency, Currency, TradeType>
allowedSlippage: Percent
recipient: string | null
showAcceptChanges: boolean
@@ -63,19 +62,7 @@ export default function SwapModalHeader({
<AutoColumn gap={'4px'} style={{ marginTop: '1rem' }}>
<LightCard padding="0.75rem 1rem">
<AutoColumn gap={'8px'}>
<RowBetween>
<ThemedText.Body color={theme.text3} fontWeight={500} fontSize={14}>
<Trans>From</Trans>
</ThemedText.Body>
<FiatValue fiatValue={fiatValueInput} />
</RowBetween>
<RowBetween align="center">
<RowFixed gap={'0px'}>
<CurrencyLogo currency={trade.inputAmount.currency} size={'20px'} style={{ marginRight: '12px' }} />
<Text fontSize={20} fontWeight={500}>
{trade.inputAmount.currency.symbol}
</Text>
</RowFixed>
<RowFixed gap={'0px'}>
<TruncatedText
fontSize={24}
@@ -85,6 +72,15 @@ export default function SwapModalHeader({
{trade.inputAmount.toSignificant(6)}
</TruncatedText>
</RowFixed>
<RowFixed gap={'0px'}>
<CurrencyLogo currency={trade.inputAmount.currency} size={'20px'} style={{ marginRight: '12px' }} />
<Text fontSize={20} fontWeight={500}>
{trade.inputAmount.currency.symbol}
</Text>
</RowFixed>
</RowBetween>
<RowBetween>
<FiatValue fiatValue={fiatValueInput} />
</RowBetween>
</AutoColumn>
</LightCard>
@@ -93,10 +89,20 @@ export default function SwapModalHeader({
</ArrowWrapper>
<LightCard padding="0.75rem 1rem" style={{ marginBottom: '0.25rem' }}>
<AutoColumn gap={'8px'}>
<RowBetween align="flex-end">
<RowFixed gap={'0px'}>
<TruncatedText fontSize={24} fontWeight={500}>
{trade.outputAmount.toSignificant(6)}
</TruncatedText>
</RowFixed>
<RowFixed gap={'0px'}>
<CurrencyLogo currency={trade.outputAmount.currency} size={'20px'} style={{ marginRight: '12px' }} />
<Text fontSize={20} fontWeight={500}>
{trade.outputAmount.currency.symbol}
</Text>
</RowFixed>
</RowBetween>
<RowBetween>
<ThemedText.Body color={theme.text3} fontWeight={500} fontSize={14}>
<Trans>To</Trans>
</ThemedText.Body>
<ThemedText.Body fontSize={14} color={theme.text3}>
<FiatValue
fiatValue={fiatValueOutput}
@@ -104,32 +110,14 @@ export default function SwapModalHeader({
/>
</ThemedText.Body>
</RowBetween>
<RowBetween align="flex-end">
<RowFixed gap={'0px'}>
<CurrencyLogo currency={trade.outputAmount.currency} size={'20px'} style={{ marginRight: '12px' }} />
<Text fontSize={20} fontWeight={500}>
{trade.outputAmount.currency.symbol}
</Text>
</RowFixed>
<RowFixed gap={'0px'}>
<TruncatedText fontSize={24} fontWeight={500}>
{trade.outputAmount.toSignificant(6)}
</TruncatedText>
</RowFixed>
</RowBetween>
</AutoColumn>
</LightCard>
<RowBetween style={{ marginTop: '0.25rem', padding: '0 1rem' }}>
<ThemedText.Body color={theme.text2} fontWeight={500} fontSize={14}>
<Trans>Price</Trans>
</ThemedText.Body>
<TradePrice price={trade.executionPrice} showInverted={showInverted} setShowInverted={setShowInverted} />
</RowBetween>
<LightCard style={{ padding: '.75rem', marginTop: '0.5rem' }}>
<AdvancedSwapDetails trade={trade} allowedSlippage={allowedSlippage} />
</LightCard>
{showAcceptChanges ? (
<SwapShowAcceptChanges justify="flex-start" gap={'0px'}>
<RowBetween>

View File

@@ -1,92 +1,117 @@
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 { FeeAmount, Trade as V3Trade } from '@uniswap/v3-sdk'
import Badge from 'components/Badge'
import { Pair } from '@uniswap/v2-sdk'
import AnimatedDropdown from 'components/AnimatedDropdown'
import { AutoColumn } from 'components/Column'
import { LoadingRows } from 'components/Loader/styled'
import RoutingDiagram, { RoutingDiagramEntry } from 'components/RoutingDiagram/RoutingDiagram'
import { AutoRow, RowBetween } from 'components/Row'
import { Version } from 'hooks/useToggledVersion'
import { memo } from 'react'
import { useRoutingAPIEnabled } from 'state/user/hooks'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useAutoRouterSupported from 'hooks/useAutoRouterSupported'
import { memo, useState } from 'react'
import { Plus } from 'react-feather'
import { InterfaceTrade } from 'state/routing/types'
import { useDarkModeManager } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { getTradeVersion } from 'utils/getTradeVersion'
import { Separator, ThemedText } from 'theme'
import { AutoRouterLabel, AutoRouterLogo } from './RouterLabel'
const Separator = styled.div`
border-top: 1px solid ${({ theme }) => theme.bg2};
height: 1px;
width: 100%;
const Wrapper = styled(AutoColumn)<{ darkMode?: boolean; fixedOpen?: boolean }>`
padding: ${({ fixedOpen }) => (fixedOpen ? '12px' : '12px 8px 12px 12px')};
border-radius: 16px;
border: 1px solid ${({ theme, fixedOpen }) => (fixedOpen ? 'transparent' : theme.bg2)};
cursor: pointer;
`
const OpenCloseIcon = styled(Plus)<{ open?: boolean }>`
margin-left: 8px;
height: 20px;
stroke-width: 2px;
transition: transform 0.1s;
transform: ${({ open }) => (open ? 'rotate(45deg)' : 'none')};
stroke: ${({ theme }) => theme.text3};
cursor: pointer;
:hover {
opacity: 0.8;
}
`
const V2_DEFAULT_FEE_TIER = 3000
export default memo(function SwapRoute({
trade,
syncing,
}: {
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
interface SwapRouteProps extends React.HTMLAttributes<HTMLDivElement> {
trade: InterfaceTrade<Currency, Currency, TradeType>
syncing: boolean
}) {
const routingAPIEnabled = useRoutingAPIEnabled()
fixedOpen?: boolean // fixed in open state, hide open/close icon
}
export default memo(function SwapRoute({ trade, syncing, fixedOpen = false, ...rest }: SwapRouteProps) {
const autoRouterSupported = useAutoRouterSupported()
const routes = getTokenPath(trade)
const [open, setOpen] = useState(false)
const { chainId } = useActiveWeb3React()
const [darkMode] = useDarkModeManager()
const formattedGasPriceString = trade?.gasUseEstimateUSD
? trade.gasUseEstimateUSD.toFixed(2) === '0.00'
? '<$0.01'
: '$' + trade.gasUseEstimateUSD.toFixed(2)
: undefined
return (
<AutoColumn gap="12px">
<RowBetween>
<Wrapper {...rest} darkMode={darkMode} fixedOpen={fixedOpen}>
<RowBetween onClick={() => setOpen(!open)}>
<AutoRow gap="4px" width="auto">
<AutoRouterLogo />
<AutoRouterLabel />
</AutoRow>
{syncing ? (
<LoadingRows>
<div style={{ width: '30px', height: '24px' }} />
</LoadingRows>
) : (
<Badge>
<ThemedText.Black fontSize={12}>
{getTradeVersion(trade) === Version.v2 ? <Trans>V2</Trans> : <Trans>V3</Trans>}
</ThemedText.Black>
</Badge>
)}
{fixedOpen ? null : <OpenCloseIcon open={open} />}
</RowBetween>
<Separator />
{syncing ? (
<LoadingRows>
<div style={{ width: '400px', height: '30px' }} />
</LoadingRows>
) : (
<RoutingDiagram
currencyIn={trade.inputAmount.currency}
currencyOut={trade.outputAmount.currency}
routes={getTokenPath(trade)}
/>
)}
{routingAPIEnabled && (
<ThemedText.Main fontSize={12} width={400}>
<Trans>This route optimizes your price by considering split routes, multiple hops, and gas costs.</Trans>
</ThemedText.Main>
)}
</AutoColumn>
<AnimatedDropdown open={open || fixedOpen}>
<AutoRow gap="4px" width="auto" style={{ paddingTop: '12px', margin: 0 }}>
{syncing ? (
<LoadingRows>
<div style={{ width: '400px', height: '30px' }} />
</LoadingRows>
) : (
<RoutingDiagram
currencyIn={trade.inputAmount.currency}
currencyOut={trade.outputAmount.currency}
routes={routes}
/>
)}
{autoRouterSupported && (
<>
<Separator />
{syncing ? (
<LoadingRows>
<div style={{ width: '250px', height: '15px' }} />
</LoadingRows>
) : (
<ThemedText.Main fontSize={12} width={400} margin={0}>
{trade?.gasUseEstimateUSD && chainId && SUPPORTED_GAS_ESTIMATE_CHAIN_IDS.includes(chainId) ? (
<Trans>Best price route costs ~{formattedGasPriceString} in gas. </Trans>
) : null}{' '}
<Trans>
This route optimizes your total output by considering split routes, multiple hops, and the gas cost
of each step.
</Trans>
</ThemedText.Main>
)}
</>
)}
</AutoRow>
</AnimatedDropdown>
</Wrapper>
)
})
function getTokenPath(
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>
): RoutingDiagramEntry[] {
// convert V2 path to a list of routes
if (trade instanceof V2Trade) {
const { path: tokenPath } = (trade as V2Trade<Currency, Currency, TradeType>).route
const path = []
for (let i = 1; i < tokenPath.length; i++) {
path.push([tokenPath[i - 1], tokenPath[i], V2_DEFAULT_FEE_TIER] as RoutingDiagramEntry['path'][0])
}
return [{ percent: new Percent(100, 100), path }]
}
return trade.swaps.map(({ route: { tokenPath, pools }, inputAmount, outputAmount }) => {
function getTokenPath(trade: Trade<Currency, Currency, TradeType>): RoutingDiagramEntry[] {
return trade.swaps.map(({ route: { path: tokenPath, pools, protocol }, inputAmount, outputAmount }) => {
const portion =
trade.tradeType === TradeType.EXACT_INPUT
? inputAmount.divide(trade.inputAmount)
@@ -94,18 +119,25 @@ function getTokenPath(
const percent = new Percent(portion.numerator, portion.denominator)
const path: [Currency, Currency, FeeAmount][] = []
const path: RoutingDiagramEntry['path'] = []
for (let i = 0; i < pools.length; i++) {
const nextPool = pools[i]
const tokenIn = tokenPath[i]
const tokenOut = tokenPath[i + 1]
path.push([tokenIn, tokenOut, nextPool.fee])
const entry: RoutingDiagramEntry['path'][0] = [
tokenIn,
tokenOut,
nextPool instanceof Pair ? V2_DEFAULT_FEE_TIER : nextPool.fee,
]
path.push(entry)
}
return {
percent,
path,
protocol,
}
})
}

View File

@@ -0,0 +1,75 @@
import { Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Token, TradeType } from '@uniswap/sdk-core'
import { RowBetween } from 'components/Row'
import { MouseoverTooltipContent } from 'components/Tooltip'
import { Info } from 'react-feather'
import { InterfaceTrade } from 'state/routing/types'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { ResponsiveTooltipContainer } from './styleds'
const Wrapper = styled.div`
background-color: ${({ theme }) => theme.bg1};
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
padding: 14px;
margin-top: -20px;
padding-top: 32px;
`
const StyledInfoIcon = styled(Info)`
stroke: ${({ theme }) => theme.text3};
`
/**
* @returns Dropdown card for showing edge case warnings outside of button
*/
export default function SwapWarningDropdown({
fiatValueInput,
trade,
}: {
fiatValueInput: CurrencyAmount<Token> | null
trade: InterfaceTrade<Currency, Currency, TradeType> | undefined
}) {
// gas cost estimate is more than half of input value
const showNetworkFeeWarning = Boolean(
fiatValueInput &&
trade?.gasUseEstimateUSD &&
parseFloat(trade.gasUseEstimateUSD.toSignificant(6)) > parseFloat(fiatValueInput.toFixed(6)) / 2
)
if (!showNetworkFeeWarning) {
return null
}
return (
<Wrapper>
{showNetworkFeeWarning ? (
<RowBetween>
<ThemedText.Main fontSize="14px" color="text3">
<Trans>Network fees exceed 50% of the swap amount!</Trans>
</ThemedText.Main>
<MouseoverTooltipContent
wrap={false}
content={
<ResponsiveTooltipContainer origin="top right" style={{ padding: '12px' }}>
<ThemedText.Main fontSize="12px" color="text3" maxWidth="200px">
<Trans>
The cost of sending this transaction is more than half of the value of the input amount.
</Trans>
</ThemedText.Main>
<ThemedText.Main fontSize="12px" color="text3" maxWidth="200px" mt="8px">
<Trans>You might consider waiting until the network fees go down to complete this transaction.</Trans>
</ThemedText.Main>
</ResponsiveTooltipContainer>
}
placement="bottom"
>
<StyledInfoIcon size={16} />
</MouseoverTooltipContent>
</RowBetween>
) : null}
</Wrapper>
)
}

View File

@@ -13,16 +13,20 @@ interface TradePriceProps {
}
const StyledPriceContainer = styled.button`
align-items: center;
background-color: transparent;
border: none;
cursor: pointer;
display: grid;
height: 24px;
justify-content: center;
align-items: center;
justify-content: flex-start;
padding: 0;
grid-template-columns: 1fr auto;
grid-gap: 0.25rem;
display: flex;
flex-direction: row;
text-align: left;
flex-wrap: wrap;
padding: 8px 0;
user-select: text;
`
export default function TradePrice({ price, showInverted, setShowInverted }: TradePriceProps) {
@@ -44,8 +48,14 @@ export default function TradePrice({ price, showInverted, setShowInverted }: Tra
const text = `${'1 ' + labelInverted + ' = ' + formattedPrice ?? '-'} ${label}`
return (
<StyledPriceContainer onClick={flipPrice} title={text}>
<Text fontWeight={500} fontSize={14} color={theme.text1}>
<StyledPriceContainer
onClick={(e) => {
e.stopPropagation() // dont want this click to affect dropdowns / hovers
flipPrice()
}}
title={text}
>
<Text fontWeight={500} color={theme.text1}>
{text}
</Text>{' '}
{usdcPrice && (

View File

@@ -6,7 +6,7 @@ import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import Modal from 'components/Modal'
import { AutoRow, RowBetween } from 'components/Row'
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useState } from 'react'
import styled from 'styled-components/macro'
import { CloseIcon, ExternalLink, ThemedText, Z_INDEX } from 'theme'

View File

@@ -1,5 +1,6 @@
import { isAddress } from '@ethersproject/address'
import { Trans } from '@lingui/macro'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { ReactNode, useState } from 'react'
import { X } from 'react-feather'
import styled from 'styled-components/macro'
@@ -7,7 +8,6 @@ import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
import { UNI } from '../../constants/tokens'
import useENS from '../../hooks/useENS'
import { useActiveWeb3React } from '../../hooks/web3'
import { useDelegateCallback } from '../../state/governance/hooks'
import { useTokenBalance } from '../../state/wallet/hooks'
import { ThemedText } from '../../theme'

View File

@@ -1,6 +1,6 @@
import { Trans } from '@lingui/macro'
import { L2_CHAIN_IDS } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import { SupportedChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
@@ -38,7 +38,7 @@ const EmptyState = ({ HeaderContent, SubHeaderContent }: EmptyStateProps) => (
export default function ProposalEmptyState() {
const { chainId } = useActiveWeb3React()
if (chainId && L2_CHAIN_IDS.includes(chainId)) {
if (chainId && chainId !== SupportedChainId.MAINNET) {
return (
<EmptyState
HeaderContent={() => <Trans>Please connect to Layer 1 Ethereum</Trans>}

View File

@@ -1,11 +1,11 @@
import { Trans } from '@lingui/macro'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useContext, useState } from 'react'
import { ArrowUpCircle, X } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
import Circle from '../../assets/images/blue-loader.svg'
import { useActiveWeb3React } from '../../hooks/web3'
import { useUserVotes, useVoteCallback } from '../../state/governance/hooks'
import { VoteOption } from '../../state/governance/types'
import { CustomLightSpinner, ThemedText } from '../../theme'

View File

@@ -36,11 +36,14 @@ class MiniRpcProvider implements AsyncSendable {
public readonly path: string
public readonly batchWaitTimeMs: number
private readonly connector: NetworkConnector
private nextId = 1
private batchTimeoutId: ReturnType<typeof setTimeout> | null = null
private batch: BatchItem[] = []
constructor(chainId: number, url: string, batchWaitTimeMs?: number) {
constructor(connector: NetworkConnector, chainId: number, url: string, batchWaitTimeMs?: number) {
this.connector = connector
this.chainId = chainId
this.url = url
const parsed = new URL(url)
@@ -52,7 +55,21 @@ class MiniRpcProvider implements AsyncSendable {
public readonly clearBatch = async () => {
console.debug('Clearing batch', this.batch)
const batch = this.batch
let batch = this.batch
batch = batch.filter((b) => {
if (b.request.method === 'wallet_switchEthereumChain') {
try {
this.connector.changeChainId(parseInt((b.request.params as [{ chainId: string }])[0].chainId))
b.resolve({ id: b.request.id })
} catch (error) {
b.reject(error)
}
return false
}
return true
})
this.batch = []
this.batchTimeoutId = null
let response: Response
@@ -148,9 +165,9 @@ export class NetworkConnector extends AbstractConnector {
invariant(defaultChainId || Object.keys(urls).length === 1, 'defaultChainId is a required argument with >1 url')
super({ supportedChainIds: Object.keys(urls).map((k): number => Number(k)) })
this.currentChainId = defaultChainId || Number(Object.keys(urls)[0])
this.currentChainId = defaultChainId ?? Number(Object.keys(urls)[0])
this.providers = Object.keys(urls).reduce<{ [chainId: number]: MiniRpcProvider }>((accumulator, chainId) => {
accumulator[Number(chainId)] = new MiniRpcProvider(Number(chainId), urls[Number(chainId)])
accumulator[Number(chainId)] = new MiniRpcProvider(this, Number(chainId), urls[Number(chainId)])
return accumulator
}, {})
}
@@ -178,4 +195,21 @@ export class NetworkConnector extends AbstractConnector {
public deactivate() {
return
}
/**
* Meant to be called only by MiniRpcProvider
* @param chainId the new chain id
*/
public changeChainId(chainId: number) {
if (chainId in this.providers) {
this.currentChainId = chainId
this.emitUpdate({
chainId,
account: null,
provider: this.providers[chainId],
})
} else {
throw new Error(`Unsupported chain ID: ${chainId}`)
}
}
}

View File

@@ -4,35 +4,19 @@ import { InjectedConnector } from '@web3-react/injected-connector'
import { PortisConnector } from '@web3-react/portis-connector'
import { WalletConnectConnector } from '@web3-react/walletconnect-connector'
import { WalletLinkConnector } from '@web3-react/walletlink-connector'
import { INFURA_NETWORK_URLS } from 'constants/chainInfo'
import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from 'constants/chains'
import UNISWAP_LOGO_URL from '../assets/svg/logo.svg'
import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from '../constants/chains'
import getLibrary from '../utils/getLibrary'
import { FortmaticConnector } from './Fortmatic'
import { NetworkConnector } from './NetworkConnector'
const INFURA_KEY = process.env.REACT_APP_INFURA_KEY
const FORMATIC_KEY = process.env.REACT_APP_FORTMATIC_KEY
const PORTIS_ID = process.env.REACT_APP_PORTIS_ID
if (typeof INFURA_KEY === 'undefined') {
throw new Error(`REACT_APP_INFURA_KEY must be a defined environment variable`)
}
const NETWORK_URLS: { [key in SupportedChainId]: string } = {
[SupportedChainId.MAINNET]: `https://mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.RINKEBY]: `https://rinkeby.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.ROPSTEN]: `https://ropsten.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.GOERLI]: `https://goerli.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.KOVAN]: `https://kovan.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.OPTIMISM]: `https://optimism-mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.OPTIMISTIC_KOVAN]: `https://optimism-kovan.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.ARBITRUM_ONE]: `https://arbitrum-mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.ARBITRUM_RINKEBY]: `https://arbitrum-rinkeby.infura.io/v3/${INFURA_KEY}`,
}
export const network = new NetworkConnector({
urls: NETWORK_URLS,
urls: INFURA_NETWORK_URLS,
defaultChainId: 1,
})
@@ -49,7 +33,7 @@ export const gnosisSafe = new SafeAppConnector()
export const walletconnect = new WalletConnectConnector({
supportedChainIds: ALL_SUPPORTED_CHAIN_IDS,
rpc: NETWORK_URLS,
rpc: INFURA_NETWORK_URLS,
qrcode: true,
})
@@ -65,9 +49,9 @@ export const portis = new PortisConnector({
networks: [1],
})
// mainnet only
export const walletlink = new WalletLinkConnector({
url: NETWORK_URLS[SupportedChainId.MAINNET],
url: INFURA_NETWORK_URLS[SupportedChainId.MAINNET],
appName: 'Uniswap',
appLogoUrl: UNISWAP_LOGO_URL,
supportedChainIds: [SupportedChainId.MAINNET, SupportedChainId.POLYGON],
})

View File

@@ -11,12 +11,31 @@ export const MULTICALL_ADDRESS: AddressMap = {
...constructSameAddressMap('0x1F98415757620B543A52E61c46B32eB19261F984', [
SupportedChainId.OPTIMISTIC_KOVAN,
SupportedChainId.OPTIMISM,
SupportedChainId.POLYGON_MUMBAI,
SupportedChainId.POLYGON,
]),
[SupportedChainId.ARBITRUM_ONE]: '0xadF885960B47eA2CD9B55E6DAc6B42b7Cb2806dB',
[SupportedChainId.ARBITRUM_RINKEBY]: '0xa501c031958F579dB7676fF1CE78AD305794d579',
}
export const V2_FACTORY_ADDRESSES: AddressMap = constructSameAddressMap(V2_FACTORY_ADDRESS)
export const V2_ROUTER_ADDRESS: AddressMap = constructSameAddressMap('0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D')
export const V3_ROUTER_ADDRESS: AddressMap = constructSameAddressMap('0xE592427A0AEce92De3Edee1F18E0157C05861564', [
SupportedChainId.OPTIMISM,
SupportedChainId.OPTIMISTIC_KOVAN,
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
SupportedChainId.POLYGON,
SupportedChainId.POLYGON_MUMBAI,
])
export const SWAP_ROUTER_ADDRESSES: AddressMap = constructSameAddressMap('0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45', [
SupportedChainId.OPTIMISM,
SupportedChainId.OPTIMISTIC_KOVAN,
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
SupportedChainId.POLYGON,
SupportedChainId.POLYGON_MUMBAI,
])
/**
* The oldest V0 governance address
@@ -50,12 +69,16 @@ export const V3_CORE_FACTORY_ADDRESSES: AddressMap = constructSameAddressMap(V3_
SupportedChainId.OPTIMISTIC_KOVAN,
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
SupportedChainId.POLYGON_MUMBAI,
SupportedChainId.POLYGON,
])
export const QUOTER_ADDRESSES: AddressMap = constructSameAddressMap('0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6', [
SupportedChainId.OPTIMISM,
SupportedChainId.OPTIMISTIC_KOVAN,
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
SupportedChainId.POLYGON_MUMBAI,
SupportedChainId.POLYGON,
])
export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES: AddressMap = constructSameAddressMap(
'0xC36442b4a4522E871399CD717aBDD847Ab11FE88',
@@ -64,6 +87,8 @@ export const NONFUNGIBLE_POSITION_MANAGER_ADDRESSES: AddressMap = constructSameA
SupportedChainId.OPTIMISTIC_KOVAN,
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
SupportedChainId.POLYGON_MUMBAI,
SupportedChainId.POLYGON,
]
)
export const ENS_REGISTRAR_ADDRESSES: AddressMap = {
@@ -75,13 +100,15 @@ export const ENS_REGISTRAR_ADDRESSES: AddressMap = {
export const SOCKS_CONTROLLER_ADDRESSES: AddressMap = {
[SupportedChainId.MAINNET]: '0x65770b5283117639760beA3F867b69b3697a91dd',
}
export const SWAP_ROUTER_ADDRESSES: AddressMap = constructSameAddressMap('0xE592427A0AEce92De3Edee1F18E0157C05861564', [
SupportedChainId.OPTIMISM,
SupportedChainId.OPTIMISTIC_KOVAN,
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
])
export const V3_MIGRATOR_ADDRESSES: AddressMap = constructSameAddressMap('0xA5644E29708357803b5A882D272c41cC0dF92B34', [
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
SupportedChainId.POLYGON_MUMBAI,
SupportedChainId.POLYGON,
])
export const TICK_LENS_ADDRESSES: AddressMap = {
[SupportedChainId.ARBITRUM_ONE]: '0xbfd8137f7d1516D3ea5cA83523914859ec47F573',
[SupportedChainId.ARBITRUM_RINKEBY]: '0xbfd8137f7d1516D3ea5cA83523914859ec47F573',
}

233
src/constants/chainInfo.ts Normal file
View File

@@ -0,0 +1,233 @@
import ms from 'ms.macro'
import ethereumLogoUrl from '../assets/images/ethereum-logo.png'
import arbitrumLogoUrl from '../assets/svg/arbitrum_logo.svg'
import optimismLogoUrl from '../assets/svg/optimistic_ethereum.svg'
import polygonMaticLogo from '../assets/svg/polygon-matic-logo.svg'
import { SupportedChainId, SupportedL1ChainId, SupportedL2ChainId } from './chains'
import { ARBITRUM_LIST, OPTIMISM_LIST } from './lists'
const INFURA_KEY = process.env.REACT_APP_INFURA_KEY
if (typeof INFURA_KEY === 'undefined') {
throw new Error(`REACT_APP_INFURA_KEY must be a defined environment variable`)
}
/**
* These are the network URLs used by the interface when there is not another available source of chain data
*/
export const INFURA_NETWORK_URLS: { [key in SupportedChainId]: string } = {
[SupportedChainId.MAINNET]: `https://mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.RINKEBY]: `https://rinkeby.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.ROPSTEN]: `https://ropsten.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.GOERLI]: `https://goerli.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.KOVAN]: `https://kovan.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.OPTIMISM]: `https://optimism-mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.OPTIMISTIC_KOVAN]: `https://optimism-kovan.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.ARBITRUM_ONE]: `https://arbitrum-mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.ARBITRUM_RINKEBY]: `https://arbitrum-rinkeby.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.POLYGON]: `https://polygon-mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.POLYGON_MUMBAI]: `https://polygon-mumbai.infura.io/v3/${INFURA_KEY}`,
}
/**
* This is used to call the add network RPC
*/
interface AddNetworkInfo {
readonly rpcUrl: string
readonly nativeCurrency: {
name: string // e.g. 'Goerli ETH',
symbol: string // e.g. 'gorETH',
decimals: number // e.g. 18,
}
}
export enum NetworkType {
L1,
L2,
}
interface BaseChainInfo {
readonly networkType: NetworkType
readonly blockWaitMsBeforeWarning?: number
readonly docs: string
readonly bridge?: string
readonly explorer: string
readonly infoLink: string
readonly logoUrl: string
readonly label: string
readonly helpCenterUrl?: string
readonly addNetworkInfo: AddNetworkInfo
}
export interface L1ChainInfo extends BaseChainInfo {
readonly networkType: NetworkType.L1
}
export interface L2ChainInfo extends BaseChainInfo {
readonly networkType: NetworkType.L2
readonly bridge: string
readonly statusPage?: string
readonly defaultListUrl: string
}
export type ChainInfoMap = { readonly [chainId: number]: L1ChainInfo | L2ChainInfo } & {
readonly [chainId in SupportedL2ChainId]: L2ChainInfo
} &
{ readonly [chainId in SupportedL1ChainId]: L1ChainInfo }
export const CHAIN_INFO: ChainInfoMap = {
[SupportedChainId.MAINNET]: {
networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/',
explorer: 'https://etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Ethereum',
logoUrl: ethereumLogoUrl,
addNetworkInfo: {
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrl: INFURA_NETWORK_URLS[SupportedChainId.MAINNET],
},
},
[SupportedChainId.RINKEBY]: {
networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/',
explorer: 'https://rinkeby.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Rinkeby',
logoUrl: ethereumLogoUrl,
addNetworkInfo: {
nativeCurrency: { name: 'Rinkeby Ether', symbol: 'rETH', decimals: 18 },
rpcUrl: INFURA_NETWORK_URLS[SupportedChainId.RINKEBY],
},
},
[SupportedChainId.ROPSTEN]: {
networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/',
explorer: 'https://ropsten.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Ropsten',
logoUrl: ethereumLogoUrl,
addNetworkInfo: {
nativeCurrency: { name: 'Ropsten Ether', symbol: 'ropETH', decimals: 18 },
rpcUrl: INFURA_NETWORK_URLS[SupportedChainId.ROPSTEN],
},
},
[SupportedChainId.KOVAN]: {
networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/',
explorer: 'https://kovan.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Kovan',
logoUrl: ethereumLogoUrl,
addNetworkInfo: {
nativeCurrency: { name: 'Kovan Ether', symbol: 'kovETH', decimals: 18 },
rpcUrl: INFURA_NETWORK_URLS[SupportedChainId.KOVAN],
},
},
[SupportedChainId.GOERLI]: {
networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/',
explorer: 'https://goerli.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Görli',
logoUrl: ethereumLogoUrl,
addNetworkInfo: {
nativeCurrency: { name: 'Görli Ether', symbol: 'görETH', decimals: 18 },
rpcUrl: INFURA_NETWORK_URLS[SupportedChainId.GOERLI],
},
},
[SupportedChainId.OPTIMISM]: {
networkType: NetworkType.L2,
blockWaitMsBeforeWarning: ms`25m`,
bridge: 'https://gateway.optimism.io/?chainId=1',
defaultListUrl: OPTIMISM_LIST,
docs: 'https://optimism.io/',
explorer: 'https://optimistic.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/optimism/',
label: 'Optimism',
logoUrl: optimismLogoUrl,
statusPage: 'https://optimism.io/status',
helpCenterUrl: 'https://help.uniswap.org/en/collections/3137778-uniswap-on-optimistic-ethereum-oξ',
addNetworkInfo: {
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrl: 'https://mainnet.optimism.io',
},
},
[SupportedChainId.OPTIMISTIC_KOVAN]: {
networkType: NetworkType.L2,
blockWaitMsBeforeWarning: ms`25m`,
bridge: 'https://gateway.optimism.io/',
defaultListUrl: OPTIMISM_LIST,
docs: 'https://optimism.io/',
explorer: 'https://optimistic.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/optimism/',
label: 'Optimistic Kovan',
logoUrl: optimismLogoUrl,
statusPage: 'https://optimism.io/status',
helpCenterUrl: 'https://help.uniswap.org/en/collections/3137778-uniswap-on-optimistic-ethereum-oξ',
addNetworkInfo: {
nativeCurrency: { name: 'Optimistic Kovan Ether', symbol: 'kovOpETH', decimals: 18 },
rpcUrl: 'https://kovan.optimism.io',
},
},
[SupportedChainId.ARBITRUM_ONE]: {
networkType: NetworkType.L2,
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://bridge.arbitrum.io/',
docs: 'https://offchainlabs.com/',
explorer: 'https://arbiscan.io/',
infoLink: 'https://info.uniswap.org/#/arbitrum',
label: 'Arbitrum',
logoUrl: arbitrumLogoUrl,
defaultListUrl: ARBITRUM_LIST,
helpCenterUrl: 'https://help.uniswap.org/en/collections/3137787-uniswap-on-arbitrum',
addNetworkInfo: {
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
rpcUrl: 'https://arb1.arbitrum.io/rpc',
},
},
[SupportedChainId.ARBITRUM_RINKEBY]: {
networkType: NetworkType.L2,
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://bridge.arbitrum.io/',
docs: 'https://offchainlabs.com/',
explorer: 'https://rinkeby-explorer.arbitrum.io/',
infoLink: 'https://info.uniswap.org/#/arbitrum/',
label: 'Arbitrum Rinkeby',
logoUrl: arbitrumLogoUrl,
defaultListUrl: ARBITRUM_LIST,
helpCenterUrl: 'https://help.uniswap.org/en/collections/3137787-uniswap-on-arbitrum',
addNetworkInfo: {
nativeCurrency: { name: 'Rinkeby Arbitrum Ether', symbol: 'rinkArbETH', decimals: 18 },
rpcUrl: 'https://rinkeby.arbitrum.io/rpc',
},
},
[SupportedChainId.POLYGON]: {
networkType: NetworkType.L1,
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://wallet.polygon.technology/bridge',
docs: 'https://polygon.io/',
explorer: 'https://polygonscan.com/',
infoLink: 'https://info.uniswap.org/#/polygon/',
label: 'Polygon',
logoUrl: polygonMaticLogo,
addNetworkInfo: {
rpcUrl: 'https://polygon-rpc.com/',
nativeCurrency: { name: 'Polygon Matic', symbol: 'MATIC', decimals: 18 },
},
},
[SupportedChainId.POLYGON_MUMBAI]: {
networkType: NetworkType.L1,
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://wallet.polygon.technology/bridge',
docs: 'https://polygon.io/',
explorer: 'https://mumbai.polygonscan.com/',
infoLink: 'https://info.uniswap.org/#/polygon/',
label: 'Polygon Mumbai',
logoUrl: polygonMaticLogo,
addNetworkInfo: {
nativeCurrency: { name: 'Polygon Mumbai Matic', symbol: 'mMATIC', decimals: 18 },
rpcUrl: 'https://rpc-endpoints.superfluid.dev/mumbai',
},
},
}

View File

@@ -1,10 +1,6 @@
import ethereumLogoUrl from 'assets/images/ethereum-logo.png'
import arbitrumLogoUrl from 'assets/svg/arbitrum_logo.svg'
import optimismLogoUrl from 'assets/svg/optimistic_ethereum.svg'
import ms from 'ms.macro'
import { ARBITRUM_LIST, OPTIMISM_LIST } from './lists'
/**
* List of all the networks supported by the Uniswap Interface
*/
export enum SupportedChainId {
MAINNET = 1,
ROPSTEN = 3,
@@ -14,33 +10,56 @@ export enum SupportedChainId {
ARBITRUM_ONE = 42161,
ARBITRUM_RINKEBY = 421611,
OPTIMISM = 10,
OPTIMISTIC_KOVAN = 69,
POLYGON = 137,
POLYGON_MUMBAI = 80001,
}
export const ALL_SUPPORTED_CHAIN_IDS: SupportedChainId[] = [
SupportedChainId.MAINNET,
SupportedChainId.ROPSTEN,
SupportedChainId.RINKEBY,
SupportedChainId.GOERLI,
SupportedChainId.KOVAN,
export const CHAIN_IDS_TO_NAMES = {
[SupportedChainId.MAINNET]: 'mainnet',
[SupportedChainId.ROPSTEN]: 'ropsten',
[SupportedChainId.RINKEBY]: 'rinkeby',
[SupportedChainId.GOERLI]: 'goerli',
[SupportedChainId.KOVAN]: 'kovan',
[SupportedChainId.POLYGON]: 'polygon',
[SupportedChainId.POLYGON_MUMBAI]: 'polygon_mumbai',
[SupportedChainId.ARBITRUM_ONE]: 'arbitrum',
[SupportedChainId.ARBITRUM_RINKEBY]: 'arbitrum_rinkeby',
[SupportedChainId.OPTIMISM]: 'optimism',
[SupportedChainId.OPTIMISTIC_KOVAN]: 'optimistic_kovan',
}
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
SupportedChainId.OPTIMISM,
SupportedChainId.OPTIMISTIC_KOVAN,
]
/**
* Array of all the supported chain IDs
*/
export const ALL_SUPPORTED_CHAIN_IDS: SupportedChainId[] = Object.values(SupportedChainId).filter(
(id) => typeof id === 'number'
) as SupportedChainId[]
export const SUPPORTED_GAS_ESTIMATE_CHAIN_IDS = [SupportedChainId.MAINNET, SupportedChainId.POLYGON]
/**
* All the chain IDs that are running the Ethereum protocol.
*/
export const L1_CHAIN_IDS = [
SupportedChainId.MAINNET,
SupportedChainId.ROPSTEN,
SupportedChainId.RINKEBY,
SupportedChainId.GOERLI,
SupportedChainId.KOVAN,
SupportedChainId.POLYGON,
SupportedChainId.POLYGON_MUMBAI,
] as const
export type SupportedL1ChainId = typeof L1_CHAIN_IDS[number]
/**
* Controls some L2 specific behavior, e.g. slippage tolerance, special UI behavior.
* The expectation is that all of these networks have immediate transaction confirmation.
*/
export const L2_CHAIN_IDS = [
SupportedChainId.ARBITRUM_ONE,
SupportedChainId.ARBITRUM_RINKEBY,
@@ -49,120 +68,3 @@ export const L2_CHAIN_IDS = [
] as const
export type SupportedL2ChainId = typeof L2_CHAIN_IDS[number]
export interface L1ChainInfo {
readonly blockWaitMsBeforeWarning?: number
readonly docs: string
readonly explorer: string
readonly infoLink: string
readonly label: string
readonly logoUrl?: string
readonly rpcUrls?: string[]
readonly nativeCurrency: {
name: string // 'Goerli ETH',
symbol: string // 'gorETH',
decimals: number //18,
}
}
export interface L2ChainInfo extends L1ChainInfo {
readonly bridge: string
readonly logoUrl: string
readonly statusPage?: string
readonly defaultListUrl: string
}
export type ChainInfo = { readonly [chainId: number]: L1ChainInfo | L2ChainInfo } & {
readonly [chainId in SupportedL2ChainId]: L2ChainInfo
} &
{ readonly [chainId in SupportedL1ChainId]: L1ChainInfo }
export const CHAIN_INFO: ChainInfo = {
[SupportedChainId.ARBITRUM_ONE]: {
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://bridge.arbitrum.io/',
defaultListUrl: ARBITRUM_LIST,
docs: 'https://offchainlabs.com/',
explorer: 'https://arbiscan.io/',
infoLink: 'https://info.uniswap.org/#/arbitrum/',
label: 'Arbitrum',
logoUrl: arbitrumLogoUrl,
nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
rpcUrls: ['https://arb1.arbitrum.io/rpc'],
},
[SupportedChainId.ARBITRUM_RINKEBY]: {
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://bridge.arbitrum.io/',
defaultListUrl: ARBITRUM_LIST,
docs: 'https://offchainlabs.com/',
explorer: 'https://rinkeby-explorer.arbitrum.io/',
infoLink: 'https://info.uniswap.org/#/arbitrum/',
label: 'Arbitrum Rinkeby',
logoUrl: arbitrumLogoUrl,
nativeCurrency: { name: 'Rinkeby ArbETH', symbol: 'rinkArbETH', decimals: 18 },
rpcUrls: ['https://rinkeby.arbitrum.io/rpc'],
},
[SupportedChainId.MAINNET]: {
docs: 'https://docs.uniswap.org/',
explorer: 'https://etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Ethereum',
logoUrl: ethereumLogoUrl,
nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
},
[SupportedChainId.RINKEBY]: {
docs: 'https://docs.uniswap.org/',
explorer: 'https://rinkeby.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Rinkeby',
nativeCurrency: { name: 'Rinkeby ETH', symbol: 'rinkETH', decimals: 18 },
},
[SupportedChainId.ROPSTEN]: {
docs: 'https://docs.uniswap.org/',
explorer: 'https://ropsten.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Ropsten',
nativeCurrency: { name: 'Ropsten ETH', symbol: 'ropETH', decimals: 18 },
},
[SupportedChainId.KOVAN]: {
docs: 'https://docs.uniswap.org/',
explorer: 'https://kovan.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Kovan',
nativeCurrency: { name: 'Kovan ETH', symbol: 'kovETH', decimals: 18 },
},
[SupportedChainId.GOERLI]: {
docs: 'https://docs.uniswap.org/',
explorer: 'https://goerli.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Görli',
nativeCurrency: { name: 'Görli ETH', symbol: 'görETH', decimals: 18 },
},
[SupportedChainId.OPTIMISM]: {
blockWaitMsBeforeWarning: ms`15m`,
bridge: 'https://gateway.optimism.io/',
defaultListUrl: OPTIMISM_LIST,
docs: 'https://optimism.io/',
explorer: 'https://optimistic.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/optimism/',
label: 'OΞ',
logoUrl: optimismLogoUrl,
nativeCurrency: { name: 'Optimistic ETH', symbol: 'ETH', decimals: 18 },
rpcUrls: ['https://mainnet.optimism.io'],
},
[SupportedChainId.OPTIMISTIC_KOVAN]: {
blockWaitMsBeforeWarning: ms`15m`,
bridge: 'https://gateway.optimism.io/',
defaultListUrl: OPTIMISM_LIST,
docs: 'https://optimism.io/',
explorer: 'https://optimistic.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/optimism/',
label: 'Optimistic Kovan',
rpcUrls: ['https://kovan.optimism.io'],
logoUrl: optimismLogoUrl,
nativeCurrency: { name: 'Optimistic kovETH', symbol: 'kovOpETH', decimals: 18 },
},
}
export const ARBITRUM_HELP_CENTER_LINK = 'https://help.uniswap.org/en/collections/3137787-uniswap-on-arbitrum'
export const OPTIMISM_HELP_CENTER_LINK =
'https://help.uniswap.org/en/collections/3137778-uniswap-on-optimistic-ethereum-oξ'

View File

@@ -1,3 +1,4 @@
const UNI_LIST = 'https://tokens.uniswap.org'
const AAVE_LIST = 'tokenlist.aave.eth'
const BA_LIST = 'https://raw.githubusercontent.com/The-Blockchain-Association/sec-notice-list/master/ba-sec-list.json'
const CMC_ALL_LIST = 'https://api.coinmarketcap.com/data-api/v3/uniswap/all.json'
@@ -16,6 +17,7 @@ export const UNSUPPORTED_LIST_URLS: string[] = [BA_LIST]
// this is the default list of lists that are exposed to users
// lower index == higher priority for token import
const DEFAULT_LIST_OF_LISTS_TO_DISPLAY: string[] = [
UNI_LIST,
COMPOUND_LIST,
AAVE_LIST,
CMC_ALL_LIST,
@@ -35,4 +37,4 @@ export const DEFAULT_LIST_OF_LISTS: string[] = [
]
// default lists to be 'active' aka searched across
export const DEFAULT_ACTIVE_LIST_URLS: string[] = [GEMINI_LIST]
export const DEFAULT_ACTIVE_LIST_URLS: string[] = [UNI_LIST, GEMINI_LIST]

View File

@@ -33,11 +33,12 @@ export const SUPPORTED_LOCALES = [
'zh-CN',
'zh-TW',
] as const
export type SupportedLocale = typeof SUPPORTED_LOCALES[number]
export type SupportedLocale = typeof SUPPORTED_LOCALES[number] | 'pseudo'
// eslint-disable-next-line import/first
import * as enUS from '../locales/en-US'
export const DEFAULT_LOCALE: SupportedLocale = 'en-US'
export { messages as DEFAULT_MESSAGES } from '../locales/en-US'
export const DEFAULT_CATALOG = enUS
export const LOCALE_LABEL: { [locale in SupportedLocale]: string } = {
'af-ZA': 'Afrikaans',
@@ -72,4 +73,5 @@ export const LOCALE_LABEL: { [locale in SupportedLocale]: string } = {
'vi-VN': 'Tiếng Việt',
'zh-CN': '简体中文',
'zh-TW': '繁体中文',
pseudo: 'ƥƨèúδô',
}

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