Compare commits

..

432 Commits

Author SHA1 Message Date
Crowdin Bot
c9dbe2f0ac chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-24 10:04:51 +00:00
Crowdin Bot
775cf57c30 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-24 09:04:32 +00:00
Moody Salem
f4935e9264 fix(arbitrum): miscellaneous arbitrum network changes
- adds the arbitrum rinkeby testnet deployment
- compute usdc prices on arbitrum one
2021-06-23 20:58:03 -05:00
Crowdin Bot
6b3914b7b9 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-23 08:05:03 +00:00
Crowdin Bot
41efb6f617 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-23 06:05:18 +00:00
Crowdin Bot
52df5f14cf chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-22 23:04:56 +00:00
Noah Zinsmeister
b48a7c529f fix: proposal sorting 2021-06-22 18:47:12 -04:00
Moody Salem
2eca50be93 chore: remove defunct arbitrum kovan testnet 2021-06-22 17:23:40 -05:00
Moody Salem
be2ce18bfa fix: change polling interval per network (#1898) 2021-06-22 17:21:01 -05:00
yj
fe13b29e5e Update README.md (#1897)
Simple signposting, for issue #1896
2021-06-22 15:03:45 -07:00
Crowdin Bot
02aac08489 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-22 21:05:04 +00:00
Crowdin Bot
8f29980b94 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-22 20:05:13 +00:00
Scott Moses Sunarto
bb542ef0fb feat: Add proposal creation interface (#1799)
* Make address input panel more generalized

* Add TextInput component

* Allow adjusting AppBody maxwidth

* Add create proposal layout page

* Fix style consistency

* create proposal ui goes brrr

* various fixes

* minor tweaks and bug fixes

* merge conflict clean up + bug fix

* i18n

* always show create proposal button

* adjust proposal title top margin and show ButtonError styling

* use button disable instead of button error when form is not filled

* revert mistaken css change

* default params for address input panel

* Refactor & fixes

- Add missing i18n
- Refactor how some styled-components is done
- ButtonError is now disabled when proposal is true in create proposal interface
- Edit copywriting
- Minor styling adjustments

* Fixed create proposal padding on medium screen

* refactor

* refactor pt. 2

* single column styling

* change AddressInputPanel font color

* Design adjustments

* change route for create proposal

* Add autonomous proposal CTA

* cta text edit

* Add link to docs for custom action

* small cleanup

* work with latest governor

Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
2021-06-22 15:51:32 -04:00
Crowdin Bot
c2fe17615f chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-22 13:12:10 +00:00
Crowdin Bot
a4cab75d09 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-22 08:04:47 +00:00
Crowdin Bot
882457cfef chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-21 16:05:32 +00:00
Justin Domingue
9a1bb5dbfb Add missing semicolon in English source 2021-06-21 08:10:00 -07:00
Crowdin Bot
767cc85b3e chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-21 07:07:47 +00:00
Crowdin Bot
47d726e544 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-21 06:04:54 +00:00
Crowdin Bot
32118520cd chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-20 19:05:02 +00:00
Crowdin Bot
ada8a3af92 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-19 07:06:22 +00:00
Crowdin Bot
63694b32c0 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-19 06:05:14 +00:00
Crowdin Bot
c9ab94d799 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-19 04:05:38 +00:00
Crowdin Bot
a990c4af70 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-18 21:04:57 +00:00
Crowdin Bot
b5cc33c1f5 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-18 20:05:12 +00:00
Justin Domingue
31da6cdb9d fix: new toggle theme (#1782)
* new toggle theme

* moved trans to default

* update radius

* fianlize styles
2021-06-18 12:44:14 -07:00
Crowdin Bot
4079d8a517 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-18 16:05:52 +00:00
Crowdin Bot
e93fbfd31b chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-18 15:05:19 +00:00
Crowdin Bot
7817846368 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-17 23:04:59 +00:00
Crowdin Bot
fc6a69a9af chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-17 09:04:49 +00:00
Crowdin Bot
93a774092f chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-17 08:05:12 +00:00
Crowdin Bot
55563e9bb2 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-17 07:07:40 +00:00
Crowdin Bot
f44aae2f53 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-17 06:04:53 +00:00
Crowdin Bot
7d674c33e7 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-17 04:05:17 +00:00
Noah Zinsmeister
79e6337629 fix governorIndex 2021-06-16 17:31:24 -04:00
Noah Zinsmeister
3c8e8604b8 Merge remote-tracking branch 'refs/remotes/origin/main' 2021-06-16 17:22:46 -04:00
Noah Zinsmeister
b763659788 restrict governance UI to mainnet only
fix governor name bug

revert useContract change

add governorIndex to vote page

only fetch latest useLatestProposalCount

fix useDataFromEventLogs

hardcode proposalIndexes for old governors
2021-06-16 17:22:37 -04:00
Crowdin Bot
1ac2581419 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 20:04:59 +00:00
Crowdin Bot
9f556680ed chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 19:06:17 +00:00
Justin Domingue
3f242f1b44 fix: memoize extendedEther to unnecessary rerenders (#1869) 2021-06-16 11:07:16 -07:00
Crowdin Bot
126688c753 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 17:16:00 +00:00
Ian Lapham
374cc361a6 small bg fixes (#1868) 2021-06-16 13:14:31 -04:00
Crowdin Bot
0198d0baa1 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 16:05:39 +00:00
Crowdin Bot
da2d7ba648 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 15:05:16 +00:00
Yuta Sugimura
37cf492dd5 fix: Add SwitchLocaleLink to a page where it does not exist (#1867) 2021-06-16 07:24:25 -07:00
Crowdin Bot
9e93f809a0 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 14:05:04 +00:00
Crowdin Bot
d9bd392e6d chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 12:05:13 +00:00
Crowdin Bot
c48adc519f chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 11:05:10 +00:00
Crowdin Bot
9f8983a92e chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 10:05:07 +00:00
Crowdin Bot
c9d3d81768 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 09:05:06 +00:00
Crowdin Bot
c6f73c35ee chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 08:05:22 +00:00
Crowdin Bot
7a2777b814 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-16 03:05:54 +00:00
Jordan Frankfurt
014595cdfb feat: add multi-contract governance support (#1860)
* Revert "feat: quick fix for new governor"
This reverts commit 5dd1249ddd.

* support multiple governance contracts
2021-06-15 22:36:27 -04:00
Jordan Frankfurt
1b27d8dab0 test integration key change (#1864) 2021-06-15 21:04:54 -04:00
Crowdin Bot
c4d12c86a8 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 23:04:42 +00:00
Crowdin Bot
8d2feeb89e chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 19:05:52 +00:00
Crowdin Bot
576b399768 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 18:06:23 +00:00
Crowdin Bot
eb8ce85872 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 15:04:56 +00:00
Justin Domingue
1644e4f9c6 fix(a11y): color contrast changes (#1803)
* fix: a11y changes

* more a11y fixes

* updated theme colors

* addressed rev4 comments

* address rev5 comments

* addressed rev6
2021-06-15 07:55:38 -07:00
Yuta Sugimura
574fab54d1 fix: props for ResponsiveButtonPrimary (#1839)
* fix: props for ResponsiveButtonPrimary

* fix ResponsiveButtonPrimary style
2021-06-15 07:55:11 -07:00
Crowdin Bot
8e581c19ff chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 09:05:09 +00:00
Crowdin Bot
8c2fa89e9e chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 08:05:05 +00:00
Crowdin Bot
0ae7452eca chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 07:07:02 +00:00
Crowdin Bot
4589beb789 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 06:04:49 +00:00
Crowdin Bot
55aee86971 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 04:04:55 +00:00
Crowdin Bot
a457af91b6 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 03:07:51 +00:00
Crowdin Bot
e61b5da3c5 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-15 00:08:26 +00:00
Crowdin Bot
b4f44744c1 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 23:05:29 +00:00
Crowdin Bot
27f4e2e750 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 22:04:51 +00:00
Crowdin Bot
01159c53d5 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 21:04:56 +00:00
Crowdin Bot
8d8d63b873 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 20:05:10 +00:00
Crowdin Bot
da9db4b5f1 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 18:04:48 +00:00
Justin Domingue
1724bee0f5 Update useSwapCallback.ts 2021-06-14 10:24:33 -07:00
Crowdin Bot
48e526554b chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 17:14:33 +00:00
Crowdin Bot
53add345de chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 16:05:45 +00:00
Crowdin Bot
e28faf0da2 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 13:12:25 +00:00
Crowdin Bot
f79dc5fe82 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 12:04:53 +00:00
Crowdin Bot
a6f29cbff8 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 11:04:51 +00:00
Crowdin Bot
68f0d4b725 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 10:04:57 +00:00
Crowdin Bot
111e7dc929 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 09:04:55 +00:00
Crowdin Bot
39d61e4913 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 08:07:59 +00:00
Crowdin Bot
3e6d3ec1b5 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 07:07:26 +00:00
Crowdin Bot
3f65530bf4 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 06:04:48 +00:00
Crowdin Bot
dba0d20781 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 05:07:28 +00:00
Crowdin Bot
a0f3bd0dc6 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 04:04:52 +00:00
Crowdin Bot
bef85abfd4 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 03:06:19 +00:00
Crowdin Bot
9934dba805 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 02:21:00 +00:00
Crowdin Bot
72d94b2831 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 01:28:24 +00:00
Crowdin Bot
138697a30a chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-14 00:10:25 +00:00
Crowdin Bot
0add8ae177 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 22:04:40 +00:00
Crowdin Bot
13f7859aaa chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 21:04:46 +00:00
Crowdin Bot
3337b5de22 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 20:04:51 +00:00
Noah Zinsmeister
55ea6616a4 Merge remote-tracking branch 'refs/remotes/origin/main' 2021-06-13 15:15:07 -04:00
Noah Zinsmeister
5dd1249ddd feat: quick fix for new governor 2021-06-13 15:15:00 -04:00
Crowdin Bot
4ab2bd3474 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 19:06:13 +00:00
Crowdin Bot
9eb20624cb chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 18:05:07 +00:00
Crowdin Bot
25c5cf04e6 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 17:13:27 +00:00
Crowdin Bot
1f70e63cd0 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 16:08:49 +00:00
Crowdin Bot
df88b0ddd1 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 15:05:26 +00:00
Crowdin Bot
679759c3a0 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 14:05:00 +00:00
Crowdin Bot
9b6003bdc5 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 13:12:31 +00:00
Crowdin Bot
2b32824c26 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 12:09:45 +00:00
Crowdin Bot
a4e4cf8ab9 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 11:04:48 +00:00
Crowdin Bot
f08cea1820 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 10:04:50 +00:00
Crowdin Bot
e2d35c56fc chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 09:05:04 +00:00
Crowdin Bot
5f20040107 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 07:06:32 +00:00
Crowdin Bot
9344abd1cf chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 06:05:04 +00:00
Crowdin Bot
426e31230d chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 05:06:53 +00:00
Crowdin Bot
06c48559c5 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 04:05:34 +00:00
Crowdin Bot
0a33ed1a50 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 03:05:54 +00:00
Crowdin Bot
d5c490b871 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 02:19:46 +00:00
Crowdin Bot
099c2adea3 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 01:28:37 +00:00
Crowdin Bot
d387538576 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-13 00:10:49 +00:00
Crowdin Bot
a3a7d01ce9 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 23:05:25 +00:00
Crowdin Bot
549e67bcea chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 22:09:06 +00:00
Crowdin Bot
932992b57f chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 21:04:46 +00:00
Crowdin Bot
76a24376d4 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 20:08:09 +00:00
Crowdin Bot
f873b2249f chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 19:08:33 +00:00
Crowdin Bot
22452c03b0 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 18:05:07 +00:00
Crowdin Bot
14e045b999 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 17:13:55 +00:00
Crowdin Bot
948781f927 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 16:05:42 +00:00
Crowdin Bot
2f72d6b77e chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 15:06:47 +00:00
Crowdin Bot
a78209690d chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 14:04:39 +00:00
Crowdin Bot
98a2f51125 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 13:10:38 +00:00
Crowdin Bot
a1043573af chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 12:07:02 +00:00
Crowdin Bot
63760faa9d chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 11:04:39 +00:00
Crowdin Bot
0566ec28be chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 10:04:55 +00:00
Crowdin Bot
d4c1baba57 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 09:04:49 +00:00
Crowdin Bot
7e41b27cd3 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 08:05:55 +00:00
Crowdin Bot
1d18a5159f chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 07:06:40 +00:00
Crowdin Bot
bb87d2dd03 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 06:04:58 +00:00
Crowdin Bot
0b27528a6a chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 05:06:33 +00:00
Crowdin Bot
5788a273ba chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 04:09:51 +00:00
Crowdin Bot
4d322b17da chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-12 03:09:09 +00:00
Crowdin Bot
cb5b80b558 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-11 16:05:43 +00:00
Crowdin Bot
6964b519bc chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-11 11:04:45 +00:00
Crowdin Bot
ee4ea2a1f0 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-11 10:05:12 +00:00
Crowdin Bot
3763ad15e0 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-10 18:14:56 +00:00
Justin Domingue
557042a88f add missing translations (#1842) 2021-06-10 10:42:07 -07:00
Crowdin Bot
860413dd52 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-10 17:21:32 +00:00
Crowdin Bot
18d4cdcce4 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-10 14:05:54 +00:00
Crowdin Bot
55767de484 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-10 13:15:24 +00:00
Yuta Sugimura
60d5cef69b fix: untranslated parts (#1837) 2021-06-10 07:49:03 -05:00
yj
ad2833a3ed Translate both text in PositionPage.tsx (#1838) 2021-06-10 07:47:59 -05:00
Crowdin Bot
e4a105714a chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-10 12:05:11 +00:00
Crowdin Bot
3e842d3259 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-10 10:05:04 +00:00
Crowdin Bot
e9d18acd41 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-10 00:10:42 +00:00
Moody Salem
abeba3d6b6 fix: translate both prices in the rate toggle
fixes https://github.com/Uniswap/uniswap-interface/issues/1834
2021-06-09 18:06:42 -05:00
Moody Salem
84c4219c02 fix: proposals not showing up on first load of vote page 2021-06-09 18:04:59 -05:00
Crowdin Bot
50b81c8334 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-09 19:14:47 +00:00
Crowdin Bot
8986b63335 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-09 18:15:03 +00:00
Crowdin Bot
631b4c08b6 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-09 17:20:45 +00:00
Crowdin Bot
b92f0b8d90 chore(i18n): synchronize translations from crowdin [skip ci] 2021-06-09 08:05:19 +00:00
Moody Salem
ce926e91b7 chore(ci): skip ci on crowdin syncs 2021-06-08 19:29:57 -05:00
Justin Domingue
4857281a1e undo testing artifact 2021-06-08 11:49:38 -07:00
Crowdin Bot
d2a872e7d2 chore(i18n): synchronize translations from crowdin 2021-06-08 14:09:11 +00:00
Crowdin Bot
73042f20fd chore(i18n): synchronize translations from crowdin 2021-06-08 13:16:53 +00:00
Crowdin Bot
29b5e583c5 chore(i18n): synchronize translations from crowdin 2021-06-08 12:05:11 +00:00
Crowdin Bot
d67f3158bd chore(i18n): synchronize translations from crowdin 2021-06-08 11:07:08 +00:00
Crowdin Bot
817732d62e chore(i18n): synchronize translations from crowdin 2021-06-08 09:05:31 +00:00
Crowdin Bot
562a54a175 chore(i18n): synchronize translations from crowdin 2021-06-08 08:06:38 +00:00
Crowdin Bot
cd1e0cf378 chore(i18n): synchronize translations from crowdin 2021-06-08 06:12:39 +00:00
Crowdin Bot
0c81b08d66 chore(i18n): synchronize translations from crowdin 2021-06-08 04:21:20 +00:00
Crowdin Bot
2662f8afbc chore(i18n): synchronize translations from crowdin 2021-06-08 02:38:00 +00:00
Moody Salem
355012eec9 fix: set polling interval back to 15 seconds 2021-06-07 17:52:49 -05:00
Noah Zinsmeister
68518d7ce0 fix[migrate]: use proper slippage check (#1821) 2021-06-07 15:01:30 -04:00
Crowdin Bot
2c9c99b868 chore(i18n): synchronize translations from crowdin 2021-06-07 18:48:52 +00:00
ChristophSiegenthaler
7b78dfa2c4 Fix typo (#1815)
Co-authored-by: ChristophSiegenthaler <csi@gmx.ch>
2021-06-07 11:07:16 -07:00
Crowdin Bot
e6cbab3c72 chore(i18n): synchronize translations from crowdin 2021-06-07 16:21:50 +00:00
Crowdin Bot
144f86bdfd chore(i18n): synchronize translations from crowdin 2021-06-06 01:33:53 +00:00
Crowdin Bot
6703743aef chore(i18n): synchronize translations from crowdin 2021-06-06 00:16:18 +00:00
Crowdin Bot
0320083909 chore(i18n): synchronize translations from crowdin 2021-06-05 22:08:28 +00:00
Crowdin Bot
b96f7d27ca chore(i18n): synchronize translations from crowdin 2021-06-05 21:08:45 +00:00
Crowdin Bot
45e85bc857 chore(i18n): synchronize translations from crowdin 2021-06-05 20:11:50 +00:00
Crowdin Bot
24e1a01b1a chore(i18n): synchronize translations from crowdin 2021-06-05 19:24:25 +00:00
Crowdin Bot
0e7a94313c chore(i18n): synchronize translations from crowdin 2021-06-05 18:31:11 +00:00
Crowdin Bot
35e80fa3ed chore(i18n): synchronize translations from crowdin 2021-06-05 17:29:29 +00:00
Crowdin Bot
4a70d8eb28 chore(i18n): synchronize translations from crowdin 2021-06-05 16:14:07 +00:00
Moody Salem
706d8724c1 README.md already at the top! 2021-06-05 09:47:18 -05:00
Moody Salem
6e363c1ff1 make _README.md into a symlink 2021-06-05 09:46:49 -05:00
Crowdin Bot
27007708ec chore(i18n): synchronize translations from crowdin 2021-06-04 20:28:49 +00:00
Crowdin Bot
c4739ea963 chore(i18n): synchronize translations from crowdin 2021-06-04 18:41:01 +00:00
Justin Domingue
50954eff0f Create _README.md 2021-06-04 11:14:15 -07:00
Crowdin Bot
af112765e4 chore(i18n): synchronize translations from crowdin 2021-06-04 14:32:59 +00:00
Crowdin Bot
52b71004d0 chore(i18n): synchronize translations from crowdin 2021-06-04 13:29:48 +00:00
Crowdin Bot
2ba7c857cd chore(i18n): synchronize translations from crowdin 2021-06-04 12:26:58 +00:00
Crowdin Bot
67f3b40671 chore(i18n): synchronize translations from crowdin 2021-06-04 05:34:23 +00:00
Crowdin Bot
c2acf5c1a8 chore(i18n): synchronize translations from crowdin 2021-06-04 02:49:43 +00:00
Crowdin Bot
51cf8aa0da chore(i18n): synchronize translations from crowdin 2021-06-04 01:34:22 +00:00
Crowdin Bot
bc0e578610 chore(i18n): synchronize translations from crowdin 2021-06-03 21:28:59 +00:00
Crowdin Bot
1b13cac0fb chore(i18n): synchronize translations from crowdin 2021-06-03 20:33:14 +00:00
Crowdin Bot
14ed4dbb2e chore(i18n): synchronize translations from crowdin 2021-06-03 11:25:20 +00:00
Crowdin Bot
dc140901b3 chore(i18n): synchronize translations from crowdin 2021-06-03 07:33:57 +00:00
Crowdin Bot
07a92ba63b chore(i18n): synchronize translations from crowdin 2021-06-03 06:36:08 +00:00
Crowdin Bot
3f2f46df43 chore(i18n): synchronize translations from crowdin 2021-06-03 05:39:54 +00:00
Crowdin Bot
2dc5c0d386 chore(i18n): synchronize translations from crowdin 2021-06-03 04:58:53 +00:00
Crowdin Bot
38de86f4c9 chore(i18n): synchronize translations from crowdin 2021-06-03 03:01:20 +00:00
Crowdin Bot
b2196e7e48 chore(i18n): synchronize translations from crowdin 2021-06-03 00:24:19 +00:00
Crowdin Bot
30f66f7062 chore(i18n): synchronize translations from crowdin 2021-06-02 23:21:59 +00:00
Justin Domingue
b87430277a support plurals (#1798) 2021-06-02 16:01:16 -07:00
Moody Salem
b4c59cfc6e chore: fix the double translation of 'For'
fixes https://github.com/Uniswap/uniswap-interface/issues/1800
2021-06-02 17:51:54 -05:00
Moody Salem
2326dfa108 chore: remove the lang attribute as well 2021-06-02 17:25:41 -05:00
Crowdin Bot
97bf36efbf chore(i18n): synchronize translations from crowdin 2021-06-02 21:32:30 +00:00
Justin Domingue
264acaae48 Update CONTRIBUTING.md 2021-06-02 14:16:11 -07:00
Crowdin Bot
63e9f6e4d2 chore(i18n): synchronize translations from crowdin 2021-06-02 20:50:26 +00:00
Moody Salem
02d80e07dc refactor(L2): Arbitrum Kovan testnet and Arbitrum One support (#1716)
* experimental! point at a kovan arbitrum deployment

* remove the unwrapped token from mint hook

* fix explorer links

* Etherscan -> Explorer

* move chains to constant file

* use NETWORK_URLS instead

* temporary fix to the syncing issue

* fix tests

* fix unknown chain id crash

* use a multicall that returns arbitrum block numbers

* lower polling interval for layer 2

* use a better multicall

* remove unused import

* fixed multicall2

* make some v2 code chain specific

* fix build

* line number changes

* update keys

* fix the locale parsing of full locale string

* extract

* fix lint

* add arbitrum one

* add arbitrum one to supported chains

* add missing arbitrum one label

* refactor: remove storybook

* point to the arbitrum explorer address

* fix arbitrum mainnet links

* fix how weth shows up in the interface

* make the usdc price feature more cross chain compatible

* missing translation

* clean up some governance code so it doesn't crash on unsupported networks

* improve how we check for transaction receipts for sequencer networks

* improve it a bit more
2021-06-02 15:14:34 -05:00
Crowdin Bot
ad53da5efe chore(i18n): synchronize translations from crowdin 2021-06-02 19:58:27 +00:00
Crowdin Bot
29223ce34f chore(i18n): synchronize translations from crowdin 2021-06-02 18:58:14 +00:00
Crowdin Bot
b88919ed69 chore(i18n): synchronize translations from crowdin 2021-06-02 17:34:57 +00:00
Ian Lapham
ab80910553 fix: add pool find button to v2 pool page (#1700)
* add pool find button to v2 pool page

* update copy to be v2 specific

* fixed migrate v2 liquidity back arrow

* add missing <Trans>

Co-authored-by: Justin Domingue <judo@uniswap.org>
2021-06-02 10:08:45 -07:00
Crowdin Bot
1cdb8aa6a4 chore(i18n): synchronize translations from crowdin 2021-06-02 16:27:43 +00:00
Crowdin Bot
88976d0294 chore(i18n): synchronize translations from crowdin 2021-06-02 15:21:20 +00:00
Crowdin Bot
b908c81e2b chore(i18n): synchronize translations from crowdin 2021-06-02 14:34:38 +00:00
Crowdin Bot
5c20d0adb7 chore(i18n): synchronize translations from crowdin 2021-06-02 09:35:14 +00:00
Crowdin Bot
ca6295fcb7 chore(i18n): synchronize translations from crowdin 2021-06-02 07:35:26 +00:00
Crowdin Bot
e8af59198d chore(i18n): synchronize translations from crowdin 2021-06-02 06:49:31 +00:00
Crowdin Bot
cd4c43b482 chore(i18n): synchronize translations from crowdin 2021-06-02 05:07:18 +00:00
jab416171
c1e07f3713 Fixing some instances of the removeChild issue (#1793)
specifically when the google translate extension triggers it
2021-06-01 20:39:53 -07:00
Crowdin Bot
bccda20473 chore(i18n): synchronize translations from crowdin 2021-06-02 03:03:17 +00:00
Moody Salem
bed8dd5110 fix: do not show price data on non-mainnet 2021-06-01 17:33:50 -05:00
Moody Salem
6bcbabec23 refactor: remove storybook 2021-06-01 17:04:26 -05:00
Justin Domingue
71a490f2aa fix(#1694): fix popup item header overlap (#1783) 2021-06-01 14:30:08 -07:00
Moody Salem
abcf1f5a5c fix: background should show up while loading the js 2021-06-01 16:20:31 -05:00
Crowdin Bot
65e5e9c98e chore(i18n): synchronize translations from crowdin 2021-06-01 20:55:07 +00:00
Moody Salem
fdabb90f0e fix: fire a GA event when the locale is switched 2021-06-01 15:31:15 -05:00
Crowdin Bot
049054f5bb chore(i18n): synchronize translations from crowdin 2021-06-01 20:00:20 +00:00
Crowdin Bot
91d0a002c9 chore(i18n): synchronize translations from crowdin 2021-06-01 16:25:05 +00:00
Justin Domingue
305d2e1df9 chore: change inactive to closed (#1780) 2021-06-01 08:23:23 -07:00
Crowdin Bot
6bb7d9d9b2 chore(i18n): synchronize translations from crowdin 2021-06-01 15:03:26 +00:00
Moody Salem
55d5762e39 chore(ci): sync translations from crowdin straight into main 2021-06-01 09:59:27 -05:00
Justin Domingue
979686100e chore: simplify useSelector and useDispatch types using inference (#1760)
* chore: simplify app dispatch and selector types with ts inference

* update SearchModal to use new types inference

* chore: simplify useSelector and useDispatch types using inference
2021-06-01 07:58:21 -07:00
Moody Salem
a7a1607faa fix: add a link to switch the locale conditionally (#1776)
* add a link to switch the locale conditionally

* make it smaller

* add the locale labels

* language labels from the internet

* fix the heart in the claim popup

* undo the conditional change

* remove todo

* updated Chinese locale name to office-365 language ids

* added missing <Trans>

Co-authored-by: Justin Domingue <judo@uniswap.org>
2021-06-01 09:54:43 -05:00
Hart Lambur
5125cbb1a3 fix(uma): UMA/UNI June expiry call option routing (#1777)
This would allow for direct routing from UMA tokens to June expiry UMA and UNI covered call option tokens (specifically [UMA 25 Call [30 June 2021]](https://etherscan.io/address/0xb46f57e7ce3a284d74b70447ef9352b5e5df8963) and  [UNI 50 Call [30 June 2021]](https://etherscan.io/address/0xe0360a9e2cdd7d03b9408c7d3001e017bac2ecd5)), in the same manner as the May expiry call tokens allowed.
2021-06-01 07:28:21 -05:00
github-actions[bot]
e89387bb26 chore(i18n): synchronize translations from crowdin (#1775) 2021-06-01 05:57:18 -05:00
Moody Salem
f7896db5aa fix linting error, fix header responsiveness in non-english languages, try to fix the background color issue on safari 2021-05-31 22:08:48 -05:00
Moody Salem
0a0053c6f1 fix: prevent the interface from flashing the wrong locale temporarily on load 2021-05-31 21:36:56 -05:00
github-actions[bot]
9e10abbf97 chore(i18n): synchronize translations from crowdin (#1773)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-31 21:11:08 -05:00
Moody Salem
c38771a6aa refactor: remove the fixed global style component (#1772)
* chore: remove the fixed global style component

* move it to a more appropriate place

* move some css around

* add an element that triggers the font to immediately load

* some more nit refactoring

* style

* move the radial gradient into the index.css file

* try overriding the font display attribute of the inter family

* remove font-display rule
2021-05-31 21:10:36 -05:00
Moody Salem
8e364680b6 chore(deps): remove some unused code and dependencies 2021-05-31 20:15:59 -05:00
Henry Zhu
04c25685f7 fix: add space to backToV3 swap button (#1769) 2021-05-31 19:35:53 -05:00
github-actions[bot]
be1e184d88 chore(i18n): synchronize translations from crowdin (#1766)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-31 16:55:57 -05:00
Moody Salem
b485b14395 chore(i18n): add id-ID 2021-05-31 09:55:01 -05:00
github-actions[bot]
44ef0138de chore(i18n): synchronize translations from crowdin (#1762)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-31 09:54:06 -05:00
github-actions[bot]
a1142cc7af chore(i18n): synchronize translations from crowdin (#1761) 2021-05-30 22:00:29 -05:00
Moody Salem
089280ddf0 fix: clean up the charts navigation link 2021-05-30 18:44:34 -05:00
Moody Salem
f3c2a6eaea more translations in the swap page 2021-05-30 18:40:36 -05:00
github-actions[bot]
54dc5b1f19 chore(i18n): synchronize translations from crowdin (#1757)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-30 18:28:19 -05:00
Moody Salem
0af7651c0b info about doing translations 2021-05-30 17:51:26 -05:00
Justin Domingue
61d9dfe127 chore: simplify redux types with ts inference (#1758)
* chore: simplify app dispatch and selector types with ts inference

* update SearchModal to use new types inference
2021-05-30 14:32:57 -07:00
Henry Zhu
d990dfdec7 fix: add padding to price outside of range (#1752) 2021-05-30 14:51:15 -05:00
github-actions[bot]
4336e08233 chore(i18n): synchronize translations from crowdin (#1755)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-30 14:49:57 -05:00
Moody Salem
3840daf365 few more missed spots 2021-05-30 14:15:55 -05:00
Moody Salem
1104bdcefc use trans macro instead of t wherever possible 2021-05-30 14:05:37 -05:00
Moody Salem
499ef27722 fix the english translation in build 2021-05-30 13:37:33 -05:00
github-actions[bot]
1ea0769ba3 chore(i18n): synchronize translations from crowdin (#1751)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-29 20:49:44 -05:00
Moody Salem
637d43621b chore(ci): undo the if check on yarn install 2021-05-29 20:41:16 -05:00
Moody Salem
9831cda290 more i18n for errors 2021-05-29 20:36:43 -05:00
Moody Salem
62d4bb8b51 fix linting error, one more missing key 2021-05-29 20:32:31 -05:00
Moody Salem
58a1be8421 chore(i18n): add a few more translations 2021-05-29 20:29:49 -05:00
Moody Salem
40b939df58 chore(ci): skip install step if node modules is cached and remove cache from release 2021-05-29 20:19:49 -05:00
github-actions[bot]
3ccecc5ca1 chore(i18n): synchronize translations from crowdin (#1749)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-29 20:13:31 -05:00
Moody Salem
9df5b536c9 chore(ci): set up the shared cache for all jobs and extract before doing the sync 2021-05-29 20:06:49 -05:00
Moody Salem
4b72d757c5 chore: add a bunch of missing translation keys 2021-05-29 16:02:43 -05:00
Moody Salem
63affd9828 add required translation key 2021-05-29 15:48:20 -05:00
github-actions[bot]
135f9dc219 chore(i18n): synchronize translations from crowdin (#1748)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-29 15:47:37 -05:00
Moody Salem
08b74b2524 add the source config key 2021-05-29 15:45:49 -05:00
Moody Salem
ffcea6388e chore(ci): separate sources upload and translations download workflows 2021-05-29 15:44:26 -05:00
Moody Salem
408a07ebd4 try extracting en-US.po only in the github workflow 2021-05-29 15:32:51 -05:00
Moody Salem
7f837810e0 chore: reduce png image sizes 2021-05-29 15:22:00 -05:00
github-actions[bot]
57a7a4995a chore(i18n): synchronize translations from crowdin (#1747)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-29 12:27:29 -07:00
Justin Domingue
cc66783278 Update CONTRIBUTING.md 2021-05-29 12:07:46 -07:00
Justin Domingue
f97dcaef1d Add localized pill 2021-05-29 11:34:10 -07:00
Moody Salem
cfea3723a2 remove setting the locale from using the active locale 2021-05-29 07:14:26 -05:00
Moody Salem
7d0fb9cc10 workaround for the url locale not sticking 2021-05-29 00:29:17 -05:00
github-actions[bot]
8633dc7a50 chore(i18n): synchronize translations from crowdin (#1746)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-29 00:21:49 -05:00
Moody Salem
f340537544 add a bunch of missing translations to the swap page 2021-05-29 00:16:57 -05:00
Moody Salem
3e9289dc35 couple of missing translations in the currency list 2021-05-29 00:11:10 -05:00
Moody Salem
4eb5c3cac8 fix the forced re-render on locale change 2021-05-29 00:07:42 -05:00
github-actions[bot]
cfadd3b165 chore(i18n): synchronize translations from crowdin (#1745)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-29 00:03:15 -05:00
Moody Salem
d6db79b8f5 update the commit message since it is used in the pr merge commit 2021-05-29 00:01:51 -05:00
Moody Salem
6007527ce0 couple more missing keys 2021-05-28 23:58:23 -05:00
Moody Salem
06c8db917f chore: handle a couple missing translation keys 2021-05-28 23:46:55 -05:00
Moody Salem
3394bc738f fix the locale parsing of full locale string 2021-05-28 23:43:15 -05:00
Moody Salem
32b56ba0fd just pick the first occurrence of an abbreviated locale in the locale parsing 2021-05-28 23:30:29 -05:00
github-actions[bot]
f97ce35cee chore(i18n): synchronize translations from Crowdin
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-28 23:27:19 -05:00
Moody Salem
0dafd3e7ba chore: update to the top 30 locales 2021-05-28 23:25:32 -05:00
Moody Salem
d719942931 chore: en -> en-US 2021-05-28 23:15:07 -05:00
github-actions[bot]
62b9b5d527 New Crowdin translations by Github Action (#1743)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2021-05-28 23:10:02 -05:00
Moody Salem
ab34645073 chore: pare down the locales directory to let the crowdin sync do the work 2021-05-28 23:06:54 -05:00
Moody Salem
dab3671cfe fix environment variable 2021-05-28 22:07:15 -05:00
Moody Salem
478cb3afa3 another config change to try 2021-05-28 22:06:15 -05:00
Moody Salem
d56015d750 one more config attempt 2021-05-28 21:57:25 -05:00
Moody Salem
a639e65cee chore(ci): try inlining the config 2021-05-28 21:55:29 -05:00
Moody Salem
243e14b74e chore(ci): add a workflow for crowdin.yaml 2021-05-28 21:48:15 -05:00
Justin Domingue
70174140bc chore: refactored locale management hook (#1737)
* chore: refactored locale management hook

* use useMemo instead of useState
2021-05-28 17:36:37 -07:00
Justin Domingue
4fede9df36 removed custom keys, part 2 (#1740) 2021-05-28 17:10:56 -07:00
Justin Domingue
fbd5dab53e Update CONTRIBUTING.md 2021-05-28 16:32:55 -07:00
Justin Domingue
ecdce21b16 Update README.md 2021-05-28 16:30:40 -07:00
Justin Domingue
1a38309500 Update CONTRIBUTING.md 2021-05-28 16:29:38 -07:00
Justin Domingue
46f539c604 chore(i18n): wrapped English text around <Trans> component (#1714)
* feat(i18n): wrapped English text around <Trans> component

* cleanup

* synced

* regenerated locales
2021-05-28 16:25:50 -07:00
Justin Domingue
ad65b63868 remove custom keys (#1739) 2021-05-28 15:33:40 -07:00
Justin Domingue
f9a5dbf6ce fix: add sourceLocale: en (#1738)
* fix: add sourceLocale: en

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
2021-05-28 14:52:54 -07:00
Justin Domingue
7991b0b0d8 Update CONTRIBUTING.md 2021-05-28 10:17:41 -07:00
Moody Salem
d85dccd01a chore: remove list update popup code 2021-05-28 11:08:04 -05:00
dependabot[bot]
37799caa03 chore(deps): bump dns-packet from 1.3.1 to 1.3.4 (#1721)
Bumps [dns-packet](https://github.com/mafintosh/dns-packet) from 1.3.1 to 1.3.4.
- [Release notes](https://github.com/mafintosh/dns-packet/releases)
- [Changelog](https://github.com/mafintosh/dns-packet/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mafintosh/dns-packet/compare/v1.3.1...v1.3.4)

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-05-28 11:04:22 -05:00
Justin Domingue
04878e095c feat(i18n): save and load locale from redux store (#1723)
* wrap sock around function component to get re-renders

* removed sourcelocale since we are using custom ids

* load locale data dynamically

* undo dev change

* ran yarn i18n:extract

* store locale in redux

* added support for redux

* restored header

* refactor

* addressed pr feedback

* specify type

* added navigator locale fallback to generic dialect

* make locale array const and typed

* addressed pr feedback

* fixed various

* addressed pr feedback

* make supported locales constant uppercase

* add back toUpperCase removed during refactoring

* removed lingui/detect-locale

* run yarn
2021-05-28 09:03:53 -07:00
Moody Salem
14a6953b90 fix: useCallback is not necessary 2021-05-28 09:44:05 -05:00
Moody Salem
d866d79578 fix: anonymize outbound link events sent to google analytics
fixes https://github.com/Uniswap/uniswap-interface/issues/1729
2021-05-28 09:08:53 -05:00
Moody Salem
7f1def300d fix: usdc prices shouldn't reload when v3 prices reload 2021-05-27 15:28:45 -05:00
Justin Domingue
8930627064 delete old locales/ folders (#1725) 2021-05-27 12:10:42 -07:00
Justin Domingue
efb939297f update CONTRIBUTING.md with new folder structure 2021-05-27 09:42:38 -07:00
Justin Domingue
69cc728d43 fix(i18n): various fixes and improvements (#1718)
* wrap sock around function component to get re-renders

* removed sourcelocale since we are using custom ids

* load locale data dynamically

* undo dev change

* ran yarn i18n:extract

* make SOCK component lower case

* fixed unmerged conflicts

* regenerated po for wallet.socks

* added loadLocaleData
2021-05-27 09:38:37 -07:00
Moody Salem
a6bc7775bc chore(i18n): single directory for locales 2021-05-27 10:52:17 -05:00
Moody Salem
3452be9a45 chore(i18n): remove line numbers from extracted po 2021-05-27 10:37:15 -05:00
Justin Domingue
be6e2fe74a chore(i18n): convert old locale file to new format (#1715)
* added supported locales

* added vi locale

* deleted old locale files

* add catalogues to i18n.tsx

* remove fallbackLocales

* add fallback
2021-05-26 18:58:00 -07:00
Justin Domingue
83b1297ff6 Update CONTRIBUTING.md 2021-05-26 17:18:57 -07:00
Justin Domingue
a20ed15b00 Update CONTRIBUTING.md 2021-05-26 17:15:04 -07:00
Justin Domingue
1413ab91bf Create CONTRIBUTING.md 2021-05-26 17:14:02 -07:00
Justin Domingue
c4846c8832 feat(i18n): improve i18n (#1692)
* replaced i18next with lingui

* integrate lingui in i18n and update dev setup

* updated components to @lingui

* fix compile error after rebase

* detect locale

* add all previous languages to linguirc

* address pr feedback

* remove it for now

* ignore generate *js files, various fixes

* added more translations

* fixed yarn build command

* wrapped more hardcoded english around <Trans>

* finished second round of translations

* added support for pseudo-en locale

* improvements

* moved copy.tsx to different branch

* moved extra files to different branch

* regenerated po

* clean up

* more fixes

* regenerate po

* remove messages.js

* clean up

* addressed pr feedback

* regenerated po
2021-05-26 13:34:52 -07:00
Moody Salem
dbbffd17a6 fix: improve cancel/retry detection 2021-05-25 13:48:23 -05:00
Moody Salem
85d8b1e514 fix: improve privacy of the claim popup (#1698)
* fix: improve privacy of the claim popup

fixes https://github.com/Uniswap/uniswap-interface/issues/1337

* fix unhandled rejection

* clean up the claim code a bit more

* working claim fetch

* working claim fetch

* trigger some events on the claim popup
2021-05-24 18:15:12 -05:00
Moody Salem
739986ba66 chore: update README.md twitter link 2021-05-24 12:11:59 -05:00
Moody Salem
e9148b30c9 chore: bump v3-sdk 2021-05-21 20:21:41 -05:00
Moody Salem
6e46f25bd4 improvement: use the block number in receipts to update the app state (#1681) 2021-05-21 19:55:44 -05:00
Justin Domingue
02269e9376 fix: handle usdc directly in useUSDCPrice (#1683) 2021-05-21 16:45:39 -07:00
Moody Salem
9822e68d5a remove console.log accidentally committed to swap 2021-05-21 14:35:48 -05:00
Justin Domingue
9d1556b777 feat(pool): add toggle to hide inactive positions (#1676)
* feat(pool): add toggle to hide inactive positions in pools page

* cleanup code

* keep positions sorted, but move zero liquidity positions to end

* simplified sorting logic
2021-05-21 12:22:40 -07:00
Justin Domingue
858b6afb2f improvement(swap): hide swap placeholders to reduce visual complexity (#1678)
* resolve #1646: hide swap placeholders to reduce visual complexity

* use empty string over space
2021-05-21 10:44:41 -07:00
Moody Salem
da14d8fd5b chore: update links in README.md 2021-05-21 10:28:39 -05:00
Moody Salem
3aaa3fef89 fix: wrap/unwrap should not show computed trade details 2021-05-21 10:09:11 -05:00
Moody Salem
bc243e1c07 refactor: some clean up of the common bases code, add WETH 2021-05-21 10:01:58 -05:00
Moody Salem
679a58daf4 unwrapped token is not needed 2021-05-21 09:39:32 -05:00
Moody Salem
eff512deb8 bump sdk-core 2021-05-21 09:34:46 -05:00
Moody Salem
562b402293 feat: use multicall for argent wallets in swap and v3 add liquidity (#1387)
* use argent wallet contract in swap callback

* maybe working swap callback

* chore(v3): trigger a breaking release

BREAKING CHANGE: trigger a major release for the uniswap interface to indicate it now supports swapping and liquidity provision against uniswap protocol v3

* fix the value

* improve the error coverage

* retry more frequently, couple more error nits

* the is argent call was being sketchy

* get it working for add liquidity

* `0x0` for v2 swaps too

* small nits in position page

* fix import

* fix compiler error
2021-05-21 09:30:07 -05:00
Moody Salem
99ad4ae44c feat: ETH2x-FLI to ETH2X pair routing (#1644) 2021-05-20 23:53:28 -05:00
Moody Salem
6e52a43584 fix: remove the click to flip price on the position list item
fixes https://github.com/Uniswap/uniswap-interface/issues/1436
2021-05-20 23:09:14 -05:00
Moody Salem
d4c5d3e8c8 chore: run eslint 2021-05-20 20:14:55 -05:00
Moody Salem
a6e46623ad chore: bump ethers and regenerate lockfile (#1666)
* bump ethers

* regenerate lockfile

* update code style

* Fix code style issues with ESLint

* remove unused useRef

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
2021-05-20 20:11:32 -05:00
Justin Domingue
9353c7838c fix: catch errors from Pair.getLiquidityMinted (#1668) 2021-05-20 16:14:23 -07:00
TeaTwo
816249b4b1 fix: replace jazzicon to @metamask/jazzicon (#1659) 2021-05-20 15:10:39 -07:00
Moody Salem
70292a5512 do not ask for approve for argent wallet migrate 2021-05-20 16:36:51 -05:00
Justin Domingue
ecdbb4a49f revert: "fix: handle insufficient input amount error in v2 add liquidity (#1652)" (#1665)
This reverts commit 307a995a50.
2021-05-20 11:08:07 -07:00
Justin Domingue
536a5d99de fix: fix typo is getLiquidityMinted catch (#1663) 2021-05-20 10:11:42 -07:00
Noah Zinsmeister
ffc2015595 invalidate stale requests in useV3PositionFees 2021-05-20 12:31:46 -04:00
Moody Salem
5e30a4b4ad refactor: bump to latest sdk (#1657) 2021-05-20 11:21:40 -05:00
Moody Salem
b14da2844d chore: remove all tick lens stuff that is not used 2021-05-19 17:35:59 -05:00
Justin Domingue
d3c04b7246 fix: stabilize fiat value by fixing max hop and increasing USDC out to 100k (#1651)
* stablizie fiat value by fixing max hop and increasing USDC out to 100k

* move maxHops and singleHopOnly to parameter of useV2TradeExactOut

* remove single hop param
2021-05-19 13:21:27 -07:00
Justin Domingue
307a995a50 fix: handle insufficient input amount error in v2 add liquidity (#1652)
* handle insufficient input amount error in mint/hooks

* use error.isInsufficientInputAmountError

* fixed typo
2021-05-19 13:18:32 -07:00
Moody Salem
46911593e5 fix: removing and adding liquidity when the price of the pool is at the min/max price
fixes https://github.com/Uniswap/uniswap-interface/issues/1641
2021-05-18 19:17:05 -05:00
Justin Domingue
1ac36c7b6b fix: display pool shares < 10% (#1639)
* fix: display pool shares < 10%

* set bips to 1/10_000
2021-05-18 17:07:06 -05:00
Moody Salem
8e055df447 refactor: make the price computation in v2 add liquidity a little safer 2021-05-18 16:06:54 -05:00
Moody Salem
02ecd727eb fix: do not crash when user switches eth -> weth in add (#1637)
* fix: do not crash when user switches eth -> weth in add

* linting error
2021-05-18 16:52:34 -04:00
Moody Salem
adc8429bdc fix: working copy to clipboard button in walletconnect qr code modal (#1636)
fixes https://github.com/Uniswap/uniswap-interface/issues/1488
2021-05-18 15:22:53 -05:00
Moody Salem
458d34d96c give the check a name 2021-05-18 15:14:33 -05:00
Justin Domingue
6a4fa0c9bf fix: division by 0 error when both reserves are 0 (#1632)
* set pair to invalid if both reserves are 0

* consider reserve0/1=0 as no liquidity
2021-05-18 12:50:28 -07:00
Moody Salem
7fc9a655fc fix: improve rendering of fee dollar values 2021-05-18 14:35:02 -05:00
Moody Salem
8d3babd015 refactor: more separation by chain of addresses 2021-05-18 14:33:03 -05:00
Moody Salem
75ed4c5dae fix: missed a memo for fetching v2 pairs (#1635) 2021-05-18 14:21:06 -05:00
Justin Domingue
58dfadb13c handle custom token overflow (#1634) 2021-05-18 11:32:09 -07:00
Moody Salem
3d5f5f783c chore: check pr titles 2021-05-18 13:26:23 -05:00
jab416171
ecb7132843 Add etherscan links for the two tokens in the pool on the NFT page (#1593)
* Add etherscan links for the two tokens in the pool on the NFT page

* moving linked tokens to a function

added arrow to show that it's a link
added check for eth

* clean up impl

Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
2021-05-18 13:34:20 -04:00
Justin Domingue
980eb8a518 Leverage Trade api for USDC price with v2 & v3 support (#1610)
* calculate usdc price using trade exact out

* fix typo

* add support for non-mainnet

* use fromRawAmount instead of tryParseAmount
2021-05-18 10:07:37 -07:00
Noah Zinsmeister
a11e89c0e1 hide WETH toggle for non-WETH pairs (#1633)
* only show weth toggle for eth pairs

* revert unwrappedToken change
2021-05-18 12:58:42 -04:00
Moody Salem
3efe5268ae refactor: break down some constants files and move some stuff around 2021-05-18 10:31:22 -05:00
Moody Salem
3f43a8fbaf npx not needed 2021-05-18 09:28:30 -05:00
Ian Lapham
cccf149568 fix: update tick parsing to handle min/max prices (#1613)
* update tick parsing to handle min/max prices

* remove fee tier step
2021-05-17 20:19:15 -04:00
Justin Domingue
604ea49567 Revert "lazy load uncommon routes to reduce initial bundle size (#1597)" (#1611)
This reverts commit 4c0c6dfde6.
2021-05-17 11:24:31 -07:00
Justin Domingue
4c0c6dfde6 lazy load uncommon routes to reduce initial bundle size (#1597) 2021-05-17 11:03:49 -07:00
Noah Zinsmeister
a160bb8f02 Merge remote-tracking branch 'refs/remotes/origin/main' 2021-05-17 11:54:17 -04:00
Noah Zinsmeister
e86946b104 bump to sdk version that fixes mint slippage bug
closes #1573
2021-05-17 11:54:06 -04:00
Moody Salem
03108b981e update README.md 2021-05-17 10:14:35 -05:00
Moody Salem
ae27e245b4 replace the message when we fail to parse an error 2021-05-14 14:13:13 -05:00
Moody Salem
897f354202 chore: bump mathieudutour/github-tag-action to latest release version to fix generated changelogs
https://github.com/Uniswap/uniswap-interface/issues/1572
2021-05-14 10:56:57 -05:00
Moody Salem
4745052f0e fix: break words in swap error messages (fixes https://github.com/Uniswap/uniswap-interface/issues/1462) 2021-05-14 10:50:55 -05:00
Moody Salem
5bc5d6504e improve the text slightly 2021-05-14 08:45:17 -05:00
Moody Salem
7a0b85bf41 improvement: estimated amounts instead of minimum/maximums (#1570)
* estimated amounts instead of minimum/maximums

* missed a spot

* fix linting error
2021-05-14 07:15:53 -05:00
OMGspidertanx
534afb3278 fix: tweak element sizing/wraping in approve button (#1569) 2021-05-14 07:15:41 -05:00
Moody Salem
7d71af353e perf: debounce localStorage save 2021-05-14 07:10:25 -05:00
Moody Salem
af6098bfe5 feat: allow walletconnect on testnets (#1389)
* try walletconnect multinetwork

* clean up environment variables for multinetwork

* remove irrelevant config

* move some stuff around

Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
2021-05-13 17:46:30 -05:00
Moody Salem
fce29bb36f fix: division by 0 when computing the USDC value of tokens that do not have a v2 pair (fixes https://github.com/Uniswap/uniswap-interface/issues/1566) 2021-05-13 17:27:34 -05:00
Noah Zinsmeister
4517af39ba don't jump on mouse exit (#1565) 2021-05-13 17:06:25 -04:00
Noah Zinsmeister
b40163ce05 allow fee collection/liquidity removal in weth (#1553)
* add dummy flags for burn/collect as weth

* add toggles

* clean up toggle position

* only show weth toggle if collection is possible
2021-05-13 14:49:54 -04:00
Moody Salem
809902efec fixes https://github.com/Uniswap/uniswap-interface/issues/1386 2021-05-13 12:17:34 -05:00
Noah Zinsmeister
70be9894fa bump walletlink connector (#1563) 2021-05-13 12:35:17 -04:00
Moody Salem
698ad5bac9 bump v3 sdk 2021-05-13 11:21:07 -05:00
Moody Salem
cd37b7533d put the error reason in the message so we can differentiate between unrecognized errors 2021-05-13 11:16:37 -05:00
Justin Domingue
c0cd6a1c8d handle ape= query parameter (#1555)
* handle expert_mode= and ape= query parameters

* removed console log

* use useParsedQueryString

* only handle setting ape mode
2021-05-13 12:01:58 -04:00
Moody Salem
f6245d1093 retry more frequently, couple more error nits 2021-05-13 10:51:06 -05:00
Moody Salem
83c784f7c0 improve the error coverage 2021-05-13 10:51:06 -05:00
Moody Salem
3d95b1a33b fix access of undefined property 2021-05-13 09:37:04 -05:00
Moody Salem
5c96942922 fix: show better errors 2021-05-13 09:02:48 -05:00
Justin Domingue
d27c83b382 use styled-components/macro to display className in dev builds (#1541) 2021-05-13 09:15:13 -04:00
Moody Salem
b2f88965a9 handle errors better 2021-05-12 22:05:00 -05:00
Moody Salem
95db44e0fc add a little state to the automatic issue body 2021-05-12 18:20:16 -05:00
Moody Salem
7d45ff5ca8 fix 0 decimal tokens error 2021-05-12 17:29:02 -05:00
Moody Salem
8964cf86aa nit with how we convert percent to negative value 2021-05-12 17:13:40 -05:00
Moody Salem
0e9f23ed56 hover text nit 2021-05-12 17:12:16 -05:00
Moody Salem
e08e597655 show list in import token dialog 2021-05-12 17:01:20 -05:00
Moody Salem
744db49803 do not show duplicate token results, and stop searching as soon as possible 2021-05-12 16:54:05 -05:00
Moody Salem
54f59e02fd add page url to the issue template 2021-05-12 16:17:46 -05:00
Moody Salem
7950e5c083 fixes https://github.com/Uniswap/uniswap-interface/issues/1548 2021-05-12 16:16:00 -05:00
Ian Lapham
dd33205bf6 update string in token amount formatting (#1539) 2021-05-12 14:19:01 -04:00
Moody Salem
397a20b9ec fix the issue title 2021-05-12 13:14:02 -05:00
Moody Salem
0aac0b43aa clean up the error boundary 2021-05-12 13:11:10 -05:00
Ian Lapham
702500794d truncate and format large numbers (#1518)
* truncate and format large numbers

* update truncation shorthand

* update logic for detecting small amount
2021-05-12 14:08:05 -04:00
Moody Salem
8bea95fab2 fix the transaction deadline errors 2021-05-12 13:01:31 -05:00
Moody Salem
27094c87f2 clean up price impact formatting 2021-05-12 12:39:21 -05:00
Justin Domingue
bede9171c3 add header background on scroll body overlap (#1531)
* add header background-color on scroll overlap

* slide background in/out on scroll

* remove unused import

Co-authored-by: Justin Domingue <domingue.justin@gmail.com>
2021-05-12 13:19:43 -04:00
Justin Domingue
251d7c0bc2 Fix NFT SVG performance issue in browser (#1509)
* only animate NFT SVG on hover by using a canvas

* handle high dpis

* animation transition between canvas and img

* set start state to not animated

* removed animations that were causing issues on Firefox

* simplify code

* remove debugger statement

* remove useEffect in favor of an event handler

* hide canvas without unmounting to avoid blinking

* fix lint error

* fix flicker on hover by leaving canvas always visible

* add comment about z-index

Co-authored-by: Justin Domingue <domingue.justin@gmail.com>
2021-05-12 13:02:52 -04:00
Moody Salem
285e4f28f5 fix bug in fiat value price impact display 2021-05-12 11:56:18 -05:00
Moody Salem
3aa045303a remove a few unused isToken calls 2021-05-12 11:43:30 -05:00
Noah Zinsmeister
e0a7c3794e bump gas margin to 20% 2021-05-12 12:35:46 -04:00
Noah Zinsmeister
f5fc5da341 fix erroneous addition of tokensOwned{0,1} (#1533)
only pass tokenId to useV3PositionFees
2021-05-12 12:20:20 -04:00
Moody Salem
bea5c0484b fix lint errors, show source list in extra tokens 2021-05-12 09:32:24 -05:00
Moody Salem
27960532ca refactor: use new sdk version (#1472)
* do not construct tokens for wrapped token info

* some cleanup of the wrapped token info

* back to extends, bump sdk core version via v2/v3 sdk updates

* Revert "back to extends, bump sdk core version via v2/v3 sdk updates"

This reverts commit 92cc5073

* update the sdk version

* fix some more uses of instanceof

* finish the refactor

* mess with the currency list performance

* start replacing with the latest v3/v2 sdks

* raw -> quotient

* more cleanup

* finish the refactor

* clean up currency list refactor

* fix list rendering

* perf(token lists): improve app performance when there are large inactive token lists (#1510)

* improve inactive token lists performance

* cleanup before larger changes to combine inactive lists

* only do the search if the query does not match any active lists, limit the number of results

* more performance improvements

* search inactive lists more aggressively
2021-05-12 08:52:17 -05:00
Ian Lapham
37a4e2f6e3 More UI bug fixes (#1515)
* fix for error token map parsings

* update varios UI styles

* update padding on & amounts
2021-05-11 22:29:25 -04:00
Moody Salem
19a3b12ca8 bump typechain for faster/less noisy type generation 2021-05-11 16:43:08 -05:00
Noah Zinsmeister
22c1ddf393 swaps to .5% slippage 2021-05-11 15:00:51 -04:00
Noah Zinsmeister
b44ae1a267 clean up parseCurrencyFromURLParameter 2021-05-11 14:19:56 -04:00
Ian Lapham
418dcf0cb2 Various bug fixes (#1501)
* fix for error token map parsings

* fix error on formatting sig figs

* fix various bugs

* no hover cursor

Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
2021-05-11 14:03:02 -04:00
Noah Zinsmeister
58a508c9d6 .25% -> .30% slippage for v3 swaps 2021-05-11 13:53:15 -04:00
Jorropo
3198129af2 feat(routing): support mirror protocol routing as additional bases (#1375)
* feat(routing): support mirror protocol routing as additional bases

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
2021-05-11 13:28:50 -04:00
John Shutt
89d484d882 feat(uma): uma call option routing (#1385)
* feat(uma): uma call option routing

Signed-off-by: John Shutt <john.d.shutt@gmail.com>

* Fix code style issues with ESLint

Co-authored-by: Lint Action <lint-action@samuelmeuli.com>
Co-authored-by: Moody Salem <moodysalem@users.noreply.github.com>
2021-05-11 13:25:51 -04:00
Callil Capuozzo
fa4688d96c UI improvements (#1505)
* Change price ratio using slash to "per"

* Fix header, toggle copy and increase copy

* Add clearer V2 and migrate buttons

* Fix link

* fix account modal background color

* tweak sig figs

Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
2021-05-11 13:25:04 -04:00
Moody Salem
7ee761a59e feat: automatic slippage tolerance (#1463)
* automatic slippage tolerance start

* get it compiling

* out of range/in range behavior of slippage tolerance in add

* small useDerivedSwapInfo refactor

* improve useSwapSlippageTolerance

* fix unit test

* thread placeholder slippage through

* small improvement to slippage input behavior

* fix the display bug

* fix tx settings modal ux

* don't pass props unnecessarily

* switch back to static swap slippage for now

bump migrate slippage to .75%

* fix font size

* add flag for auto slippage migration

validate version updates even more

Co-authored-by: Noah Zinsmeister <noahwz@gmail.com>
2021-05-11 13:00:42 -04:00
jochenboesmans
78e95f6073 Add App-level error boundary, referring users to GitHub issue creation (#1464)
* Add App-level error boundary, referring users to GitHub issue creation on page crashes. (#1452)

* Class component is used as boundary since catching errors is apparently not yet possible with hooks.

* EventListener in window was removed and replaced by error boundary's error catch, which now fires a GA exception. The fields it passes are slightly different because React uses slightly different error types.

* Pre-filling issues with dynamic data is possible with POST requests to GitHub's API, but the GH web client seems to only support pre-fill based on templates. Therefore users still need to copy error info themselves.

* Prefill GitHub issues with crash data.

* Added package 'react-device-detect' to include device data such as OS, browser etc. in crash report.
* Included error stack in issue body.
* Used <code> html tag for displaying stack to user.

* Slightly reduce vertical padding on code block.

* Add ua-parser-js for parsing user agent.

* Revert react-device-detect to ^1.6.2 (which is used for mobile detection etc. in components)
2021-05-11 12:09:01 -04:00
Noah Zinsmeister
c67e57505a make price sig figs more consistent 2021-05-11 10:17:06 -04:00
Justin Domingue
30f7385db7 optimize sandtexture.png with .webp (#1502)
Co-authored-by: Justin Domingue <domingue.justin@gmail.com>
2021-05-10 21:32:53 -04:00
Noah Zinsmeister
c0f58ae810 don't use a signer for callStatic contract 2021-05-10 16:59:11 -04:00
Noah Zinsmeister
54dd5476ca fetch fees directly from collect via callStatic (#1500)
* fetch fees directly from collect via callStatic

* don't clear state
2021-05-10 16:30:02 -04:00
Moody Salem
57786335df fix calculateSlippageAmount (#1497) 2021-05-10 14:22:26 -05:00
Joe Butler
948e01a196 Fix typo (#1454) 2021-05-10 14:01:35 -04:00
335 changed files with 74650 additions and 12783 deletions

5
.env
View File

@@ -1,5 +1,2 @@
REACT_APP_CHAIN_ID="1"
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847"
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
REACT_APP_WALLETCONNECT_BRIDGE_URL="https://uniswap.bridge.walletconnect.org"
# Because we use storybook which has its own babel-loader dependency @ 8.2.2, where react-scripts uses 8.1.0
SKIP_PREFLIGHT_CHECK=true

View File

@@ -1,5 +1,4 @@
REACT_APP_CHAIN_ID="1"
REACT_APP_NETWORK_URL="https://mainnet.infura.io/v3/099fc58e0de9451d80b18d7c74caa7c1"
REACT_APP_INFURA_KEY="099fc58e0de9451d80b18d7c74caa7c1"
REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236"
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
REACT_APP_GOOGLE_ANALYTICS_ID="UA-128182339-4"

View File

@@ -1,4 +1,4 @@
blank_issues_enabled: false
blank_issues_enabled: true
contact_links:
- name: Support
url: https://discord.gg/FCfyBSbCU5

17
.github/workflows/check-pr-title.yaml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: "Check PR Title"
on:
pull_request_target:
types:
- opened
- edited
- synchronize
jobs:
check-pr-title:
name: Check PR Title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v3.4.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

57
.github/workflows/crowdin-sync.yaml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: Crowdin Download
# hourly we sync translations from Crowdin
on:
schedule:
- cron: '0 * * * *' # every hour we download translations and update the pr from crowdin
# manual trigger
workflow_dispatch:
jobs:
download-translations:
name: Download translations
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: Extract translations
run: "yarn i18n:extract"
- name: Synchronize
uses: crowdin/github-action@1.1.0
with:
upload_sources: false
download_translations: true
project_id: 458284
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN_SECRET }}
source: 'src/locales/en-US.po'
translation: 'src/locales/%locale%.po'
create_pull_request: false
localization_branch_name: main
commit_message: "chore(i18n): synchronize translations from crowdin [skip ci]"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

52
.github/workflows/crowdin.yaml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Crowdin Upload
# on any push to main, we upload the translations to be translated
on:
push:
branches:
- main
jobs:
synchronize-with-crowdin:
name: Upload sources to Crowdin
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: Extract translations
run: "yarn i18n:extract"
- name: Synchronize
uses: crowdin/github-action@1.1.0
with:
upload_sources: true
download_translations: false
project_id: 458284
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN_SECRET }}
source: 'src/locales/en-US.po'
translation: 'src/locales/%locale%.po'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -22,6 +22,18 @@ jobs:
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

View File

@@ -23,6 +23,18 @@ jobs:
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

View File

@@ -19,7 +19,7 @@ jobs:
- name: Bump version and push tag
id: github_tag_action
uses: mathieudutour/github-tag-action@v4.5
uses: mathieudutour/github-tag-action@331898d5052eedac9b15fec867b5ba66ebf9b692
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
release_branches: .*
@@ -94,19 +94,13 @@ jobs:
The latest release is always accessible via our alias to the Cloudflare IPFS gateway at [app.uniswap.org](https://app.uniswap.org).
You can also access the Uniswap Interface directly from an IPFS gateway.
The Uniswap interface uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to store your settings.
**Beware** that other sites you access via the _same_ IPFS gateway can read and modify your settings on the Uniswap interface without your permission.
You can avoid this issue by using a subdomain IPFS gateway, or our alias to the latest release at [app.uniswap.org](https://app.uniswap.org).
The preferred URLs below are safe to use to access this specific release.
**BEWARE**: The Uniswap interface uses [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to remember your settings, such as which tokens you have imported.
**You should always use an IPFS gateway that enforces origin separation**, or our alias to the latest release at [app.uniswap.org](https://app.uniswap.org).
Your Uniswap settings are never remembered across different URLs.
Preferred URLs:
IPFS gateways:
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.dweb.link/
- https://${{ steps.convert_cidv0.outputs.cidv1 }}.ipfs.cf-ipfs.com/
- [ipfs://${{ steps.upload.outputs.hash }}/](ipfs://${{ steps.upload.outputs.hash }}/)
Other IPFS gateways:
- https://cloudflare-ipfs.com/ipfs/${{ steps.upload.outputs.hash }}/
- https://ipfs.infura.io/ipfs/${{ steps.upload.outputs.hash }}/
- https://ipfs.io/ipfs/${{ steps.upload.outputs.hash }}/
${{ needs.bump_version.outputs.changelog }}

View File

@@ -21,6 +21,18 @@ jobs:
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

4
.gitignore vendored
View File

@@ -3,6 +3,10 @@
# generated contract types
/src/types/v3
/src/abis/types
/src/locales/**/*.js
/src/locales/**/*.ts
/src/locales/**/*.json
/src/locales/**/en-US.po
# dependencies
/node_modules

View File

@@ -1,16 +0,0 @@
const { dirname, join, parse, resolve } = require('path')
const { existsSync } = require('fs')
module.exports = {
stories: ['../src/**/*.stories.@(ts|tsx)'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/preset-create-react-app'],
typescript: {
check: true,
checkOptions: {},
reactDocgen: 'react-docgen-typescript',
reactDocgenTypescriptOptions: {
shouldExtractLiteralValuesFromEnum: true,
propFilter: (prop) => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true),
},
},
}

View File

@@ -1,4 +0,0 @@
import { addons } from '@storybook/addons'
import { light } from './theme'
addons.setConfig({ theme: light })

View File

@@ -1,91 +0,0 @@
import 'inter-ui'
import { Story } from '@storybook/react/types-6-0'
import { createWeb3ReactRoot, Web3ReactProvider } from '@web3-react/core'
import React from 'react'
import { Provider as StoreProvider } from 'react-redux'
import { ThemeProvider as SCThemeProvider } from 'styled-components'
import { NetworkContextName } from '../src/constants'
import store from '../src/state'
import { FixedGlobalStyle, theme, ThemedGlobalStyle } from '../src/theme'
import getLibrary from '../src/utils/getLibrary'
import * as storybookThemes from './theme'
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
dependencies: {
withStoriesOnly: true,
hideEmpty: true,
},
docs: {
theme: storybookThemes.light,
},
viewport: {
viewports: {
mobile: {
name: 'iPhone X',
styles: {
width: '375px',
height: '812px',
},
},
tablet: {
name: 'iPad',
styles: {
width: '768px',
height: '1024px',
},
},
laptop: {
name: 'Laptop',
styles: {
width: '1024px',
height: '768px',
},
},
desktop: {
name: 'Desktop',
styles: {
width: '1440px',
height: '1024px',
},
},
},
},
}
export const globalTypes = {
theme: {
name: 'Theme',
description: 'Global theme for components',
defaultValue: 'light',
toolbar: {
icon: 'circlehollow',
items: ['light', 'dark'],
},
},
}
const Web3ProviderNetwork = createWeb3ReactRoot(NetworkContextName)
const withProviders = (Component: Story, context: Record<string, any>) => {
const THEME = theme(context.globals.theme === 'dark')
return (
<>
<Web3ReactProvider getLibrary={getLibrary}>
<Web3ProviderNetwork getLibrary={getLibrary}>
<StoreProvider store={store}>
<SCThemeProvider theme={THEME}>
<FixedGlobalStyle />
<ThemedGlobalStyle />
<main>
<Component />
</main>
</SCThemeProvider>
</StoreProvider>
</Web3ProviderNetwork>
</Web3ReactProvider>
</>
)
}
export const decorators = [withProviders]

View File

@@ -1,17 +0,0 @@
import { create } from '@storybook/theming'
// this themes the storybook UI
const uniswapBaseTheme = {
brandTitle: 'Uniswap Design',
brandUrl: 'https://uniswap.org',
brandImage: 'https://ipfs.io/ipfs/QmNa8mQkrNKp1WEEeGjFezDmDeodkWRevGFN8JCV7b4Xir',
}
export const light = create({
base: 'light',
...uniswapBaseTheme,
})
// export const dark = create({
// base: 'dark',
// ...uniswapBaseTheme,
// })

47
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,47 @@
# Development
## Install Dependencies
```bash
yarn install
```
## Generate locale files
```
yarn i18n:extract
```
## Run the interface
```bash
yarn start
```
# Contributing
Thank you for your interest in contributing to the Uniswap interface! 🦄
## Finding a first issue
Start with issues with the label
[`good first issue`](https://github.com/Uniswap/uniswap-interface/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
## Pull requests
**Please open all pull requests against the `main` branch.**
CI checks will run against all PRs.
# Translations
Help Uniswap reach a global audience!
Uniswap uses [Crowdin](https://crowdin.com/project/uniswap-interface)
for managing translations. Whenever a new string is added to the project,
it gets uploaded to Crowdin for translation by [this workflow](./.github/workflows/crowdin.yaml).
Every hour, translations are synced from Crowdin in [this other workflow](./.github/workflows/crowdin-sync.yaml).
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!

View File

@@ -4,17 +4,21 @@
[![Integration Tests](https://github.com/Uniswap/uniswap-interface/actions/workflows/integration-tests.yaml/badge.svg)](https://github.com/Uniswap/uniswap-interface/actions/workflows/integration-tests.yaml)
[![Lint](https://github.com/Uniswap/uniswap-interface/actions/workflows/lint.yml/badge.svg)](https://github.com/Uniswap/uniswap-interface/actions/workflows/lint.yml)
[![Release](https://github.com/Uniswap/uniswap-interface/actions/workflows/release.yaml/badge.svg)](https://github.com/Uniswap/uniswap-interface/actions/workflows/release.yaml)
[![Crowdin](https://badges.crowdin.net/uniswap-interface/localized.svg)](https://crowdin.com/project/uniswap-interface)
An open source interface for Uniswap -- a protocol for decentralized exchange of Ethereum tokens.
- Website: [uniswap.org](https://uniswap.org/)
- Interface: [app.uniswap.org](https://app.uniswap.org)
- Docs: [uniswap.org/docs/](https://uniswap.org/docs/)
- Twitter: [@UniswapProtocol](https://twitter.com/UniswapProtocol)
- Twitter: [@Uniswap](https://twitter.com/Uniswap)
- Reddit: [/r/Uniswap](https://www.reddit.com/r/Uniswap/)
- Email: [contact@uniswap.org](mailto:contact@uniswap.org)
- Discord: [Uniswap](https://discord.gg/FCfyBSbCU5)
- Whitepaper: [Link](https://hackmd.io/C-DvwDSfSxuh-Gd4WKE_ig)
- Whitepapers:
- [V1](https://hackmd.io/C-DvwDSfSxuh-Gd4WKE_ig)
- [V2](https://uniswap.org/whitepaper.pdf)
- [V3](https://uniswap.org/whitepaper-v3.pdf)
## Accessing the Uniswap Interface
@@ -22,46 +26,21 @@ To access the Uniswap Interface, use an IPFS gateway link from the
[latest release](https://github.com/Uniswap/uniswap-interface/releases/latest),
or visit [app.uniswap.org](https://app.uniswap.org).
## Listing a token
Please see the
[@uniswap/default-token-list](https://github.com/uniswap/default-token-list)
repository.
## Development
### Install Dependencies
```bash
yarn
```
### Run
```bash
yarn start
```
### Configuring the environment (optional)
To have the interface default to a different network when a wallet is not connected:
1. Make a copy of `.env` named `.env.local`
2. Change `REACT_APP_NETWORK_ID` to `"{YOUR_NETWORK_ID}"`
3. Change `REACT_APP_NETWORK_URL` to e.g. `"https://{YOUR_NETWORK_ID}.infura.io/v3/{YOUR_INFURA_KEY}"`
Note that the interface only works on testnets where both
[Uniswap V2](https://uniswap.org/docs/v2/smart-contracts/factory/) and
[multicall](https://github.com/makerdao/multicall) are deployed.
The interface will not work on other networks.
## Contributions
**Please open all pull requests against the `main` branch.**
CI checks will run against all PRs.
For steps on local deployment, development, and code contribution, please see [CONTRIBUTING](./CONTRIBUTING.md).
## Accessing Uniswap Interface V1
## Accessing Uniswap V2
The Uniswap Interface supports swapping against, and migrating or removing liquidity from Uniswap V1. However,
if you would like to use Uniswap V1, the Uniswap V1 interface for mainnet and testnets is accessible via IPFS gateways
The Uniswap Interface supports swapping, adding liquidity, removing liquidity and migrating liquidity for
Uniswap protocol V2.
- Swap on Uniswap V2: https://app.uniswap.org/#/swap?use=v2
- View V2 liquidity: https://app.uniswap.org/#/pool/v2
- Add V2 liquidity: https://app.uniswap.org/#/add/v2
- Migrate V2 liquidity to V3: https://app.uniswap.org/#/migrate/v2
## Accessing Uniswap V1
The Uniswap V1 interface for mainnet and testnets is accessible via IPFS gateways
linked from the [v1.0.0 release](https://github.com/Uniswap/uniswap-interface/releases/tag/v1.0.0).

View File

@@ -0,0 +1,8 @@
const isDev = process.env.NODE_ENV !== 'production'
module.exports = {
styledComponents: {
fileName: isDev,
displayName: isDev,
},
}

View File

@@ -8,7 +8,9 @@ import { JsonRpcProvider } from '@ethersproject/providers'
import { Wallet } from '@ethersproject/wallet'
import { Eip1193Bridge } from '@ethersproject/experimental/lib/eip1193-bridge'
const TEST_PRIVATE_KEY = Cypress.env('INTEGRATION_TEST_PRIVATE_KEY')
// todo: figure out how env vars actually work in CI
// const TEST_PRIVATE_KEY = Cypress.env('INTEGRATION_TEST_PRIVATE_KEY')
const TEST_PRIVATE_KEY = '0xe580410d7c37d26c6ad1a837bbae46bc27f9066a466fb3a66e770523b4666d19'
// address of the above key
export const TEST_ADDRESS_NEVER_USE = new Wallet(TEST_PRIVATE_KEY).address

53
lingui.config.ts Normal file
View File

@@ -0,0 +1,53 @@
export default {
catalogs: [
{
path: '<rootDir>/src/locales/{locale}',
include: ['<rootDir>/src'],
},
],
compileNamespace: 'cjs',
fallbackLocales: {
default: 'en-US',
},
format: 'po',
formatOptions: {
lineNumbers: false,
},
locales: [
'af-ZA',
'ar-SA',
'ca-ES',
'cs-CZ',
'da-DK',
'de-DE',
'el-GR',
'en-US',
'es-ES',
'fi-FI',
'fr-FR',
'he-IL',
'hu-HU',
'id-ID',
'it-IT',
'ja-JP',
'ko-KR',
'nl-NL',
'no-NO',
'pl-PL',
'pt-BR',
'pt-PT',
'ro-RO',
'ru-RU',
'sr-SP',
'sv-SE',
'tr-TR',
'uk-UA',
'vi-VN',
'zh-CN',
'zh-TW',
],
orderBy: 'messageId',
rootDir: '.',
runtimeConfigModule: ['@lingui/core', 'i18n'],
sourceLocale: 'en-US',
}

View File

@@ -4,24 +4,22 @@
"homepage": ".",
"private": true,
"devDependencies": {
"@emotion/core": "^11.0.0",
"@ethersproject/experimental": "^5.0.1",
"@ethersproject/experimental": "^5.2.0",
"@lingui/cli": "^3.9.0",
"@lingui/loader": "^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.3.5",
"@storybook/addon-actions": "^6.1.17",
"@storybook/addon-essentials": "^6.1.17",
"@storybook/addon-links": "^6.1.17",
"@storybook/addons": "^6.1.17",
"@storybook/components": "^6.1.17",
"@storybook/preset-create-react-app": "^3.1.5",
"@storybook/preset-typescript": "^3.0.0",
"@storybook/react": "^6.1.17",
"@storybook/theming": "^6.1.17",
"@styled-system/css": "^5.1.5",
"@typechain/ethers-v5": "^6.0.5",
"@typechain/ethers-v5": "^7.0.0",
"@types/jest": "^25.2.1",
"@types/lingui__core": "^2.7.1",
"@types/lingui__macro": "^2.7.4",
"@types/lingui__react": "^2.8.3",
"@types/lodash.flatmap": "^4.5.6",
"@types/luxon": "^1.24.4",
"@types/multicodec": "^1.0.0",
@@ -36,6 +34,7 @@
"@types/rebass": "^4.0.7",
"@types/styled-components": "^5.1.0",
"@types/testing-library__cypress": "^5.0.5",
"@types/ua-parser-js": "^0.7.35",
"@types/wcag-contrast": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
@@ -46,16 +45,16 @@
"@uniswap/token-lists": "^1.0.0-beta.19",
"@uniswap/v2-core": "1.0.0",
"@uniswap/v2-periphery": "^1.1.0-beta.0",
"@uniswap/v2-sdk": "^1.0.9",
"@uniswap/v2-sdk": "^3.0.0-alpha.2",
"@uniswap/v3-core": "1.0.0",
"@uniswap/v3-periphery": "1.0.0",
"@uniswap/v3-sdk": "^1.0.8",
"@uniswap/v3-sdk": "^3.0.0-alpha.9",
"@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": "^6.1.1",
"@web3-react/walletlink-connector": "^6.0.9",
"@web3-react/walletconnect-connector": "^6.2.0",
"@web3-react/walletlink-connector": "^6.2.0",
"ajv": "^6.12.3",
"cids": "^1.0.0",
"copy-to-clipboard": "^3.2.0",
@@ -66,12 +65,8 @@
"eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-react": "^7.19.0",
"eslint-plugin-react-hooks": "^4.0.0",
"ethers": "^5.0.7",
"i18next": "^15.0.9",
"i18next-browser-languagedetector": "^3.0.1",
"i18next-xhr-backend": "^2.0.1",
"ethers": "^5.2.0",
"inter-ui": "^3.13.1",
"jazzicon": "^1.5.0",
"lightweight-charts": "^3.3.0",
"lodash.flatmap": "^4.5.0",
"luxon": "^1.25.0",
@@ -87,7 +82,6 @@
"react-dom": "^17.0.1",
"react-feather": "^2.0.8",
"react-ga": "^2.5.7",
"react-i18next": "^10.7.0",
"react-markdown": "^4.3.1",
"react-popper": "^2.2.3",
"react-redux": "^7.2.2",
@@ -103,8 +97,9 @@
"start-server-and-test": "^1.11.0",
"styled-components": "^4.2.0",
"styled-system": "^5.1.5",
"typechain": "^4.0.3",
"typechain": "^5.0.0",
"typescript": "^4.2.3",
"ua-parser-js": "^0.7.28",
"use-count-up": "^2.2.5",
"wcag-contrast": "^3.0.0",
"workbox-core": "^6.1.0",
@@ -113,15 +108,19 @@
"workbox-routing": "^6.1.0",
"workbox-strategies": "^6.1.0"
},
"resolutions": {
"@walletconnect/web3-provider": "1.4.2-rc.2"
},
"scripts": {
"compile-contract-types": "yarn compile-external-abi-types && yarn compile-v3-contract-types",
"compile-external-abi-types": "npx typechain --target ethers-v5 --outDir src/abis/types './src/abis/**/*.json'",
"compile-v3-contract-types": "npx typechain --target ethers-v5 --outDir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
"build": "yarn compile-contract-types && react-scripts build",
"compile-external-abi-types": "typechain --target ethers-v5 --out-dir src/abis/types './src/abis/**/*.json'",
"compile-v3-contract-types": "typechain --target ethers-v5 --out-dir src/types/v3 './node_modules/@uniswap/?(v3-core|v3-periphery)/artifacts/contracts/**/*.json'",
"build": "yarn compile-contract-types && yarn i18n:extract && yarn i18n:compile && react-scripts build",
"i18n:extract": "lingui extract --locale en-US",
"i18n:compile": "lingui compile",
"integration-test": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run'",
"postinstall": "yarn compile-contract-types",
"start": "yarn compile-contract-types && react-scripts start",
"storybook": "start-storybook -p 6006",
"test": "react-scripts test --env=jsdom"
},
"eslintConfig": {

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html translate="no">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" type="image/png" href="%PUBLIC_URL%/favicon.png" />
@@ -24,11 +24,80 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<style>
* {
font-family: 'Inter', sans-serif;
box-sizing: border-box;
}
@supports (font-variation-settings: normal) {
* {
font-family: 'Inter var', sans-serif;
}
}
html,
body {
margin: 0;
padding: 0;
}
button {
user-select: none;
}
html {
font-size: 16px;
font-variant: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
font-feature-settings: 'ss01' on, 'ss02' on, 'cv01' on, 'cv03' on;
}
#background-radial-gradient {
position: fixed;
top: 0;
left: 0;
right: 0;
pointer-events: none;
width: 200vw;
height: 200vh;
mix-blend-mode: color;
background: radial-gradient(50% 50% at 50% 50%, #fc077d10 0%, rgba(255, 255, 255, 0) 100%);
transform: translate(-50vw, -100vh);
z-index: -1;
}
html {
min-height: 100%;
}
@media (prefers-color-scheme: dark) {
html {
background-color: #212429;
}
}
@media (prefers-color-scheme: light) {
html {
background-color: #F7F8FA;
}
}
</style>
<title>Uniswap Interface</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!-- The root is the container of the app -->
<div id="root">
<!-- Triggers the font to load immediately and then is replaced by the app -->
<div style="visibility: hidden">X</div>
</div>
<div id="background-radial-gradient"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.

View File

@@ -1,89 +0,0 @@
{
"noWallet": "Keine Ethereum-Wallet gefunden",
"wrongNetwork": "Du bist auf dem falschen Netzwerk.",
"switchNetwork": "Bitte wechsle zum {{ correctNetwork }}",
"installWeb3MobileBrowser": "Bitte besuche uns mit einem web3-fähigen mobilen Browser wie z.B. Trust Wallet oder Coinbase Wallet.",
"installMetamask": "Bitte besuch uns erneut, nachdem du Metamask oder Brave installiert hast.",
"disconnected": "Nicht verbunden",
"swap": "Tauschen",
"swapAnyway": "Trotzdem tauschen",
"send": "Senden",
"sendAnyway": "Trotzdem senden",
"pool": "Pool",
"betaWarning": "Dieses Projekt ist in beta. Nutzung auf eigenes Risiko.",
"input": "Input",
"output": "Output",
"estimated": "geschätzt",
"balance": "Guthaben: {{ balanceInput }}",
"unlock": "Freischalten",
"pending": "hängige",
"selectToken": "Token auswählen",
"searchOrPaste": "Token Name, Symbol oder Adresse suchen",
"searchOrPasteMobile": "Name, Symbol oder Adresse",
"noExchange": "Exchange nicht gefunden",
"exchangeRate": "Wechselkurs",
"invertedRate": "Invertierter Wechselkurs",
"unknownError": "Oops! Ein unbekannter Fehler ist aufgetreten. Bitte Seite neu laden oder uns von einem anderen Browser oder Gerät erneut besuchen.",
"enterValueCont": "Wert {{ missingCurrencyValue }} eingeben um fortzufahren.",
"selectTokenCont": "Token auswählen um fortzufahren.",
"noLiquidity": "Keine Liquidität.",
"insufficientLiquidity": "Liquidität ungenügend.",
"unlockTokenCont": "Token freischalten um fortzufahren.",
"transactionDetails": "Details der Transaktion",
"hideDetails": "Details ausblenden",
"slippageWarning": "Wechselkursrutsch",
"highSlippageWarning": "Hoher Wechselkursrutsch",
"youAreSelling": "Du verkaufst",
"orTransFail": "oder die Transaktion wird fehlschlagen.",
"youWillReceive": "Du erhältst mindestens",
"youAreBuying": "Du kaufst",
"itWillCost": "Es kostet höchstens",
"forAtMost": "für maximal",
"insufficientBalance": "Guthaben ungenügend",
"inputNotValid": "Eingabewert ungültig",
"differentToken": "Es müssen unterschiedliche Token sein.",
"noRecipient": "Empfängeradresse angeben.",
"invalidRecipient": "Bitte gib eine gültige Empfängeradresse an.",
"recipientAddress": "Adresse des Empfängers",
"youAreSending": "Du schickst",
"willReceive": "erhält mindestens",
"to": "zu",
"addLiquidity": "Liquidität hinzufügen",
"deposit": "Depot",
"currentPoolSize": "Aktuelle Größe des Pools",
"yourPoolShare": "Dein Anteil am Pool",
"noZero": "Wert darf nicht Null sein.",
"mustBeETH": "Einer der Inputs muß ETH sein.",
"enterCurrencyOrLabelCont": "{{ inputCurrency }} oder {{ label }} Wert eingeben um fortzufahren.",
"youAreAdding": "Du fügst zwischen",
"and": "und",
"intoPool": "in den Liquiditätspool.",
"outPool": "vom Liquiditätspool.",
"youWillMint": "Du prägst",
"liquidityTokens": "Liquiditätstokens.",
"totalSupplyIs": "Die gesamte Anzahl Liquiditätstokens ist aktuell",
"youAreSettingExRate": "Du setzt den anfänglichen Wechselkurs auf",
"totalSupplyIs0": "Die gesamte Anzahl Liquiditätstokens ist aktuell 0.",
"tokenWorth": "Zum gegenwärtigen Wechselkurs ist jeder Pool Token so viel Wert",
"firstLiquidity": "Du bist die erste Person die Liquidität bereitstellt!",
"initialExchangeRate": "Der initiale Wechselkurs wird auf deiner Überweisung basieren. Stelle sicher, dass deine ETH und {{ label }} denselben Fiatwert haben.",
"removeLiquidity": "Liquidität entfernen",
"poolTokens": "Pool Tokens",
"enterLabelCont": "{{ label }} Wert eingeben um fortzufahren.",
"youAreRemoving": "Du entfernst zwischen",
"youWillRemove": "Du entfernst",
"createExchange": "Exchange erstellen",
"invalidTokenAddress": "Ungültige Tokenadresse",
"exchangeExists": "{{ label }} Exchange existiert bereits!",
"invalidSymbol": "Symbol ungültig",
"invalidDecimals": "Dezimalstellen ungültig",
"tokenAddress": "Tokenadresse",
"label": "Label",
"name": "Name",
"symbol": "Symbol",
"decimals": "Dezimalstellen",
"enterTokenCont": "Tokenadresse eingeben um fortzufahren",
"priceChange": "Geschätzter Wechselkursrutsch",
"forAtLeast": "für mindestens ",
"brokenToken": "Der ausgewählte Token ist nicht kompatibel mit Uniswap V1. Liquidität hinzufügen wird zu nicht mehr zugänglichen Token führen!"
}

View File

@@ -1,116 +0,0 @@
{
"noWallet": "No Ethereum wallet found",
"wrongNetwork": "You are on the wrong network",
"switchNetwork": "Please switch to {{ correctNetwork }}",
"installWeb3MobileBrowser": "Please visit us from a web3-enabled mobile browser such as Trust Wallet or Coinbase Wallet.",
"installMetamask": "Please visit us after installing Metamask on Chrome or Brave.",
"disconnected": "Disconnected",
"swap": "Swap",
"swapAnyway": "Swap Anyway",
"send": "Send",
"sendAnyway": "Send Anyway",
"pool": "Pool",
"betaWarning": "This project is in beta. Use at your own risk.",
"input": "Input",
"output": "Output",
"estimated": "estimated",
"balance": "Balance: {{ balanceInput }}",
"unlock": "Unlock",
"pending": "Pending",
"selectToken": "Select a token",
"searchOrPaste": "Search Token Name, Symbol, or Address",
"searchOrPasteMobile": "Name, Symbol, or Address",
"noExchange": "No Exchange Found",
"noToken": "No Token Found",
"exchangeRate": "Exchange Rate",
"unknownError": "Oops! An unknown error occurred. Please refresh the page, or visit from another browser or device.",
"enterValueCont": "Enter a {{ missingCurrencyValue }} value to continue.",
"selectTokenCont": "Select a token to continue.",
"noLiquidity": "No liquidity.",
"insufficientLiquidity": "Insufficient liquidity.",
"unlockTokenCont": "Please unlock token to continue.",
"transactionDetails": "Advanced Details",
"hideDetails": "Hide Details",
"slippageWarning": "Slippage Warning",
"highSlippageWarning": "High Slippage Warning",
"youAreSelling": "You are selling",
"orTransFail": "or the transaction will fail.",
"youWillReceive": "You will receive at least",
"youAreBuying": "You are buying",
"itWillCost": "It will cost at most",
"forAtMost": "for at most",
"insufficientBalance": "Insufficient Balance",
"inputNotValid": "Not a valid input value",
"differentToken": "Must be different token.",
"noRecipient": "Enter a wallet address to send to.",
"invalidRecipient": "Please enter a valid wallet address recipient.",
"recipientAddress": "Recipient Address",
"youAreSending": "You are sending",
"willReceive": "will receive at least",
"to": "to",
"addLiquidity": "Add Liquidity",
"deposit": "Deposit",
"currentPoolSize": "Current Pool Size",
"yourPoolShare": "Your Pool Share",
"noZero": "Amount cannot be zero.",
"mustBeETH": "One of the input must be ETH.",
"enterCurrencyOrLabelCont": "Enter a {{ inputCurrency }} or {{ label }} value to continue.",
"youAreAdding": "You are adding",
"and": "and",
"intoPool": "into the liquidity pool.",
"outPool": "from the liquidity pool.",
"youWillMint": "You will mint",
"liquidityTokens": "liquidity tokens.",
"totalSupplyIs": "Current total supply of liquidity tokens is",
"youAreSettingExRate": "You are setting the initial exchange rate to",
"totalSupplyIs0": "Current total supply of liquidity tokens is 0.",
"tokenWorth": "At current exchange rate, each pool token is worth",
"firstLiquidity": "You are the first person to add liquidity!",
"initialExchangeRate": "The initial exchange rate will be set based on your deposits. Please make sure that your ETH and {{ label }} deposits have the same fiat value.",
"removeLiquidity": "Remove Liquidity",
"poolTokens": "Pool Tokens",
"enterLabelCont": "Enter a {{ label }} value to continue.",
"youAreRemoving": "You are removing between",
"youWillRemove": "You will remove",
"createExchange": "Create Exchange",
"invalidTokenAddress": "Not a valid token address",
"exchangeExists": "{{ label }} Exchange already exists!",
"invalidSymbol": "Invalid symbol",
"invalidDecimals": "Invalid decimals",
"tokenAddress": "Token Address",
"label": "Label",
"name": "Name",
"symbol": "Symbol",
"decimals": "Decimals",
"enterTokenCont": "Enter a token address to continue",
"priceChange": "Expected price slippage",
"forAtLeast": "for at least ",
"brokenToken": "The selected token is not compatible with Uniswap V1. Adding liquidity will result in locked funds.",
"toleranceExplanation": "Lowering this limit decreases your risk of frontrunning. However, this makes more likely that your transaction will fail due to normal price movements.",
"tokenSearchPlaceholder": "Search name or paste address",
"selectFee": "Select Fee",
"selectLiquidityRange": "Set Price Range",
"selectPool": "Select Fee Tier",
"depositAmounts": "Deposit Amounts",
"fee": "fee",
"setLimits": "Set Limits",
"percent": "Percent",
"rate": "Rate",
"currentRate": "Current {{label}} Price:",
"inactiveRangeWarning": "Your position will not earn fees or be used in trades until the market price moves into your range.",
"invalidRangeWarning": "Invalid range selected. The min price must be lower than the max price.",
"connectWallet": "Connect Wallet",
"unsupportedAsset": "Unsupported Asset",
"feePool": "Fee Pool",
"feeTier": "Fee Tier",
"rebalanceMessage": "Your underlying tokens will be automatically rebalanced when the rate of the pool changes and may be different when you withdraw the position.",
"addEarnHelper": "You will earn fees from trades proportional to your share of the pool.",
"learnMoreAboutFess": " Learn more about earning fees.",
"selectAPool": "Choose the best fee tier for your selected pair.",
"poolType": "Select a fee tier based on your preferred liquidity provider fee.",
"rangeWarning": "Your liquidity will only be active and earning fees when the rate of the pool is within this price range.",
"chooseLiquidityAmount": "Choose an amount of tokens to open this liquidity position. If you dont have enough tokens you can trade for them with a Swap.",
"inputTokenDynamic": "Input {{label}}",
"selectStartingPrice": "Set Starting Price",
"newPoolPrice": "Select the market rate for the tokens being added."
}

View File

@@ -1,75 +0,0 @@
{
"noWallet": "No se encontró billetera de Ethereum",
"wrongNetwork": "Te encontrás en la red equivocada",
"switchNetwork": "Por favor cambia a {{ correctNetwork }}",
"installWeb3MobileBrowser": "Por favor ingresá desde un navegador móvil con web3 habilitado como Trust Wallet o Coinbase Wallet.",
"installMetamask": "Por favor visítanos nuevamente luego de instalar Metamask en Chrome o Brave.",
"disconnected": "Desconectado",
"swap": "Intercambiar",
"send": "Enviar",
"pool": "Pool",
"betaWarning": "Este proyecto se encuentra en beta. Usalo bajo tu propio riesgo.",
"input": "Entrada",
"output": "Salida",
"estimated": "estimado",
"balance": "Saldo: {{ balanceInput }}",
"unlock": "Desbloquear",
"pending": "Pendiente",
"selectToken": "Seleccioná un token",
"searchOrPaste": "Buscar Token o Pegar Dirección",
"noExchange": "No se encontró la divisa",
"exchangeRate": "Tasa de Cambio",
"enterValueCont": "Ingresá un valor en {{ missingCurrencyValue }} para continuar.",
"selectTokenCont": "Seleccioná un token para continuar.",
"noLiquidity": "Sin liquidez.",
"unlockTokenCont": "Por favor desbloqueá un token para continuar.",
"transactionDetails": "Detalles de la transacción",
"hideDetails": "Ocultar detalles",
"youAreSelling": "Estás vendiendo",
"orTransFail": "o la transacción fallará.",
"youWillReceive": "Vas a recibir al menos",
"youAreBuying": "Estás comprando",
"itWillCost": "Costará a lo sumo",
"insufficientBalance": "Saldo insuficiente",
"inputNotValid": "No es un valor de entrada válido",
"differentToken": "Debe ser un token distinto.",
"noRecipient": "Ingresá una dirección de billetera para enviar.",
"invalidRecipient": "Por favor ingrese una billetera de destino válida.",
"recipientAddress": "Dirección del recipiente",
"youAreSending": "Estás enviando",
"willReceive": "recibirá al menos",
"to": "a",
"addLiquidity": "Agregar liquidez",
"deposit": "Depositar",
"currentPoolSize": "Tamaño del Pool Actual",
"yourPoolShare": "Tu parte del Pool",
"noZero": "El monto no puede ser cero.",
"mustBeETH": "Una de las entradas debe ser ETH.",
"enterCurrencyOrLabelCont": "Ingresá un valor de {{ inputCurrency }} o de {{ label }} para continuar.",
"youAreAdding": "Estás agregando entre",
"and": "y",
"intoPool": "en el pool de liquidez.",
"outPool": "en el pool de liquidez.",
"youWillMint": "Vas a acuñar",
"liquidityTokens": "tokens de liquidez.",
"totalSupplyIs": "El actual suministro total de tokens de liquidez es",
"youAreSettingExRate": "Está configurando el tipo de cambio inicial a",
"totalSupplyIs0": "El actual suministro total de tokens de liquidez es 0.",
"tokenWorth": "Al tipo de cambio actual, cada token del pool vale",
"firstLiquidity": "Sos la primer persona en agregar liquidez!",
"initialExchangeRate": "El tipo de cambio inicial se establecerá en función de tus depósitos. Por favor, asegúrate de que tus depósitos en ETH y {{ label }} tengan el mismo valor fíat.",
"removeLiquidity": "Remover Liquidez",
"poolTokens": "Pool de Tokens",
"enterLabelCont": "Ingresá un valor de {{ label }} para continuar.",
"youAreRemoving": "Estás quitando entre",
"youWillRemove": "Vas a remover",
"createExchange": "Crear divisa",
"invalidTokenAddress": "No es una dirección de token válida",
"exchangeExists": "La divisa {{ label }} ya existe!",
"invalidSymbol": "Símbolo inválido",
"invalidDecimals": "Decimales inválidos",
"tokenAddress": "Dirección de Token",
"label": "Etiqueta",
"decimals": "Decimales",
"enterTokenCont": "Ingresá una dirección de token para continuar"
}

View File

@@ -1,75 +0,0 @@
{
"noWallet": "No se ha encontrado billetera de Ethereum",
"wrongNetwork": "Se encuentra en la red equivocada",
"switchNetwork": "Por favor cambie a {{ correctNetwork }}",
"installWeb3MobileBrowser": "Por favor ingrese desde un navegador móvil con web3 habilitado como Trust Wallet o Coinbase Wallet.",
"installMetamask": "Por favor visítenos nuevamente luego de instalar Metamask en Chrome o Brave.",
"disconnected": "Desconectado",
"swap": "Intercambiar",
"send": "Enviar",
"pool": "Pool",
"betaWarning": "Este proyecto se encuentra en beta. Úselo bajo tu propio riesgo.",
"input": "Entrada",
"output": "Salida",
"estimated": "estimado",
"balance": "Saldo: {{ balanceInput }}",
"unlock": "Desbloquear",
"pending": "Pendiente",
"selectToken": "Seleccione un token",
"searchOrPaste": "Buscar Token o Pegar Dirección",
"noExchange": "No se ha encontrado la divisa",
"exchangeRate": "Tasa de Cambio",
"enterValueCont": "Ingrese un valor en {{ missingCurrencyValue }} para continuar.",
"selectTokenCont": "Seleccione un token para continuar.",
"noLiquidity": "Sin liquidez.",
"unlockTokenCont": "Por favor desbloquea un token para continuar.",
"transactionDetails": "Detalles de la transacción",
"hideDetails": "Ocultar detalles",
"youAreSelling": "Está vendiendo",
"orTransFail": "o la transacción fallará.",
"youWillReceive": "Va a recibir al menos",
"youAreBuying": "Está comprando",
"itWillCost": "Costará a lo sumo",
"insufficientBalance": "Saldo insuficiente",
"inputNotValid": "No es un valor de entrada válido",
"differentToken": "Debe ser un token distinto.",
"noRecipient": "Ingrese una dirección de billetera para enviar.",
"invalidRecipient": "Por favor ingrese una billetera de destino válida.",
"recipientAddress": "Dirección del recipiente",
"youAreSending": "Está enviando",
"willReceive": "recibirá al menos",
"to": "a",
"addLiquidity": "Agregar liquidez",
"deposit": "Depositar",
"currentPoolSize": "Tamaño del Pool Actual",
"yourPoolShare": "Su parte del Pool",
"noZero": "El monto no puede ser cero.",
"mustBeETH": "Una de las entradas debe ser ETH.",
"enterCurrencyOrLabelCont": "Ingrese un valor de {{ inputCurrency }} o de {{ label }} para continuar.",
"youAreAdding": "Está agregando entre",
"and": "y",
"intoPool": "en el pool de liquidez.",
"outPool": "en el pool de liquidez.",
"youWillMint": "Va a acuñar",
"liquidityTokens": "tokens de liquidez.",
"totalSupplyIs": "El actual suministro total de tokens de liquidez es",
"youAreSettingExRate": "Está configurando el tipo de cambio inicial a",
"totalSupplyIs0": "El actual suministro total de tokens de liquidez es 0.",
"tokenWorth": "Al tipo de cambio actual, cada token del pool vale",
"firstLiquidity": "Es la primer persona en agregar liquidez!",
"initialExchangeRate": "El tipo de cambio inicial se establecerá en función de sus depósitos. Por favor, asegúrese de que sus depósitos en ETH y {{ label }} tengan el mismo valor fíat.",
"removeLiquidity": "Remover Liquidez",
"poolTokens": "Pool de Tokens",
"enterLabelCont": "Ingresa un valor de {{ label }} para continuar.",
"youAreRemoving": "Está quitando entre",
"youWillRemove": "Va a remover",
"createExchange": "Crear tipo de cambio",
"invalidTokenAddress": "No es una dirección de token válida",
"exchangeExists": "El tipo de cambio {{ label }} ya existe!",
"invalidSymbol": "Símbolo inválido",
"invalidDecimals": "Decimales inválidos",
"tokenAddress": "Dirección de Token",
"label": "Etiqueta",
"decimals": "Decimales",
"enterTokenCont": "Ingrese una dirección de token para continuar"
}

View File

@@ -1,87 +0,0 @@
{
"noWallet": "Wallet Ethereum non trovato",
"wrongNetwork": "Sei connesso alla rete sbagliata",
"switchNetwork": "Perfavore connettiti su {{ correctNetwork }}",
"installWeb3MobileBrowser": "Perfavore visita il sito da un browser abilitato web3 o da un app mobile come Trust Wallet o Coinbase Wallet.",
"installMetamask": "Perfavore ritorna dopo aver installato Metamask su Chrome o Brave.",
"disconnected": "Disconnesso",
"swap": "Scambia",
"swapAnyway": "Scambia comunque",
"send": "Invia",
"sendAnyway": "Invia comunque",
"pool": "Riserva",
"betaWarning": "Questo progetto è in beta. Usalo a tuo rischio.",
"input": "Input",
"output": "Output",
"estimated": "stimato",
"balance": "Saldo: {{ balanceInput }}",
"unlock": "Sblocca",
"pending": "In attesa",
"selectToken": "Seleziona un token",
"searchOrPaste": "Cerca Nome, Simbolo o Indirizzo Token",
"searchOrPasteMobile": "Nome, Simbolo, o Indirizzo",
"noExchange": "Nessun Exchange Trovato",
"exchangeRate": "Tasso di cambio",
"unknownError": "Oops! Si è verificato un Errore imprevisto. Aggiorna la pagina o visita da un altro browser o dispositivo.",
"enterValueCont": "Inserisci un valore {{ missingCurrencyValue }} per continuare.",
"selectTokenCont": "Seleziona un token per continuare.",
"noLiquidity": "Nessuna liquidità.",
"insufficientLiquidity": "Liquidità insufficiente.",
"unlockTokenCont": "Si prega di sbloccare il token per continuare.",
"transactionDetails": "Dettagli avanzati",
"hideDetails": "Nascondi dettagli",
"slippageWarning": "Avviso di scostamento",
"highSlippageWarning": "Avviso di elevato scostamento",
"youAreSelling": "Stai vendendo",
"orTransFail": "o la transazione fallità.",
"youWillReceive": "Riceverai almeno",
"youAreBuying": "Stai comprando",
"itWillCost": "Costerà al massimo",
"forAtMost": "per al massimo",
"insufficientBalance": "Saldo insufficente",
"inputNotValid": "Non è un valore di input valido",
"differentToken": "Deve essere un token diverso.",
"noRecipient": "Inserisci un indirizzo di wallet a cui inviare.",
"invalidRecipient": "Inserisci un destinatario valido per l'indirizzo del wallet.",
"recipientAddress": "Indirizzo del destinatario",
"youAreSending": "Stai inviando",
"willReceive": "riceverà almeno",
"to": "a",
"addLiquidity": "Aggiungi liquidità",
"deposit": "Depositare",
"currentPoolSize": "Dimensione attuale del pool",
"yourPoolShare": "La tua parte di pool condivisa",
"noZero": "L'importo non può essere zero.",
"mustBeETH": "Uno degli input deve essere ETH.",
"enterCurrencyOrLabelCont": "Inserisci un valore {{ inputCurrency }} o {{ label }} per continuare.",
"youAreAdding": "Stai agginugendo",
"and": "e",
"intoPool": "nella riserva di liquidità.",
"outPool": "dalla riserva di liquidità.",
"youWillMint": "Tu conierai",
"liquidityTokens": "token di liquidità.",
"totalSupplyIs": "L'attuale disponibilità totale di token di liquidità è",
"youAreSettingExRate": "Stai impostando il tasso di cambio iniziale su",
"totalSupplyIs0": "L'attuale disponibilità totale di token di liquidità è 0.",
"tokenWorth": "Al tasso di cambio corrente, ogni token del pool vale",
"firstLiquidity": "Sei la prima persona ad aggiungere liquidità!",
"initialExchangeRate": "Il tasso di cambio iniziale verrà impostato in base ai tuoi depositi. Assicurati che i tuoi depositi ETH e {{ label }} abbiano lo stesso valore fiat.",
"removeLiquidity": "Rimuovi Liquidità",
"poolTokens": "Token Pool",
"enterLabelCont": "Inserisci un valore {{ label }} per continuare.",
"youAreRemoving": "Stai rimuovendo tra",
"youWillRemove": "Rimuoverai",
"createExchange": "Crea scambio",
"invalidTokenAddress": "Indirizzo token non valido",
"exchangeExists": "{{ label }} Exchange già esistente!",
"invalidSymbol": "Simbolo non valido",
"invalidDecimals": "Decimali non validi",
"tokenAddress": "Indirizzo Token",
"label": "Etichetta",
"name": "Nome",
"symbol": "Simbolo",
"decimals": "Decimali",
"enterTokenCont": "Inserire un indirizzo token per continuare",
"priceChange": "Scostamento del prezzo previsto",
"forAtLeast": "per almeno "
}

View File

@@ -1,75 +0,0 @@
{
"noWallet": "לא נמצא ארנק",
"wrongNetwork": "נבחרה רשת לא נכונה",
"switchNetwork": "{{ correctNetwork }} יש צורך לשנות את הרשת ל",
"installWeb3MobileBrowser": "יש צורך בארנק ווב3.0, תתקין מטאמאסק או ארנק דומה",
"installMetamask": " Metamask יש צורך להתקין תוסף מטאמאסק לדפדפן, חפשו בגוגל ",
"disconnected": "מנותק",
"swap": "המרה",
"send": "שליחה",
"pool": "להפקיד",
"betaWarning": "הפרויקט נמצא בשלב בטא, השתמשו באחריות",
"input": "מוכר",
"output": "אקבל",
"estimated": "הערכה",
"balance": "בארנק שלי {{ balanceInput }}",
"unlock": "שחרור נעילת ארנק",
"pending": "ממתין לאישור",
"selectToken": "בחרו את הטוקן להמרה",
"searchOrPaste": "הכניסו שם או כתובת של טוקן לחיפוש",
"noExchange": "לא מתאפשרת המרה",
"exchangeRate": "שער המרה",
"enterValueCont": "כדי להמשיך {{ missingCurrencyValue }} הזינו ",
"selectTokenCont": "בחרו טוקן כדי להמשיך",
"noLiquidity": "אין נזילות",
"unlockTokenCont": "יש צורך לאשר את הטוקן למסחר",
"transactionDetails": "פרטי הטרנזקציה",
"hideDetails": "הסתר פרטים נוספים",
"youAreSelling": "למכירה",
"orTransFail": "או שהטרנזקציה תיכשל",
"youWillReceive": "תוצר המרה מינימלי",
"youAreBuying": "קונה",
"itWillCost": "זה יעלה",
"insufficientBalance": "אין בחשבון מספיק מטבעות",
"inputNotValid": "קלט לא תקין",
"differentToken": "יש צורך בטוקנים שונים",
"noRecipient": "לא הוכנסה כתובת ארנק יעד",
"invalidRecipient": "לא הוכנסה כתובת תקינה",
"recipientAddress": "כתובת יעד",
"youAreSending": "כמות לשליחה",
"willReceive": "יתקבל לכל הפחות",
"to": "אל",
"addLiquidity": "להוספת נזילות למאגר",
"deposit": "הפקדה",
"currentPoolSize": "גודל מאגר הנזילות הכולל",
"yourPoolShare": "חלקך במאגר הנזילות",
"noZero": "אפס אינו ערך תקין",
"mustBeETH": "ETH חייב להופיע באחד מהצדדים",
"enterCurrencyOrLabelCont": "כדי להמשיך {{ inputCurrency }} או {{ label }} הכנס",
"youAreAdding": "מתווספים למאגר",
"and": "וגם",
"intoPool": "לתוך הנזילות",
"outPool": "מתוך",
"youWillMint": "יונפקו לכם",
"liquidityTokens": "טוקנים של נזילות",
"totalSupplyIs": "חלקך במאגר הנזילות",
"youAreSettingExRate": "שער ההמרה יקבע על ידך",
"totalSupplyIs0": "אין לך טוקנים של נזילות",
"tokenWorth": "שווי כל טוקן נזילות הינו",
"firstLiquidity": "אתה הראשוןה שמזרים נזילות למאגר",
"initialExchangeRate": "ושל האית'ר הינן בערך שווה {{ label }} תוודאו שההפקדה של הטוקן",
"removeLiquidity": "הוצאה של נזילות",
"poolTokens": "טוקנים של מאגר הנזילות",
"enterLabelCont": "כדי להמשיך {{ label }} הכנס ",
"youAreRemoving": "יוסרו",
"youWillRemove": "יוסרו",
"createExchange": "ליצירת זוג מסחר",
"invalidTokenAddress": "כתובת טוקן לא נכונה",
"exchangeExists": "{{ label }} כבר קיים זוג המרה עבור",
"invalidSymbol": "תו שגוי",
"invalidDecimals": "ספרות עשרוניות שגויות",
"tokenAddress": "כתובת הטוקן",
"label": "שם",
"decimals": "ספרות עשרויות",
"enterTokenCont": "הכניסו כתובת טוקן כדי להמשיך"
}

View File

@@ -1,91 +0,0 @@
{
"noWallet": "Niciun portofel Ethereum găsit",
"wrongNetwork": "Nu ești conectat la rețeaua corectă",
"switchNetwork": "Conectează-te te rog la {{ correctNetwork }}",
"installWeb3MobileBrowser": "Incearcă să vizitezi această pagina folosind un browser precum Trust Wallet sau Coinbase Wallet.",
"installMetamask": "Vizitează această pagină din nou după ce instalezi MetaMask în Chrome sau Brave",
"disconnected": "Deconectat",
"swap": "Schimbă",
"swapAnyway": "Schimbă Oricum",
"send": "Trimite",
"sendAnyway": "Trimite Oricum",
"pool": "Depune Lichiditate",
"betaWarning": "Proiectul este încă în versiunea beta. Folosește-l cu grijă, riscul este al tău.",
"input": "Input",
"output": "Output",
"estimated": "estimat",
"balance": "Balanță: {{ balanceInput }}",
"unlock": "Deblochează",
"pending": "În Așteptare",
"selectToken": "Selectează un jeton",
"searchOrPaste": "Caută după Numele, Simbolul sau Adresa Jetonului",
"searchOrPasteMobile": "Nume, Simbol sau Adresă",
"noExchange": "Nicio Piață de Schimb Găsită",
"noToken": "Nicin Jeton Găsit",
"exchangeRate": "Curs de Schimb",
"unknownError": "Ups! A intervenit o eroare tehnică. Te rog reîncarcă pagina, sau acceseaz-o de pe alt navigator sau dispozitiv.",
"enterValueCont": "Setează o valoare pentru {{ missingCurrencyValue }} pentru a continua.",
"selectTokenCont": "Selectează un jeton pentru a continua.",
"noLiquidity": "Nu Există Lichiditate.",
"insufficientLiquidity": "Lichiditate Insuficientă.",
"unlockTokenCont": "Te rog deblochează jetonul pentru a continua.",
"transactionDetails": "Detalii Avansate",
"hideDetails": "Ascunde Detaili",
"slippageWarning": "Alertă Deviație de Preț",
"highSlippageWarning": "Alertă Deviație de Preț Mare",
"youAreSelling": "Tu vinzi",
"orTransFail": "sau tranzacția va eșua.",
"youWillReceive": "Vei primi cel puțin",
"youAreBuying": "Tu cumperi",
"itWillCost": "Va costa cel mult",
"forAtMost": "pentru maximum",
"insufficientBalance": "Balanță Insuficientă",
"inputNotValid": "Valoarea setată nu este validă",
"differentToken": "Trebuie să fie un jeton diferit.",
"noRecipient": "Setează o adresă de portofel pentru destinatar.",
"invalidRecipient": "Te rog setează o adresă de portofel validă pentru destinatar.",
"recipientAddress": "Adresa Destinatarului",
"youAreSending": "Tu trimiți",
"willReceive": "vei primi cel puțin",
"to": "spre",
"addLiquidity": "Adaugă Lichiditate",
"deposit": "Depozitează",
"currentPoolSize": "Volumul Actual al Fondului",
"yourPoolShare": "Partea Ta din Fond",
"noZero": "Cantitatea nu poate fi zero.",
"mustBeETH": "Una dintre valori trebuie să fie ETH.",
"enterCurrencyOrLabelCont": "Setează o valoare pentru {{ inputCurrency }} sau {{ label }} pentru a continua. ",
"youAreAdding": "Tu adaugi",
"and": "și",
"intoPool": "în fondul de lichidatate.",
"outPool": "din fondul de lichiditate.",
"youWillMint": "Tu vei tipări",
"liquidityTokens": "jetoane de lichiditate.",
"totalSupplyIs": "Cantitatea totală de jetoane de lichiditate este",
"youAreSettingExRate": "Setezi cursul de schimb inițial la",
"totalSupplyIs0": "Cantitatea totală de jetoane de lichiditate este 0.",
"tokenWorth": "La cursul de schimb actual, fiecare jeton de lichiditate este valorat la",
"firstLiquidity": "Ești prima persoană care depune lichiditate!",
"initialExchangeRate": "Cursul de schimb inițial va fi setat în funcție de depozitele tale. Te rog asigură-te că ETH-ul și {{ label }}-ul pe care le-ai depozitat au aceeași valoare în bani fiat.",
"removeLiquidity": "Retrage Lichiditat",
"poolTokens": "Depune Jetoane",
"enterLabelCont": "Setează o valoare pentru {{ label }} pentru a continua.",
"youAreRemoving": "Retragi între",
"youWillRemove": "Vei retrage",
"createExchange": "Creează Piață de Schimb",
"invalidTokenAddress": "Adresa de jeton nu este validă",
"exchangeExists": "{{ label }} Piața de schimb există deja!",
"invalidSymbol": "Simbol invalid",
"invalidDecimals": "Zecimale invalide",
"tokenAddress": "Adresă Jeton",
"label": "Denumire",
"name": "Nume",
"symbol": "Simbol",
"decimals": "Zecimale",
"enterTokenCont": "Setează o adresă de jeton pentru a continua",
"priceChange": "Deviație de preț așteptată",
"forAtLeast": "pentru cel puțin ",
"brokenToken": "Jetonul selectat nu este compatibil cu Uniswap V1. Depunerea de lichiditate îți va bloca fondurile pe vecie.",
"toleranceExplanation": "Micșorând această limită, vei reduce riscul de frontrunning. În același timp, devine mai probabil că tranzacția va eșua din cauza variațiilor normale de preț.",
"tokenSearchPlaceholder": "Caută nume sau lipește adresă"
}

View File

@@ -1,75 +0,0 @@
{
"noWallet": "Кошелек эфира не найден",
"wrongNetwork": "Некорректная сеть",
"switchNetwork": "Пожалуйста, перейдите в {{ correctNetwork }}",
"installWeb3MobileBrowser": "Пожалуйста, откройте в браузере с поддержкой web3, таком, как Trust Wallet или Coinbase Wallet.",
"installMetamask": "Пожалуйста, откройте в Chrome или Brave с установленным расширением Metamask.",
"disconnected": "Нет подключения",
"swap": "Обменять",
"send": "Отправить",
"pool": "Вложить",
"betaWarning": "Проект находится на стадии бета тестирования.",
"input": "Ввести",
"output": "Вывести",
"estimated": "по оценке",
"balance": "Баланс: {{ balanceInput }}",
"unlock": "Разблокировать",
"pending": "Ожидание",
"selectToken": "Выберите токен",
"searchOrPaste": "Поиск токена или вставить адрес токена",
"noExchange": "Обмен не найден",
"exchangeRate": "Курс обмена",
"enterValueCont": "Введите {{ missingCurrencyValue }}, чтобы продолжить.",
"selectTokenCont": "Введите токен, чтобы продолжить.",
"noLiquidity": "Нет ликвидности.",
"unlockTokenCont": "Пожалуйста, разблокируйте токен, чтобы продолжить.",
"transactionDetails": "Детали транзакции",
"hideDetails": "Скрыть подробности",
"youAreSelling": "Вы продаете",
"orTransFail": "или транзакция будет отклонена.",
"youWillReceive": "Вы получите как минимум",
"youAreBuying": "Вы покупаете",
"itWillCost": "В крайнем случае это будет стоить",
"insufficientBalance": "Недостаточно средств",
"inputNotValid": "Некорректное значение",
"differentToken": "Должны быть разные токены.",
"noRecipient": "Введите адрес кошелька эфира, куда перечислить.",
"invalidRecipient": "Пожалуйста, введите корректный адрес кошелька получателя.",
"recipientAddress": "Адрес получателя",
"youAreSending": "Вы отправляете",
"willReceive": "получит как минимум",
"to": "",
"addLiquidity": "Добавить ликвидность",
"deposit": "Вложить",
"currentPoolSize": "Текущий размер пула",
"yourPoolShare": "Ваша доля в пуле",
"noZero": "Значение не может быть нулевым.",
"mustBeETH": "Одно из значений должно быть ETH.",
"enterCurrencyOrLabelCont": "Введите {{ inputCurrency }} или {{ label }}, чтобы продолжить.",
"youAreAdding": "Вы добавляете от",
"and": "и",
"intoPool": "в пул ликвидности.",
"outPool": "из пула ликвидности.",
"youWillMint": "Вы произведёте",
"liquidityTokens": "токенов ликвидности.",
"totalSupplyIs": "Ваш объем токенов ликвидности",
"youAreSettingExRate": "Вы устанавливаете начальный курс обмена",
"totalSupplyIs0": "Ваш объем токенов ликвидности 0.",
"tokenWorth": "При текущем курсе, каждый токен пула оценивается в",
"firstLiquidity": "Вы первый, кто создаст ликвидность!",
"initialExchangeRate": "Начальный курс обмена будет установлен согласно вашим депозитам. Убедитесь, что ваши депозиты ETH и {{ label }} имеют одинаковое значение в валюте.",
"removeLiquidity": "Убрать ликвидность",
"poolTokens": "Токены пула",
"enterLabelCont": "Введите {{ label }}, чтобы продолжить.",
"youAreRemoving": "Вы убираете в от",
"youWillRemove": "Вы уберёте",
"createExchange": "Создать обмен",
"invalidTokenAddress": "Некорректный адрес токена",
"exchangeExists": "{{ label }} Обмен уже существует!",
"invalidSymbol": "Некорректный символ",
"invalidDecimals": "Некорректное десятичное значение",
"tokenAddress": "Адрес токена",
"label": "Название",
"decimals": "Десятичное значение",
"enterTokenCont": "Чтобы продолжить, введите адрес токена"
}

View File

@@ -1,87 +0,0 @@
{
"noWallet": "Không tìm thấy ví tiền Ethereum",
"wrongNetwork": "Kết nối mạng không đúng",
"switchNetwork": "Vui lòng chuyển sang {{ correctNetwork }}",
"installWeb3MobileBrowser": "Vui lòng truy cập từ trình duyệt di động hỗ trợ web3 như là Ví Trust hoặc Ví Coinbase",
"installMetamask": "Vui lòng truy cập sau khi cài đặt Metamask trên Chrome hoặc Brave.",
"disconnected": "Ngắt kết nối rồi",
"swap": "Hoán đổi",
"swapAnyway": "Tiếp tục hoán đổi?",
"send": "Gửi",
"sendAnyway": "Tiếp tục gửi?",
"pool": "Chung vốn",
"betaWarning": "Dự án này đang trong giai đoạn thử nghiệm. Sử dụng có rủi ro của riêng bạn",
"input": "Đầu vào",
"output": "Đầu ra",
"estimated": "ước lượng",
"balance": "Số dư: {{ balanceInput }}",
"unlock": "Mở khóa",
"pending": "Đang chờ xử lý",
"selectToken": "Chọn một đồng tiền ảo",
"searchOrPaste": "Tìm kiếm tên, biểu tượng, hoặc địa chỉ của đồng tiền ảo",
"searchOrPasteMobile": "Tên, Biểu tượng, hoặc Địa chỉ",
"noExchange": "Không tìm thấy giao dịch",
"exchangeRate": "Tỷ giá",
"unknownError": "Rất tiếc! Xảy ra lỗi không xác định. Vui lòng làm mới trang, hoặc truy cập từ trình duyệt hay thiết bị khác.",
"enterValueCont": "Nhập một giá trị {{ missingCurrencyValue }} để tiếp tục.",
"selectTokenCont": "Chọn một đồng tiền ảo để tiếp tục.",
"noLiquidity": "Không có tính thanh khoản.",
"insufficientLiquidity": "Không đủ tính thanh khoản.",
"unlockTokenCont": "Vui lòng mở khoá đồng tiền ảo để tiếp tục",
"transactionDetails": "Chi tiết nâng cao",
"hideDetails": "Ẩn chi tiết",
"slippageWarning": "Cảnh báo trượt giá",
"highSlippageWarning": "Cảnh báo trượt giá cao",
"youAreSelling": "Bạn đang bán",
"orTransFail": "hoặc giao dịch sẽ thất bại.",
"youWillReceive": "Bạn sẽ nhận dược ít nhất là",
"youAreBuying": "Bạn đang mua",
"itWillCost": "Nó sẽ có giá cao nhất",
"forAtMost": "nhiều nhất",
"insufficientBalance": "Số dư không đủ",
"inputNotValid": "Giá trị nhập vào không hợp lệ",
"differentToken": "Đồng tiền ảo phải khác nhau.",
"noRecipient": "Nhập địa chỉ ví để gửi đến.",
"invalidRecipient": "Vui lòng nhập một người nhận địa chỉ ví hợp lệ.",
"recipientAddress": "Địa chỉ người nhận",
"youAreSending": "Bạn đang gửi",
"willReceive": "sẽ nhận dược ít nhất là",
"to": "đến",
"addLiquidity": "Thêm tiền thanh khoản",
"deposit": "Gửi tiền",
"currentPoolSize": "Quy mô hiện tại của quỹ",
"yourPoolShare": "Phần hùn của bạn trong quỹ",
"noZero": "Số tiền không thể bằng không.",
"mustBeETH": "Một trong những đầu vào phải là ETH.",
"enterCurrencyOrLabelCont": "Nhập giá trị {{ inputCurrency }} hoặc {{ label }} để tiếp tục.",
"youAreAdding": "Bạn đang thêm",
"and": "và",
"intoPool": "vào nhóm thanh khoản.",
"outPool": "từ nhóm thanh khoản.",
"youWillMint": "Bạn sẽ đúc tiền",
"liquidityTokens": "đồng thanh khoản.",
"totalSupplyIs": "Tổng cung hiện tại của đồng thanh khoản là",
"youAreSettingExRate": "Bạn đang đặt tỷ giá hối đoái ban đầu thành",
"totalSupplyIs0": "Tổng cung hiện tại của đồng thanh khoản là 0.",
"tokenWorth": "Tại tỷ giá hối đoái hiện tại, giá trị đồng token của quỹ là",
"firstLiquidity": "Bạn là người đầu tiên thêm thanh khoản!",
"initialExchangeRate": "Tỷ giá hối đoái ban đầu sẽ được thiết lập dựa trên tiền gửi của bạn. Vui lòng đảm bảo rằng tiền gửi ETH và {{ label }} của bạn có cùng giá trị tiền định danh.",
"removeLiquidity": "Loại bỏ thanh khoản",
"poolTokens": "Đồng tiền ảo của quỹ",
"enterLabelCont": "Nhập giá trị {{ label }} để tiếp tục",
"youAreRemoving": "Bạn đang loại bỏ giữa",
"youWillRemove": "Bạn sẽ loại bỏ",
"createExchange": "Tạo giao dịch",
"invalidTokenAddress": "Địa chỉ đồng tiền điện tử không hợp lệ",
"exchangeExists": "{{ label }} Giao dịch đã tồn tại!",
"invalidSymbol": "Biểu tượng không hợp lệ",
"invalidDecimals": "Số thập phân không hợp lệ",
"tokenAddress": "Địa chỉ đồng tiền điện tử",
"label": "Nhãn",
"name": "Tên",
"symbol": "Biểu tượng",
"decimals": "Số thập phân",
"enterTokenCont": "Nhập địa chỉ đồng tiền ảo để tiếp tục",
"priceChange": "Trượt giá dự kiến",
"forAtLeast": "cho ít nhất "
}

View File

@@ -1,75 +0,0 @@
{
"noWallet": "未发现以太钱包",
"wrongNetwork": "网络错误",
"switchNetwork": "请切换到 {{ correctNetwork }}",
"installWeb3MobileBrowser": "请从支持web3的移动端浏览器如 Trust Wallet 或 Coinbase Wallet 访问。",
"installMetamask": "请从安装了 Metamask 插件的 Chrome 或 Brave 访问。",
"disconnected": "未连接",
"swap": "兑换",
"send": "发送",
"pool": "资金池",
"betaWarning": "项目尚处于beta阶段。使用需自行承担风险。",
"input": "输入",
"output": "输出",
"estimated": "估计",
"balance": "余额: {{ balanceInput }}",
"unlock": "解锁",
"pending": "处理中",
"selectToken": "选择通证",
"searchOrPaste": "搜索通证或粘贴地址",
"noExchange": "未找到交易所",
"exchangeRate": "兑换率",
"enterValueCont": "输入{{ missingCurrencyValue }}值并继续。",
"selectTokenCont": "选取通证继续。",
"noLiquidity": "没有流动金。",
"unlockTokenCont": "请解锁通证并继续。",
"transactionDetails": "交易明细",
"hideDetails": "隐藏明细",
"youAreSelling": "你正在出售",
"orTransFail": "或交易失败。",
"youWillReceive": "你将至少收到",
"youAreBuying": "你正在购买",
"itWillCost": "它将至少花费",
"insufficientBalance": "余额不足",
"inputNotValid": "无效的输入值",
"differentToken": "必须是不同的通证。",
"noRecipient": "输入接收钱包地址。",
"invalidRecipient": "请输入有效的收钱地址。",
"recipientAddress": "接收地址",
"youAreSending": "你正在发送",
"willReceive": "将至少收到",
"to": "至",
"addLiquidity": "添加流动金",
"deposit": "存入",
"currentPoolSize": "当前资金池大小",
"yourPoolShare": "你的资金池份额",
"noZero": "金额不能为零。",
"mustBeETH": "输入中必须有一个是 ETH。",
"enterCurrencyOrLabelCont": "输入 {{ inputCurrency }} 或 {{ label }} 值并继续。",
"youAreAdding": "你将添加",
"and": "和",
"intoPool": "入流动资金池。",
"outPool": "出流动资金池。",
"youWillMint": "你将铸造",
"liquidityTokens": "流动通证。",
"totalSupplyIs": "当前流动通证的总量是",
"youAreSettingExRate": "你将初始兑换率设置为",
"totalSupplyIs0": "当前流动通证的总量是0。",
"tokenWorth": "当前兑换率下,每个资金池通证价值",
"firstLiquidity": "你是第一个添加流动金的人!",
"initialExchangeRate": "初始兑换率将由你的存入情况决定。请确保你存入的 ETH 和 {{ label }} 具有相同的总市值。",
"removeLiquidity": "删除流动金",
"poolTokens": "资金池通证",
"enterLabelCont": "输入 {{ label }} 值并继续。",
"youAreRemoving": "你正在移除",
"youWillRemove": "你将移除",
"createExchange": "创建交易所",
"invalidTokenAddress": "通证地址无效",
"exchangeExists": "{{ label }} 交易所已存在!",
"invalidSymbol": "通证符号无效",
"invalidDecimals": "小数位数无效",
"tokenAddress": "通证地址",
"label": "通证符号",
"decimals": "小数位数",
"enterTokenCont": "输入通证地址并继续"
}

View File

@@ -1,75 +0,0 @@
{
"noWallet": "未偵測到以太坊錢包",
"wrongNetwork": "你位在錯誤的網路",
"switchNetwork": "請切換到 {{ correctNetwork }}",
"installWeb3MobileBrowser": "請安裝含有 web3 瀏覽器的手機錢包,如 Trust Wallet 或 Coinbase Wallet。",
"installMetamask": "請使用 Chrome 或 Brave 瀏覽器安裝 Metamask。",
"disconnected": "未連接",
"swap": "兌換",
"send": "發送",
"pool": "資金池",
"betaWarning": "本產品仍在測試階段。使用者需自負風險。",
"input": "輸入",
"output": "輸出",
"estimated": "估計",
"balance": "餘額: {{ balanceInput }}",
"unlock": "解鎖",
"pending": "處理中",
"selectToken": "選擇代幣",
"searchOrPaste": "選擇代幣或輸入地址",
"noExchange": "找不到交易所",
"exchangeRate": "匯率",
"enterValueCont": "輸入 {{ missingCurrencyValue }} 以繼續。",
"selectTokenCont": "選擇代幣以繼續。",
"noLiquidity": "沒有流動性資金。",
"unlockTokenCont": "解鎖代幣以繼續。",
"transactionDetails": "交易明細",
"hideDetails": "隱藏明細",
"youAreSelling": "你正在出售",
"orTransFail": "或交易失敗。",
"youWillReceive": "你將至少收到",
"youAreBuying": "你正在購買",
"itWillCost": "這將花費至多",
"insufficientBalance": "餘額不足",
"inputNotValid": "無效的輸入值",
"differentToken": "必須是不同的代幣。",
"noRecipient": "請輸入收款人錢包地址。",
"invalidRecipient": "請輸入有效的錢包地址。",
"recipientAddress": "收款人錢包地址",
"youAreSending": "你正在發送",
"willReceive": "將至少收到",
"to": "至",
"addLiquidity": "增加流動性資金",
"deposit": "存入",
"currentPoolSize": "目前的資金池總量",
"yourPoolShare": "你在資金池中的佔比",
"noZero": "金額不能為零。",
"mustBeETH": "輸入中必須包含 ETH。",
"enterCurrencyOrLabelCont": "輸入 {{ inputCurrency }} 或 {{ label }} 以繼續。",
"youAreAdding": "你將把",
"and": "和",
"intoPool": "加入資金池。",
"outPool": "領出資金池。",
"youWillMint": "你將產生",
"liquidityTokens": "流動性代幣。",
"totalSupplyIs": "目前流動性代幣供給總量為",
"youAreSettingExRate": "初始的匯率將被設定為",
"totalSupplyIs0": "目前流動性代幣供給為零。",
"tokenWorth": "依據目前的匯率,每個流動性代幣價值",
"firstLiquidity": "您是第一個提供流動性資金的人!",
"initialExchangeRate": "初始的匯率將取決於你存入的資金。請確保存入的 ETH 和 {{ label }} 的價值相等。",
"removeLiquidity": "領出流動性資金",
"poolTokens": "資金池代幣",
"enterLabelCont": "輸入 {{ label }} 以繼續。",
"youAreRemoving": "您正在移除",
"youWillRemove": "您即將移除",
"createExchange": "創建交易所",
"invalidTokenAddress": "無效的代幣地址",
"exchangeExists": "{{ label }} 的交易所已經存在!",
"invalidSymbol": "代幣符號錯誤",
"invalidDecimals": "小數位數錯誤",
"tokenAddress": "代幣地址",
"label": "代幣符號",
"decimals": "小數位數",
"enterTokenCont": "輸入代幣地址"
}

View File

@@ -0,0 +1,61 @@
[
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "_transactions",
"type": "tuple[]"
}
],
"name": "wc_multiCall",
"outputs": [
{
"internalType": "bytes[]",
"name": "",
"type": "bytes[]"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "_msgHash",
"type": "bytes32"
},
{
"internalType": "bytes",
"name": "_signature",
"type": "bytes"
}
],
"name": "isValidSignature",
"outputs": [
{
"internalType": "bytes4",
"name": "",
"type": "bytes4"
}
],
"stateMutability": "view",
"type": "function"
}
]

View File

@@ -1,55 +0,0 @@
[
{
"inputs": [
{
"internalType": "address",
"name": "_factoryV1",
"type": "address"
},
{
"internalType": "address",
"name": "_router",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "amountTokenMin",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "amountETHMin",
"type": "uint256"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "deadline",
"type": "uint256"
}
],
"name": "migrate",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"stateMutability": "payable",
"type": "receive"
}
]

View File

@@ -1,6 +0,0 @@
import { Interface } from '@ethersproject/abi'
import { abi as STAKING_REWARDS_ABI } from '@uniswap/liquidity-staker/build/StakingRewards.json'
const STAKING_REWARDS_INTERFACE = new Interface(STAKING_REWARDS_ABI)
export { STAKING_REWARDS_INTERFACE }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 883 KiB

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 670 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 413 KiB

View File

@@ -1,9 +1,10 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import useCopyClipboard from '../../hooks/useCopyClipboard'
import { LinkStyledButton } from '../../theme'
import { CheckCircle, Copy } from 'react-feather'
import { Trans } from '@lingui/macro'
const CopyIcon = styled(LinkStyledButton)`
color: ${({ theme }) => theme.text3};
@@ -33,7 +34,9 @@ export default function CopyHelper(props: { toCopy: string; children?: React.Rea
{isCopied ? (
<TransactionStatusText>
<CheckCircle size={'16'} />
<TransactionStatusText>Copied</TransactionStatusText>
<TransactionStatusText>
<Trans>Copied</Trans>
</TransactionStatusText>
</TransactionStatusText>
) : (
<TransactionStatusText>

View File

@@ -1,11 +1,11 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { CheckCircle, Triangle } from 'react-feather'
import { useActiveWeb3React } from '../../hooks'
import { getEtherscanLink } from '../../utils'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink } from '../../theme'
import { useAllTransactions } from '../../state/transactions/hooks'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { RowFixed } from '../Row'
import Loader from '../Loader'
@@ -49,7 +49,11 @@ export default function Transaction({ hash }: { hash: string }) {
return (
<TransactionWrapper>
<TransactionState href={getEtherscanLink(chainId, hash, 'transaction')} pending={pending} success={success}>
<TransactionState
href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}
pending={pending}
success={success}
>
<RowFixed>
<TransactionStatusText>{summary ?? hash} </TransactionStatusText>
</RowFixed>

View File

@@ -1,17 +1,15 @@
import React, { useCallback, useContext } from 'react'
import { useDispatch } from 'react-redux'
import styled, { ThemeContext } from 'styled-components'
import { useActiveWeb3React } from '../../hooks'
import { AppDispatch } from '../../state'
import { SUPPORTED_WALLETS } from '../../constants/wallet'
import { useActiveWeb3React } from '../../hooks/web3'
import { clearAllTransactions } from '../../state/transactions/actions'
import { shortenAddress } from '../../utils'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { AutoRow } from '../Row'
import Copy from './Copy'
import Transaction from './Transaction'
import { SUPPORTED_WALLETS } from '../../constants'
import { ReactComponent as Close } from '../../assets/images/x.svg'
import { getEtherscanLink } from '../../utils'
import { injected, walletconnect, walletlink, fortmatic, portis } from '../../connectors'
import CoinbaseWalletIcon from '../../assets/images/coinbaseWalletIcon.svg'
import WalletConnectIcon from '../../assets/images/walletConnectIcon.svg'
@@ -21,6 +19,8 @@ import Identicon from '../Identicon'
import { ButtonSecondary } from '../Button'
import { ExternalLink as LinkIcon } from 'react-feather'
import { ExternalLink, LinkStyledButton, TYPE } from '../../theme'
import { Trans } from '@lingui/macro'
import { useAppDispatch } from 'state/hooks'
const HeaderRow = styled.div`
${({ theme }) => theme.flexRowNoWrap};
@@ -76,7 +76,6 @@ const AccountGroupingRow = styled.div`
`
const AccountSection = styled.div`
background-color: ${({ theme }) => theme.bg1};
padding: 0rem 1rem;
${({ theme }) => theme.mediaWidth.upToMedium`padding: 0rem 1rem 1.5rem 1rem;`};
`
@@ -227,7 +226,7 @@ export default function AccountDetails({
}: AccountDetailsProps) {
const { chainId, account, connector } = useActiveWeb3React()
const theme = useContext(ThemeContext)
const dispatch = useDispatch<AppDispatch>()
const dispatch = useAppDispatch()
function formatConnectorName() {
const { ethereum } = window
@@ -238,7 +237,11 @@ export default function AccountDetails({
SUPPORTED_WALLETS[k].connector === connector && (connector !== injected || isMetaMask === (k === 'METAMASK'))
)
.map((k) => SUPPORTED_WALLETS[k].name)[0]
return <WalletName>Connected with {name}</WalletName>
return (
<WalletName>
<Trans>Connected with {name}</Trans>
</WalletName>
)
}
function getStatusIcon() {
@@ -251,32 +254,32 @@ export default function AccountDetails({
} else if (connector === walletconnect) {
return (
<IconWrapper size={16}>
<img src={WalletConnectIcon} alt={'wallet connect logo'} />
<img src={WalletConnectIcon} alt={'WalletConnect logo'} />
</IconWrapper>
)
} else if (connector === walletlink) {
return (
<IconWrapper size={16}>
<img src={CoinbaseWalletIcon} alt={'coinbase wallet logo'} />
<img src={CoinbaseWalletIcon} alt={'Coinbase Wallet logo'} />
</IconWrapper>
)
} else if (connector === fortmatic) {
return (
<IconWrapper size={16}>
<img src={FortmaticIcon} alt={'fortmatic logo'} />
<img src={FortmaticIcon} alt={'Fortmatic logo'} />
</IconWrapper>
)
} else if (connector === portis) {
return (
<>
<IconWrapper size={16}>
<img src={PortisIcon} alt={'portis logo'} />
<img src={PortisIcon} alt={'Portis logo'} />
<MainWalletAction
onClick={() => {
portis.portis.showPortis()
}}
>
Show Portis
<Trans>Show Portis</Trans>
</MainWalletAction>
</IconWrapper>
</>
@@ -295,7 +298,9 @@ export default function AccountDetails({
<CloseIcon onClick={toggleWalletModal}>
<CloseColor />
</CloseIcon>
<HeaderRow>Account</HeaderRow>
<HeaderRow>
<Trans>Account</Trans>
</HeaderRow>
<AccountSection>
<YourAccount>
<InfoCard>
@@ -309,7 +314,7 @@ export default function AccountDetails({
;(connector as any).close()
}}
>
Disconnect
<Trans>Disconnect</Trans>
</WalletAction>
)}
<WalletAction
@@ -318,7 +323,7 @@ export default function AccountDetails({
openOptions()
}}
>
Change
<Trans>Change</Trans>
</WalletAction>
</div>
</AccountGroupingRow>
@@ -348,17 +353,21 @@ export default function AccountDetails({
<div>
{account && (
<Copy toCopy={account}>
<span style={{ marginLeft: '4px' }}>Copy Address</span>
<span style={{ marginLeft: '4px' }}>
<Trans>Copy Address</Trans>
</span>
</Copy>
)}
{chainId && account && (
<AddressLink
hasENS={!!ENSName}
isENS={true}
href={chainId && getEtherscanLink(chainId, ENSName, 'address')}
href={getExplorerLink(chainId, ENSName, ExplorerDataType.ADDRESS)}
>
<LinkIcon size={16} />
<span style={{ marginLeft: '4px' }}>View on Etherscan</span>
<span style={{ marginLeft: '4px' }}>
<Trans>View on Explorer</Trans>
</span>
</AddressLink>
)}
</div>
@@ -370,17 +379,21 @@ export default function AccountDetails({
<div>
{account && (
<Copy toCopy={account}>
<span style={{ marginLeft: '4px' }}>Copy Address</span>
<span style={{ marginLeft: '4px' }}>
<Trans>Copy Address</Trans>
</span>
</Copy>
)}
{chainId && account && (
<AddressLink
hasENS={!!ENSName}
isENS={false}
href={getEtherscanLink(chainId, account, 'address')}
href={getExplorerLink(chainId, account, ExplorerDataType.ADDRESS)}
>
<LinkIcon size={16} />
<span style={{ marginLeft: '4px' }}>View on Etherscan</span>
<span style={{ marginLeft: '4px' }}>
<Trans>View on Explorer</Trans>
</span>
</AddressLink>
)}
</div>
@@ -395,15 +408,21 @@ export default function AccountDetails({
{!!pendingTransactions.length || !!confirmedTransactions.length ? (
<LowerSection>
<AutoRow mb={'1rem'} style={{ justifyContent: 'space-between' }}>
<TYPE.body>Recent Transactions</TYPE.body>
<LinkStyledButton onClick={clearAllTransactionsCallback}>(clear all)</LinkStyledButton>
<TYPE.body>
<Trans>Recent Transactions</Trans>
</TYPE.body>
<LinkStyledButton onClick={clearAllTransactionsCallback}>
<Trans>(clear all)</Trans>
</LinkStyledButton>
</AutoRow>
{renderTransactions(pendingTransactions)}
{renderTransactions(confirmedTransactions)}
</LowerSection>
) : (
<LowerSection>
<TYPE.body color={theme.text1}>Your transactions will appear here...</TYPE.body>
<TYPE.body color={theme.text1}>
<Trans>Your transactions will appear here...</Trans>
</TYPE.body>
</LowerSection>
)}
</>

View File

@@ -1,11 +1,11 @@
import React, { useContext, useCallback } from 'react'
import styled, { ThemeContext } from 'styled-components'
import useENS from '../../hooks/useENS'
import { useActiveWeb3React } from '../../hooks'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink, TYPE } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { AutoColumn } from '../Column'
import { RowBetween } from '../Row'
import { getEtherscanLink } from '../../utils'
const InputPanel = styled.div`
${({ theme }) => theme.flexColumnNoWrap}
@@ -40,7 +40,7 @@ const Input = styled.input<{ error?: boolean }>`
width: 0;
background-color: ${({ theme }) => theme.bg1};
transition: color 300ms ${({ error }) => (error ? 'step-end' : 'step-start')};
color: ${({ error, theme }) => (error ? theme.red1 : theme.primary1)};
color: ${({ error, theme }) => (error ? theme.red1 : theme.text1)};
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
@@ -67,10 +67,16 @@ const Input = styled.input<{ error?: boolean }>`
export default function AddressInputPanel({
id,
className = 'recipient-address-input',
label = 'Recipient',
placeholder,
value,
onChange,
}: {
id?: string
className?: string
label?: string
placeholder?: string
// the typed string value
value: string
// triggers whenever the typed value changes
@@ -99,22 +105,25 @@ export default function AddressInputPanel({
<AutoColumn gap="md">
<RowBetween>
<TYPE.black color={theme.text2} fontWeight={500} fontSize={14}>
Recipient
{label}
</TYPE.black>
{address && chainId && (
<ExternalLink href={getEtherscanLink(chainId, name ?? address, 'address')} style={{ fontSize: '14px' }}>
(View on Etherscan)
<ExternalLink
href={getExplorerLink(chainId, name ?? address, ExplorerDataType.ADDRESS)}
style={{ fontSize: '14px' }}
>
(View on Explorer)
</ExternalLink>
)}
</RowBetween>
<Input
className="recipient-address-input"
className={className}
type="text"
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
placeholder="Wallet Address or ENS name"
placeholder={placeholder ?? 'Wallet Address or ENS name'}
error={error}
pattern="^(0x[a-fA-F0-9]{40})$"
onChange={handleInput}

View File

@@ -1,44 +0,0 @@
import { Story } from '@storybook/react/types-6-0'
import React, { PropsWithChildren } from 'react'
import Component, { BadgeProps, BadgeVariant } from './index'
export default {
title: 'Badge',
argTypes: {
variant: {
name: 'variant',
type: { name: 'string', require: false },
defaultValue: BadgeVariant.DEFAULT,
description: 'badge variant',
control: {
type: 'select',
options: Object.values(BadgeVariant),
},
},
},
args: {
children: '🦄 UNISWAP 🦄',
},
}
const Template: Story<PropsWithChildren<BadgeProps>> = (args) => <Component {...args}>{args.children}</Component>
export const DefaultBadge = Template.bind({})
DefaultBadge.args = {
variant: BadgeVariant.DEFAULT,
}
export const WarningBadge = Template.bind({})
WarningBadge.args = {
variant: BadgeVariant.WARNING,
}
export const NegativeBadge = Template.bind({})
NegativeBadge.args = {
variant: BadgeVariant.NEGATIVE,
}
export const PositiveBadge = Template.bind({})
PositiveBadge.args = {
variant: BadgeVariant.POSITIVE,
}

View File

@@ -1,10 +1,10 @@
import React from 'react'
import Badge, { BadgeVariant } from 'components/Badge'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { MouseoverTooltip } from '../../components/Tooltip'
import { useTranslation } from 'react-i18next'
import { Trans } from '@lingui/macro'
import { AlertCircle } from 'react-feather'
const BadgeWrapper = styled.div`
@@ -40,35 +40,47 @@ export default function RangeBadge({
removed: boolean | undefined
inRange: boolean | undefined
}) {
const { t } = useTranslation()
return (
<BadgeWrapper>
{removed ? (
<MouseoverTooltip text={`Your position has 0 liquidity, and is not earning fees.`}>
<Badge variant={BadgeVariant.WARNING_OUTLINE}>
<MouseoverTooltip text={<Trans>Your position has 0 liquidity, and is not earning fees.</Trans>}>
<Badge variant={BadgeVariant.DEFAULT}>
<AlertCircle width={14} height={14} />
&nbsp;
<BadgeText>{t('Inactive')}</BadgeText>
<BadgeText>
<Trans>Closed</Trans>
</BadgeText>
</Badge>
</MouseoverTooltip>
) : inRange ? (
<MouseoverTooltip
text={`The price of this pool is within your selected range. Your position is currently earning fees.`}
text={
<Trans>
The price of this pool is within your selected range. Your position is currently earning fees.
</Trans>
}
>
<Badge variant={BadgeVariant.DEFAULT}>
<ActiveDot /> &nbsp;
<BadgeText>{t('In range')}</BadgeText>
<BadgeText>
<Trans>In range</Trans>
</BadgeText>
</Badge>
</MouseoverTooltip>
) : (
<MouseoverTooltip
text={`The price of this pool is outside of your selected range. Your position is not currently earning fees.`}
text={
<Trans>
The price of this pool is outside of your selected range. Your position is not currently earning fees.
</Trans>
}
>
<Badge variant={BadgeVariant.WARNING}>
<AlertCircle width={14} height={14} />
&nbsp;
<BadgeText>{t('Out of range')}</BadgeText>
<BadgeText>
<Trans>Out of range</Trans>
</BadgeText>
</Badge>
</MouseoverTooltip>
)}

View File

@@ -1,12 +1,25 @@
import React, { ReactNode, useMemo } from 'react'
import { BLOCKED_ADDRESSES } from '../../constants'
import { useActiveWeb3React } from '../../hooks'
import { useActiveWeb3React } from '../../hooks/web3'
import { Trans } from '@lingui/macro'
// SDN OFAC addresses
const BLOCKED_ADDRESSES: string[] = [
'0x7F367cC41522cE07553e823bf3be79A889DEbe1B',
'0xd882cFc20F52f2599D84b8e8D58C7FB62cfE344b',
'0x901bb9583b24D97e995513C6778dc6888AB6870e',
'0xA7e5d5A720f06526557c513402f2e6B5fA20b008',
'0x8576aCC5C05D6Ce88f4e49bf65BdF0C62F91353C',
]
export default function Blocklist({ children }: { children: ReactNode }) {
const { account } = useActiveWeb3React()
const blocked: boolean = useMemo(() => Boolean(account && BLOCKED_ADDRESSES.indexOf(account) !== -1), [account])
if (blocked) {
return <div>Blocked address</div>
return (
<div>
<Trans>Blocked address</Trans>
</div>
)
}
return <>{children}</>
}

View File

@@ -1,153 +0,0 @@
import { Story } from '@storybook/react/types-6-0'
import styled from 'styled-components'
import React from 'react'
import {
ButtonConfirmed,
ButtonDropdown,
ButtonDropdownGrey,
ButtonDropdownLight,
ButtonEmpty,
ButtonError,
ButtonGray,
ButtonLight,
ButtonOutlined,
ButtonPink,
ButtonPrimary,
ButtonRadio,
ButtonSecondary,
ButtonUNIGradient,
ButtonWhite,
} from './index'
const wrapperCss = styled.main`
font-size: 2em;
margin: 3em;
max-width: 300px;
`
export default {
title: 'Buttons',
argTypes: {
disabled: { control: { type: 'boolean' } },
onClick: { action: 'clicked' },
},
decorators: [
(Component: Story) => (
<div css={wrapperCss}>
<Component />
</div>
),
],
}
const Unicorn = () => (
<span role="img" aria-label="unicorn">
🦄
</span>
)
export const Radio = () => (
<ButtonRadio>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonRadio>
)
export const DropdownLight = () => (
<ButtonDropdownLight>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonDropdownLight>
)
export const DropdownGrey = () => (
<ButtonDropdownGrey>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonDropdownGrey>
)
export const Dropdown = () => (
<ButtonDropdown>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonDropdown>
)
export const Error = () => (
<ButtonError>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonError>
)
export const Confirmed = () => (
<ButtonConfirmed>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonConfirmed>
)
export const White = () => (
<ButtonWhite>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonWhite>
)
export const Empty = () => (
<ButtonEmpty>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonEmpty>
)
export const Outlined = () => (
<ButtonOutlined>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonOutlined>
)
export const UNIGradient = () => (
<ButtonUNIGradient>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonUNIGradient>
)
export const Pink = () => (
<ButtonPink>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonPink>
)
export const Secondary = () => (
<ButtonSecondary>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonSecondary>
)
export const Gray = () => (
<ButtonGray>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonGray>
)
export const Light = () => (
<ButtonLight>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonLight>
)
export const Primary = () => (
<ButtonPrimary>
<Unicorn />
&nbsp;UNISWAP&nbsp;
<Unicorn />
</ButtonPrimary>
)

View File

@@ -1,18 +1,22 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { darken } from 'polished'
import { RowBetween } from '../Row'
import { ChevronDown, Check } from 'react-feather'
import { Button as RebassButton, ButtonProps } from 'rebass/styled-components'
import { Button as RebassButton, ButtonProps as ButtonPropsOriginal } from 'rebass/styled-components'
import useTheme from 'hooks/useTheme'
const Base = styled(RebassButton)<{
padding?: string
width?: string
borderRadius?: string
altDisabledStyle?: boolean
}>`
type ButtonProps = Omit<ButtonPropsOriginal, 'css'>
const Base = styled(RebassButton)<
{
padding?: string
width?: string
borderRadius?: string
altDisabledStyle?: boolean
} & ButtonProps
>`
padding: ${({ padding }) => (padding ? padding : '16px')};
width: ${({ width }) => (width ? width : '100%')};
font-weight: 500;
@@ -68,14 +72,12 @@ export const ButtonPrimary = styled(Base)`
}
&:disabled {
background-color: ${({ theme, altDisabledStyle, disabled }) =>
altDisabledStyle ? (disabled ? theme.primary1 : theme.primary1) : theme.primary1};
color: white;
altDisabledStyle ? (disabled ? theme.primary1 : theme.bg2) : theme.bg2};
color: ${({ theme }) => theme.text2};
cursor: auto;
box-shadow: none;
border: 1px solid transparent;
outline: none;
opacity: 0.4;
opacity: ${({ altDisabledStyle }) => (altDisabledStyle ? '0.5' : '0.4')};
}
`

View File

@@ -1,4 +1,4 @@
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { Box } from 'rebass/styled-components'
const Card = styled(Box)<{ width?: string; padding?: string; border?: string; borderRadius?: string }>`

View File

@@ -1,4 +1,4 @@
import styled from 'styled-components'
import styled from 'styled-components/macro'
const Column = styled.div`
display: flex;

View File

@@ -1,14 +1,16 @@
import { CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import React, { useMemo } from 'react'
import useTheme from '../../hooks/useTheme'
import { TYPE } from '../../theme'
import { warningSeverity } from '../../utils/prices'
import HoverInlineText from 'components/HoverInlineText'
import { Trans } from '@lingui/macro'
export function FiatValue({
fiatValue,
priceImpact,
}: {
fiatValue: CurrencyAmount | null | undefined
fiatValue: CurrencyAmount<Currency> | null | undefined
priceImpact?: Percent
}) {
const theme = useTheme()
@@ -16,16 +18,25 @@ export function FiatValue({
if (!priceImpact) return undefined
if (priceImpact.lessThan('0')) return theme.green1
const severity = warningSeverity(priceImpact)
if (severity < 1) return theme.text4
if (severity < 1) return theme.text3
if (severity < 3) return theme.yellow1
return theme.red1
}, [priceImpact, theme.green1, theme.red1, theme.text4, theme.yellow1])
}, [priceImpact, theme.green1, theme.red1, theme.text3, theme.yellow1])
return (
<TYPE.body fontSize={14} color={fiatValue ? theme.text2 : theme.text4}>
{fiatValue ? '~' : ''}${fiatValue ? Number(fiatValue?.toSignificant(6)).toLocaleString('en') : '-'}
{fiatValue ? (
<Trans>
~$ <HoverInlineText text={fiatValue?.toSignificant(6, { groupSeparator: ',' })} />
</Trans>
) : (
''
)}
{priceImpact ? (
<span style={{ color: priceImpactColor }}> ({priceImpact.multiply(-100).toSignificant(3)}%)</span>
<span style={{ color: priceImpactColor }}>
{' '}
(<Trans>{priceImpact.multiply(-1).toSignificant(3)}%</Trans>)
</span>
) : null}
</TYPE.body>
)

View File

@@ -1,7 +1,7 @@
import { Pair } from '@uniswap/v2-sdk'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import React, { useState, useCallback } from 'react'
import styled from 'styled-components'
import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import React, { useState, useCallback, ReactNode } from 'react'
import styled from 'styled-components/macro'
import { darken } from 'polished'
import { useCurrencyBalance } from '../../state/wallet/hooks'
import CurrencySearchModal from '../SearchModal/CurrencySearchModal'
@@ -12,12 +12,13 @@ import { RowBetween, RowFixed } from '../Row'
import { TYPE } from '../../theme'
import { Input as NumericalInput } from '../NumericalInput'
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import { useActiveWeb3React } from '../../hooks'
import { useTranslation } from 'react-i18next'
import { useActiveWeb3React } from '../../hooks/web3'
import { Trans } from '@lingui/macro'
import useTheme from '../../hooks/useTheme'
import { Lock } from 'react-feather'
import { AutoColumn } from 'components/Column'
import { FiatValue } from './FiatValue'
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
const InputPanel = styled.div<{ hideInput?: boolean }>`
${({ theme }) => theme.flexColumnNoWrap}
@@ -129,16 +130,12 @@ const StyledBalanceMax = styled.button<{ disabled?: boolean }>`
font-weight: 500;
cursor: pointer;
padding: 0;
color: ${({ theme }) => theme.primary1};
color: ${({ theme }) => theme.primaryText1};
opacity: ${({ disabled }) => (!disabled ? 1 : 0.4)};
pointer-events: ${({ disabled }) => (!disabled ? 'initial' : 'none')};
margin-left: 0.25rem;
:hover {
/* border: 1px solid ${({ theme }) => theme.primary1}; */
}
:focus {
/* border: 1px solid ${({ theme }) => theme.primary1}; */
outline: none;
}
@@ -152,18 +149,20 @@ interface CurrencyInputPanelProps {
onUserInput: (value: string) => void
onMax?: () => void
showMaxButton: boolean
label?: string
label?: ReactNode
onCurrencySelect?: (currency: Currency) => void
currency?: Currency | null
hideBalance?: boolean
pair?: Pair | null
hideInput?: boolean
otherCurrency?: Currency | null
fiatValue?: CurrencyAmount | null
fiatValue?: CurrencyAmount<Token> | null
priceImpact?: Percent
id: string
showCommonBases?: boolean
customBalanceText?: string
showCurrencyAmount?: boolean
disableNonToken?: boolean
renderBalance?: (amount: CurrencyAmount<Currency>) => ReactNode
locked?: boolean
}
@@ -177,7 +176,9 @@ export default function CurrencyInputPanel({
otherCurrency,
id,
showCommonBases,
customBalanceText,
showCurrencyAmount,
disableNonToken,
renderBalance,
fiatValue,
priceImpact,
hideBalance = false,
@@ -186,8 +187,6 @@ export default function CurrencyInputPanel({
locked = false,
...rest
}: CurrencyInputPanelProps) {
const { t } = useTranslation()
const [modalOpen, setModalOpen] = useState(false)
const { account } = useActiveWeb3React()
const selectedCurrencyBalance = useCurrencyBalance(account ?? undefined, currency ?? undefined)
@@ -203,8 +202,8 @@ export default function CurrencyInputPanel({
<FixedContainer>
<AutoColumn gap="sm" justify="center">
<Lock />
<TYPE.label fontSize="12px" textAlign="center">
The market price is outside your specified price range. Single-asset deposit only.
<TYPE.label fontSize="12px" textAlign="center" padding="0 12px">
<Trans>The market price is outside your specified price range. Single-asset deposit only.</Trans>
</TYPE.label>
</AutoColumn>
</FixedContainer>
@@ -240,7 +239,7 @@ export default function CurrencyInputPanel({
? currency.symbol.slice(0, 4) +
'...' +
currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length)
: currency?.symbol) || t('selectToken')}
: currency?.symbol) || <Trans>Select a token</Trans>}
</StyledTokenName>
)}
</RowFixed>
@@ -271,21 +270,25 @@ export default function CurrencyInputPanel({
fontSize={14}
style={{ display: 'inline', cursor: 'pointer' }}
>
{!hideBalance && !!currency && selectedCurrencyBalance
? (customBalanceText ?? 'Balance: ') +
selectedCurrencyBalance?.toSignificant(4) +
' ' +
currency.symbol
: '-'}
{!hideBalance && currency && selectedCurrencyBalance ? (
renderBalance ? (
renderBalance(selectedCurrencyBalance)
) : (
<Trans>
Balance: {formatCurrencyAmount(selectedCurrencyBalance, 4)} {currency.symbol}
</Trans>
)
) : null}
</TYPE.body>
{showMaxButton && selectedCurrencyBalance ? (
<StyledBalanceMax onClick={onMax}>(Max)</StyledBalanceMax>
<StyledBalanceMax onClick={onMax}>
<Trans>(Max)</Trans>
</StyledBalanceMax>
) : null}
</RowFixed>
) : (
'-'
<span />
)}
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
</RowBetween>
</FiatRow>
@@ -299,6 +302,8 @@ export default function CurrencyInputPanel({
selectedCurrency={currency}
otherSelectedCurrency={otherCurrency}
showCommonBases={showCommonBases}
showCurrencyAmount={showCurrencyAmount}
disableNonToken={disableNonToken}
/>
)}
</InputPanel>

View File

@@ -1,9 +1,9 @@
import { ChainId, Currency, ETHER, Token } from '@uniswap/sdk-core'
import { Currency } from '@uniswap/sdk-core'
import React, { useMemo } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import EthereumLogo from '../../assets/images/ethereum-logo.png'
import useHttpLocations from '../../hooks/useHttpLocations'
import { WrappedTokenInfo } from '../../state/lists/hooks'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
import Logo from '../Logo'
export const getTokenLogoURL = (address: string) =>
@@ -37,10 +37,10 @@ export default function CurrencyLogo({
const uriLocations = useHttpLocations(currency instanceof WrappedTokenInfo ? currency.logoURI : undefined)
const srcs: string[] = useMemo(() => {
if (currency === ETHER) return []
if (!currency || currency.isNative) return []
if (currency instanceof Token) {
const defaultUrls = currency.chainId === ChainId.MAINNET ? [getTokenLogoURL(currency.address)] : []
if (currency.isToken) {
const defaultUrls = currency.chainId === 1 ? [getTokenLogoURL(currency.address)] : []
if (currency instanceof WrappedTokenInfo) {
return [...uriLocations, ...defaultUrls]
}
@@ -49,7 +49,7 @@ export default function CurrencyLogo({
return []
}, [currency, uriLocations])
if (currency === ETHER) {
if (currency?.isNative) {
return <StyledEthereumLogo src={EthereumLogo} size={size} style={style} {...rest} />
}

View File

@@ -1,18 +0,0 @@
import { Story } from '@storybook/react/types-6-0'
import React from 'react'
import { DAI, WBTC } from '../../constants'
import Component, { DoubleCurrencyLogoProps } from './index'
export default {
title: 'DoubleCurrencyLogo',
decorators: [],
}
const Template: Story<DoubleCurrencyLogoProps> = (args) => <Component {...args} />
export const DoubleCurrencyLogo = Template.bind({})
DoubleCurrencyLogo.args = {
currency0: DAI,
currency1: WBTC,
size: 220,
}

View File

@@ -1,6 +1,6 @@
import { Currency } from '@uniswap/sdk-core'
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import CurrencyLogo from '../CurrencyLogo'
const Wrapper = styled.div<{ margin: boolean; sizeraw: number }>`

View File

@@ -0,0 +1,182 @@
import { Trans } from '@lingui/macro'
import React, { ErrorInfo } from 'react'
import store, { AppState } from '../../state'
import { ExternalLink, TYPE } from '../../theme'
import { AutoColumn } from '../Column'
import styled from 'styled-components/macro'
import ReactGA from 'react-ga'
import { getUserAgent } from '../../utils/getUserAgent'
import { AutoRow } from '../Row'
const FallbackWrapper = styled.div`
display: flex;
flex-direction: column;
width: 100%;
align-items: center;
z-index: 1;
`
const BodyWrapper = styled.div<{ margin?: string }>`
padding: 1rem;
width: 100%;
white-space: ;
`
const CodeBlockWrapper = styled.div`
background: ${({ theme }) => theme.bg0};
overflow: auto;
white-space: pre;
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
0px 24px 32px rgba(0, 0, 0, 0.01);
border-radius: 24px;
padding: 18px 24px;
color: ${({ theme }) => theme.text1};
`
const LinkWrapper = styled.div`
color: ${({ theme }) => theme.blue1};
padding: 6px 24px;
`
const SomethingWentWrongWrapper = styled.div`
padding: 6px 24px;
`
type ErrorBoundaryState = {
error: Error | null
}
export default class ErrorBoundary extends React.Component<unknown, ErrorBoundaryState> {
constructor(props: unknown) {
super(props)
this.state = { error: null }
}
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
return { error }
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
ReactGA.exception({
...error,
...errorInfo,
fatal: true,
})
}
render() {
const { error } = this.state
if (error !== null) {
const encodedBody = encodeURIComponent(issueBody(error))
return (
<FallbackWrapper>
<BodyWrapper>
<AutoColumn gap={'md'}>
<SomethingWentWrongWrapper>
<TYPE.label fontSize={24} fontWeight={600}>
<Trans>Something went wrong</Trans>
</TYPE.label>
</SomethingWentWrongWrapper>
<CodeBlockWrapper>
<code>
<TYPE.main fontSize={10}>{error.stack}</TYPE.main>
</code>
</CodeBlockWrapper>
<AutoRow>
<LinkWrapper>
<ExternalLink
id="create-github-issue-link"
href={`https://github.com/Uniswap/uniswap-interface/issues/new?assignees=&labels=bug&body=${encodedBody}&title=${encodeURIComponent(
`Crash report: \`${error.name}${error.message && `: ${error.message}`}\``
)}`}
target="_blank"
>
<TYPE.link fontSize={16}>
<Trans>Create an issue on GitHub</Trans>
<span></span>
</TYPE.link>
</ExternalLink>
</LinkWrapper>
<LinkWrapper>
<ExternalLink id="get-support-on-discord" href="https://discord.gg/FCfyBSbCU5" target="_blank">
<TYPE.link fontSize={16}>
<Trans>Get support on Discord</Trans>
<span></span>
</TYPE.link>
</ExternalLink>
</LinkWrapper>
</AutoRow>
</AutoColumn>
</BodyWrapper>
</FallbackWrapper>
)
}
return this.props.children
}
}
function getRelevantState(): null | keyof AppState {
const path = window.location.hash
if (!path.startsWith('#/')) {
return null
}
const pieces = path.substring(2).split(/[\/\\?]/)
switch (pieces[0]) {
case 'swap':
return 'swap'
case 'add':
if (pieces[1] === 'v2') return 'mint'
else return 'mintV3'
case 'remove':
if (pieces[1] === 'v2') return 'burn'
else return 'burnV3'
}
return null
}
function issueBody(error: Error): string {
const relevantState = getRelevantState()
const deviceData = getUserAgent()
return `## URL
${window.location.href}
${
relevantState
? `## \`${relevantState}\` state
\`\`\`json
${JSON.stringify(store.getState()[relevantState], null, 2)}
\`\`\`
`
: ''
}
${
error.name &&
`## Error
\`\`\`
${error.name}${error.message && `: ${error.message}`}
\`\`\`
`
}
${
error.stack &&
`## Stacktrace
\`\`\`
${error.stack}
\`\`\`
`
}
${
deviceData &&
`## Device data
\`\`\`json
${JSON.stringify(deviceData, null, 2)}
\`\`\`
`
}
`
}

View File

@@ -1,12 +1,12 @@
import React from 'react'
import { FeeAmount } from '@uniswap/v3-sdk'
import { useTranslation } from 'react-i18next'
import { Trans } from '@lingui/macro'
import { AutoColumn } from 'components/Column'
import { DynamicSection } from 'pages/AddLiquidity/styled'
import { TYPE } from 'theme'
import { RowBetween } from 'components/Row'
import { ButtonRadioChecked } from 'components/Button'
import styled from 'styled-components'
import styled from 'styled-components/macro'
const ResponsiveText = styled(TYPE.label)`
${({ theme }) => theme.mediaWidth.upToSmall`
@@ -23,14 +23,14 @@ export default function FeeSelector({
feeAmount?: FeeAmount
handleFeePoolSelect: (feeAmount: FeeAmount) => void
}) {
const { t } = useTranslation()
return (
<AutoColumn gap="16px">
<DynamicSection gap="md" disabled={disabled}>
<TYPE.label>{t('selectPool')}</TYPE.label>
<TYPE.label>
<Trans>Select Pool</Trans>
</TYPE.label>
<TYPE.main fontSize={14} fontWeight={400} style={{ marginBottom: '.5rem', lineHeight: '125%' }}>
Select a pool type based on your preferred liquidity provider fee.
<Trans>Select a pool type based on your preferred liquidity provider fee.</Trans>
</TYPE.main>
<RowBetween>
<ButtonRadioChecked
@@ -39,9 +39,11 @@ export default function FeeSelector({
onClick={() => handleFeePoolSelect(FeeAmount.LOW)}
>
<AutoColumn gap="sm" justify="flex-start">
<ResponsiveText>0.05% {t('fee')}</ResponsiveText>
<ResponsiveText>
<Trans>0.05% fee</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
Best for stable pairs.
<Trans>Best for stable pairs.</Trans>
</TYPE.main>
</AutoColumn>
</ButtonRadioChecked>
@@ -51,9 +53,11 @@ export default function FeeSelector({
onClick={() => handleFeePoolSelect(FeeAmount.MEDIUM)}
>
<AutoColumn gap="sm" justify="flex-start">
<ResponsiveText>0.3% {t('fee')}</ResponsiveText>
<ResponsiveText>
<Trans>0.3% fee</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
Best for most pairs.
<Trans>Best for most pairs.</Trans>
</TYPE.main>
</AutoColumn>
</ButtonRadioChecked>
@@ -63,9 +67,11 @@ export default function FeeSelector({
onClick={() => handleFeePoolSelect(FeeAmount.HIGH)}
>
<AutoColumn gap="sm" justify="flex-start">
<ResponsiveText>1% {t('fee')}</ResponsiveText>
<ResponsiveText>
<Trans>1% fee</Trans>
</ResponsiveText>
<TYPE.main fontWeight={400} fontSize="12px" textAlign="left">
Best for exotic pairs.
<Trans>Best for exotic pairs.</Trans>
</TYPE.main>
</AutoColumn>
</ButtonRadioChecked>

View File

@@ -1,6 +1,6 @@
import JSBI from 'jsbi'
import React from 'react'
import { CurrencyAmount, Fraction } from '@uniswap/sdk-core'
import { JSBI } from '@uniswap/v2-sdk'
import { Currency, CurrencyAmount, Fraction } from '@uniswap/sdk-core'
const CURRENCY_AMOUNT_MIN = new Fraction(JSBI.BigInt(1), JSBI.BigInt(1000000))
@@ -8,7 +8,7 @@ export default function FormattedCurrencyAmount({
currencyAmount,
significantDigits = 4,
}: {
currencyAmount: CurrencyAmount
currencyAmount: CurrencyAmount<Currency>
significantDigits?: number
}) {
return (

View File

@@ -1,10 +1,10 @@
import React, { useState, useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import styled, { keyframes } from 'styled-components'
import { TYPE, ExternalLink } from '../../theme'
import { useActiveWeb3React } from '../../hooks/web3'
import { useBlockNumber } from '../../state/application/hooks'
import { getEtherscanLink } from '../../utils'
import { useActiveWeb3React } from '../../hooks'
import { ExternalLink, TYPE } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
const StyledPolling = styled.div`
position: fixed;
@@ -21,7 +21,7 @@ const StyledPolling = styled.div`
`
const StyledPollingNumber = styled(TYPE.small)<{ breathe: boolean; hovering: boolean }>`
transition: opacity 0.25s ease;
opacity: ${({ breathe, hovering }) => (hovering ? 0.7 : breathe ? 1 : 0.2)};
opacity: ${({ breathe, hovering }) => (hovering ? 0.7 : breathe ? 1 : 0.5)};
:hover {
opacity: 1;
}
@@ -91,7 +91,9 @@ export default function Polling() {
)
return (
<ExternalLink href={chainId && blockNumber ? getEtherscanLink(chainId, blockNumber.toString(), 'block') : ''}>
<ExternalLink
href={chainId && blockNumber ? getExplorerLink(chainId, blockNumber.toString(), ExplorerDataType.BLOCK) : ''}
>
<StyledPolling onMouseEnter={() => setIsHover(true)} onMouseLeave={() => setIsHover(false)}>
<StyledPollingNumber breathe={isMounting} hovering={isHover}>
{blockNumber}

View File

@@ -1,9 +1,10 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { AlertTriangle, X } from 'react-feather'
import { useURLWarningToggle, useURLWarningVisible } from '../../state/user/hooks'
import { isMobile } from 'react-device-detect'
import { Trans } from '@lingui/macro'
const PhishAlert = styled.div<{ isActive: any }>`
width: 100%;
@@ -29,17 +30,23 @@ export default function URLWarning() {
return isMobile ? (
<PhishAlert isActive={showURLWarning}>
<div style={{ display: 'flex' }}>
<AlertTriangle style={{ marginRight: 6 }} size={12} /> Make sure the URL is
<code style={{ padding: '0 4px', display: 'inline', fontWeight: 'bold' }}>app.uniswap.org</code>
<AlertTriangle style={{ marginRight: 6 }} size={12} />
<Trans>
Make sure the URL is
<code style={{ padding: '0 4px', display: 'inline', fontWeight: 'bold' }}>app.uniswap.org</code>
</Trans>
</div>
<StyledClose size={12} onClick={toggleURLWarning} />
</PhishAlert>
) : window.location.hostname === 'app.uniswap.org' ? (
<PhishAlert isActive={showURLWarning}>
<div style={{ display: 'flex' }}>
<AlertTriangle style={{ marginRight: 6 }} size={12} /> Always make sure the URL is
<code style={{ padding: '0 4px', display: 'inline', fontWeight: 'bold' }}>app.uniswap.org</code> - bookmark it
to be safe.
<AlertTriangle style={{ marginRight: 6 }} size={12} />
<Trans>
Always make sure the URL is
<code style={{ padding: '0 4px', display: 'inline', fontWeight: 'bold' }}>app.uniswap.org</code> - bookmark it
to be safe.
</Trans>
</div>
<StyledClose size={12} onClick={toggleURLWarning} />
</PhishAlert>

View File

@@ -1,11 +1,11 @@
import { ChainId, TokenAmount } from '@uniswap/sdk-core'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import React, { useMemo } from 'react'
import { X } from 'react-feather'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import tokenLogo from '../../assets/images/token-logo.png'
import { UNI } from '../../constants'
import { UNI } from '../../constants/tokens'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useActiveWeb3React } from '../../hooks'
import { useActiveWeb3React } from '../../hooks/web3'
import { useMerkleDistributorContract } from '../../hooks/useContract'
import useCurrentBlockTimestamp from '../../hooks/useCurrentBlockTimestamp'
import { useTotalUniEarned } from '../../state/stake/hooks'
@@ -16,6 +16,7 @@ import useUSDCPrice from '../../hooks/useUSDCPrice'
import { AutoColumn } from '../Column'
import { RowBetween } from '../Row'
import { Break, CardBGImage, CardNoise, CardSection, DataCard } from '../earn/styled'
import { Trans } from '@lingui/macro'
const ContentWrapper = styled(AutoColumn)`
width: 100%;
@@ -45,18 +46,16 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
const uni = chainId ? UNI[chainId] : undefined
const total = useAggregateUniBalance()
const uniBalance: TokenAmount | undefined = useTokenBalance(account ?? undefined, uni)
const uniToClaim: TokenAmount | undefined = useTotalUniEarned()
const uniBalance: CurrencyAmount<Token> | undefined = useTokenBalance(account ?? undefined, uni)
const uniToClaim: CurrencyAmount<Token> | undefined = useTotalUniEarned()
const totalSupply: TokenAmount | undefined = useTotalSupply(uni)
const totalSupply: CurrencyAmount<Token> | undefined = useTotalSupply(uni)
const uniPrice = useUSDCPrice(uni)
const blockTimestamp = useCurrentBlockTimestamp()
const unclaimedUni = useTokenBalance(useMerkleDistributorContract()?.address, uni)
const circulation: TokenAmount | undefined = useMemo(
const circulation: CurrencyAmount<Token> | undefined = useMemo(
() =>
blockTimestamp && uni && chainId === ChainId.MAINNET
? computeUniCirculation(uni, blockTimestamp, unclaimedUni)
: totalSupply,
blockTimestamp && uni && chainId === 1 ? computeUniCirculation(uni, blockTimestamp, unclaimedUni) : totalSupply,
[blockTimestamp, chainId, totalSupply, unclaimedUni, uni]
)
@@ -67,7 +66,9 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
<CardNoise />
<CardSection gap="md">
<RowBetween>
<TYPE.white color="white">Your UNI Breakdown</TYPE.white>
<TYPE.white color="white">
<Trans>Your UNI Breakdown</Trans>
</TYPE.white>
<StyledClose stroke="white" onClick={() => setShowUniBalanceModal(false)} />
</RowBetween>
</CardSection>
@@ -83,16 +84,20 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
</AutoColumn>
<AutoColumn gap="md">
<RowBetween>
<TYPE.white color="white">Balance:</TYPE.white>
<TYPE.white color="white">
<Trans>Balance:</Trans>
</TYPE.white>
<TYPE.white color="white">{uniBalance?.toFixed(2, { groupSeparator: ',' })}</TYPE.white>
</RowBetween>
<RowBetween>
<TYPE.white color="white">Unclaimed:</TYPE.white>
<TYPE.white color="white">
<Trans>Unclaimed:</Trans>
</TYPE.white>
<TYPE.white color="white">
{uniToClaim?.toFixed(4, { groupSeparator: ',' })}{' '}
{uniToClaim && uniToClaim.greaterThan('0') && (
<StyledInternalLink onClick={() => setShowUniBalanceModal(false)} to="/uni">
(claim)
<Trans>(claim)</Trans>
</StyledInternalLink>
)}
</TYPE.white>
@@ -105,19 +110,27 @@ export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowU
<CardSection gap="sm">
<AutoColumn gap="md">
<RowBetween>
<TYPE.white color="white">UNI price:</TYPE.white>
<TYPE.white color="white">
<Trans>UNI price:</Trans>
</TYPE.white>
<TYPE.white color="white">${uniPrice?.toFixed(2) ?? '-'}</TYPE.white>
</RowBetween>
<RowBetween>
<TYPE.white color="white">UNI in circulation:</TYPE.white>
<TYPE.white color="white">
<Trans>UNI in circulation:</Trans>
</TYPE.white>
<TYPE.white color="white">{circulation?.toFixed(0, { groupSeparator: ',' })}</TYPE.white>
</RowBetween>
<RowBetween>
<TYPE.white color="white">Total Supply</TYPE.white>
<TYPE.white color="white">
<Trans>Total Supply</Trans>
</TYPE.white>
<TYPE.white color="white">{totalSupply?.toFixed(0, { groupSeparator: ',' })}</TYPE.white>
</RowBetween>
{uni && uni.chainId === ChainId.MAINNET ? (
<ExternalLink href={`https://info.uniswap.org/token/${uni.address}`}>View UNI Analytics</ExternalLink>
{uni && uni.chainId === 1 ? (
<ExternalLink href={`https://info.uniswap.org/token/${uni.address}`}>
<Trans>View UNI Analytics</Trans>
</ExternalLink>
) : null}
</AutoColumn>
</CardSection>

View File

@@ -1,35 +1,32 @@
import { ChainId } from '@uniswap/sdk-core'
import React, { useState } from 'react'
import { Text } from 'rebass'
import { NavLink } from 'react-router-dom'
import { Trans } from '@lingui/macro'
import useScrollPosition from '@react-hook/window-scroll'
import { darken } from 'polished'
import { useTranslation } from 'react-i18next'
import React, { useState } from 'react'
import { Moon, Sun } from 'react-feather'
import styled from 'styled-components'
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 styled from 'styled-components/macro'
import Logo from '../../assets/svg/logo.svg'
import LogoDark from '../../assets/svg/logo_white.svg'
import { useActiveWeb3React } from '../../hooks'
import { useDarkModeManager } from '../../state/user/hooks'
import { useETHBalances } from '../../state/wallet/hooks'
import { CardNoise } from '../earn/styled'
import { TYPE, ExternalLink } from '../../theme'
import { NETWORK_LABELS, SupportedChainId } from '../../constants/chains'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink, TYPE } from '../../theme'
import { YellowCard } from '../Card'
import Menu from '../Menu'
import Row, { RowFixed } from '../Row'
import Web3Status from '../Web3Status'
import ClaimModal from '../claim/ClaimModal'
import { useToggleSelfClaimModal, useShowClaimPopup } from '../../state/application/hooks'
import { useUserHasAvailableClaim } from '../../state/claim/hooks'
import { useUserHasSubmittedClaim } from '../../state/transactions/hooks'
import { Dots } from '../swap/styleds'
import { CardNoise } from '../earn/styled'
import Menu from '../Menu'
import Modal from '../Modal'
import Row, { RowFixed } from '../Row'
import { Dots } from '../swap/styleds'
import Web3Status from '../Web3Status'
import UniBalanceContent from './UniBalanceContent'
const HeaderFrame = styled.div`
const HeaderFrame = styled.div<{ showBackground: boolean }>`
display: grid;
grid-template-columns: 120px 1fr 120px;
align-items: center;
@@ -39,16 +36,20 @@ const HeaderFrame = styled.div`
width: 100%;
top: 0;
position: relative;
/* border-bottom: 1px solid ${({ theme }) => theme.bg2}; */
padding: 1rem;
z-index: 21;
/* background-color: ${({ theme }) => theme.bg1}; */
position: relative;
/* Background slide effect on scroll. */
background-image: ${({ theme }) => `linear-gradient(to bottom, transparent 50%, ${theme.bg0} 50% )}}`}
background-position: ${({ showBackground }) => (showBackground ? '0 -100%' : '0 0')};
background-size: 100% 200%;
box-shadow: 0px 0px 0px 1px ${({ theme, showBackground }) => (showBackground ? theme.bg2 : 'transparent;')};
transition: background-position .1s, box-shadow .1s;
${({ theme }) => theme.mediaWidth.upToMedium`
padding: 1rem;
grid-template-columns: 120px 1fr;
grid-template-columns: auto 1fr;
`};
${({ theme }) => theme.mediaWidth.upToExtraSmall`
@@ -90,7 +91,7 @@ const HeaderElement = styled.div`
}
${({ theme }) => theme.mediaWidth.upToMedium`
flex-direction: row-reverse;
flex-direction: row-reverse;
align-items: center;
`};
`
@@ -116,6 +117,9 @@ const HeaderLinks = styled(Row)`
grid-auto-flow: column;
grid-gap: 10px;
overflow: auto;
${({ theme }) => theme.mediaWidth.upToMedium`
justify-self: flex-end;
`};
`
const AccountElement = styled.div<{ active: boolean }>`
@@ -218,6 +222,7 @@ const StyledNavLink = styled(NavLink).attrs({
width: fit-content;
font-weight: 500;
padding: 8px 12px;
word-break: break-word;
&.${activeClassName} {
border-radius: 12px;
@@ -256,6 +261,7 @@ const StyledExternalLink = styled(ExternalLink).attrs({
:hover,
:focus {
color: ${({ theme }) => darken(0.1, theme.text1)};
text-decoration: none;
}
${({ theme }) => theme.mediaWidth.upToExtraSmall`
@@ -292,16 +298,8 @@ export const StyledMenuButton = styled.button`
}
`
const NETWORK_LABELS: { [chainId in ChainId]?: string } = {
[ChainId.RINKEBY]: 'Rinkeby',
[ChainId.ROPSTEN]: 'Ropsten',
[ChainId.GÖRLI]: 'Görli',
[ChainId.KOVAN]: 'Kovan',
}
export default function Header() {
const { account, chainId } = useActiveWeb3React()
const { t } = useTranslation()
const userEthBalance = useETHBalances(account ? [account] : [])?.[account ?? '']
// const [isDark] = useDarkModeManager()
@@ -316,8 +314,10 @@ export default function Header() {
const [showUniBalanceModal, setShowUniBalanceModal] = useState(false)
const showClaimPopup = useShowClaimPopup()
const scrollY = useScrollPosition()
return (
<HeaderFrame>
<HeaderFrame showBackground={scrollY > 45}>
<ClaimModal />
<Modal isOpen={showUniBalanceModal} onDismiss={() => setShowUniBalanceModal(false)}>
<UniBalanceContent setShowUniBalanceModal={setShowUniBalanceModal} />
@@ -331,7 +331,7 @@ export default function Header() {
</HeaderRow>
<HeaderLinks>
<StyledNavLink id={`swap-nav-link`} to={'/swap'}>
{t('swap')}
<Trans>Swap</Trans>
</StyledNavLink>
<StyledNavLink
id={`pool-nav-link`}
@@ -344,19 +344,20 @@ export default function Header() {
pathname.startsWith('/find')
}
>
{t('pool')}
<Trans>Pool</Trans>
</StyledNavLink>
<StyledNavLink id={`stake-nav-link`} to={'/vote'}>
Vote
<Trans>Vote</Trans>
</StyledNavLink>
<StyledExternalLink id={`stake-nav-link`} href={'https://info.uniswap.org'}>
Charts <span style={{ fontSize: '11px', textDecoration: 'none !important' }}></span>
<Trans>Charts</Trans>
<sup></sup>
</StyledExternalLink>
</HeaderLinks>
<HeaderControls>
<HeaderElement>
<HideSmall>
{chainId && NETWORK_LABELS[chainId] && (
{chainId && chainId !== SupportedChainId.MAINNET && NETWORK_LABELS[chainId] && (
<NetworkCard title={NETWORK_LABELS[chainId]}>{NETWORK_LABELS[chainId]}</NetworkCard>
)}
</HideSmall>
@@ -364,7 +365,13 @@ export default function Header() {
<UNIWrapper onClick={toggleClaimModal}>
<UNIAmount active={!!account && !availableClaim} style={{ pointerEvents: 'auto' }}>
<TYPE.white padding="0 2px">
{claimTxn && !claimTxn?.receipt ? <Dots>Claiming UNI</Dots> : 'Claim UNI'}
{claimTxn && !claimTxn?.receipt ? (
<Dots>
<Trans>Claiming UNI</Trans>
</Dots>
) : (
<Trans>Claim UNI</Trans>
)}
</TYPE.white>
</UNIAmount>
<CardNoise />
@@ -373,7 +380,7 @@ export default function Header() {
<AccountElement active={!!account} style={{ pointerEvents: 'auto' }}>
{account && userEthBalance ? (
<BalanceText style={{ flexShrink: 0 }} pl="0.75rem" pr="0.5rem" fontWeight={500}>
{userEthBalance?.toSignificant(4)} ETH
<Trans>{userEthBalance?.toSignificant(4)} ETH</Trans>
</BalanceText>
) : null}
<Web3Status />

View File

@@ -0,0 +1,62 @@
import Tooltip from 'components/Tooltip'
import React, { useState } from 'react'
import styled from 'styled-components/macro'
const TextWrapper = styled.span<{ margin: boolean; link?: boolean; fontSize?: string; adjustSize?: boolean }>`
margin-left: ${({ margin }) => margin && '4px'};
color: ${({ theme, link }) => (link ? theme.blue1 : theme.text1)};
font-size: ${({ fontSize }) => fontSize ?? 'inherit'};
@media screen and (max-width: 600px) {
font-size: ${({ adjustSize }) => adjustSize && '12px'};
}
`
const HoverInlineText = ({
text,
maxCharacters = 20,
margin = false,
adjustSize = false,
fontSize,
link,
...rest
}: {
text?: string
maxCharacters?: number
margin?: boolean
adjustSize?: boolean
fontSize?: string
link?: boolean
}) => {
const [showHover, setShowHover] = useState(false)
if (!text) {
return <span />
}
if (text.length > maxCharacters) {
return (
<Tooltip text={text} show={showHover}>
<TextWrapper
onMouseEnter={() => setShowHover(true)}
onMouseLeave={() => setShowHover(false)}
margin={margin}
adjustSize={adjustSize}
link={link}
fontSize={fontSize}
{...rest}
>
{' ' + text.slice(0, maxCharacters - 1) + '...'}
</TextWrapper>
</Tooltip>
)
}
return (
<TextWrapper margin={margin} adjustSize={adjustSize} link={link} fontSize={fontSize} {...rest}>
{text}
</TextWrapper>
)
}
export default HoverInlineText

View File

@@ -1,9 +1,9 @@
import React, { useEffect, useRef } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks'
import Jazzicon from 'jazzicon'
import { useActiveWeb3React } from '../../hooks/web3'
import Jazzicon from '@metamask/jazzicon'
const StyledIdenticonContainer = styled.div`
height: 1rem;

View File

@@ -1,4 +1,4 @@
import React, { useState, useCallback, useEffect } from 'react'
import React, { useState, useCallback, useEffect, ReactNode } from 'react'
import { LightCard } from 'components/Card'
import { RowBetween } from 'components/Row'
import { Input as NumericalInput } from '../NumericalInput'
@@ -8,6 +8,7 @@ import { AutoColumn } from 'components/Column'
import { ButtonPrimary } from 'components/Button'
import { FeeAmount } from '@uniswap/v3-sdk'
import { formattedFeeAmount } from 'utils'
import { Trans } from '@lingui/macro'
const pulse = (color: string) => keyframes`
0% {
@@ -59,7 +60,7 @@ interface StepCounterProps {
label?: string
width?: string
locked?: boolean // disable input
title: string
title: ReactNode
tokenA: string | undefined
tokenB: string | undefined
}
@@ -139,16 +140,22 @@ const StepCounter = ({
}}
/>
<InputTitle fontSize={12} textAlign="center">
{tokenB + ' / ' + tokenA}
<Trans>
{tokenB} per {tokenA}
</Trans>
</InputTitle>
</AutoColumn>
{!locked ? (
<RowBetween>
<SmallButton onClick={handleDecrement}>
<TYPE.white fontSize="12px">-{feeAmountFormatted}%</TYPE.white>
<TYPE.white fontSize="12px">
<Trans>-{feeAmountFormatted}%</Trans>
</TYPE.white>
</SmallButton>
<SmallButton onClick={handleIncrement}>
<TYPE.white fontSize="12px">+{feeAmountFormatted}%</TYPE.white>
<TYPE.white fontSize="12px">
<Trans>+{feeAmountFormatted}%</Trans>
</TYPE.white>
</SmallButton>
</RowBetween>
) : null}

View File

@@ -1,90 +0,0 @@
import { Story } from '@storybook/react/types-6-0'
import React from 'react'
// import Row, { RowFixed } from 'components/Row'
import styled from 'styled-components'
import Component, { LineChartProps } from './'
import { dummyData } from './data'
// import { AutoColumn } from 'components/Column'
// import { TYPE } from 'theme'
// import DoubleCurrencyLogo from 'components/DoubleLogo'
// import { MKR } from 'constants'
// import { ETHER } from '@uniswap/sdk'
// import LineChart from '.'
const Wrapper = styled.div`
margin: 1em 2em;
max-width: 500px;
& > * {
font-size: 1em;
}
`
export default {
title: 'Charts',
argTypes: {
disabled: { control: { type: 'boolean' } },
onClick: { action: 'clicked' },
},
decorators: [
(Component: Story) => (
<Wrapper>
<Component />
</Wrapper>
),
],
}
const Template: Story<LineChartProps> = (args) => <Component {...args}>{args.children}</Component>
export const Basic = Template.bind({})
Basic.args = { data: dummyData }
// const Full = () => {
// const [value, setValue] = useState<number | undefined>(dummyData[dummyData.length - 1].value)
// const dummyUSDPrice = 410 // used for conversion
// const TopLeftContent = () => (
// <AutoColumn gap="md">
// <RowFixed align="center">
// <DoubleCurrencyLogo currency0={MKR} currency1={ETHER} size={20} />{' '}
// <TYPE.main fontSize="20px" color="white" ml="10px">
// ETH / MKR
// </TYPE.main>
// </RowFixed>
// <Row>
// <TYPE.main fontSize="20px" color="white">
// {value} MKR
// </TYPE.main>
// <TYPE.main color="#565A69" fontSize="20px" ml="10px">
// ($
// {value
// ? (value * dummyUSDPrice).toLocaleString('USD', {
// currency: 'USD',
// minimumFractionDigits: 2
// })
// : null}{' '}
// )
// </TYPE.main>
// </Row>
// </AutoColumn>
// )
// return (
// <Wrapper>
// <LineChart data={dummyData} setValue={setValue} topLeft={<TopLeftContent />} />
// </Wrapper>
// )
// }
// export const FullVersion = Template.bind(() => <LineChart data={dummyData} />)
// Full.args = { data: dummyData }
// Full.decorators = [
// (Story: any) => {
// return (
// <Wrapper>
// <LineChart data={dummyData} />
// </Wrapper>
// )
// }
// ]

View File

@@ -3,7 +3,7 @@ import { createChart, IChartApi } from 'lightweight-charts'
import { darken } from 'polished'
import { RowBetween } from 'components/Row'
import Card from '../Card'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import useTheme from 'hooks/useTheme'
const Wrapper = styled(Card)`

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import useHttpLocations from '../../hooks/useHttpLocations'
import Logo from '../Logo'

View File

@@ -1,23 +0,0 @@
import { Story } from '@storybook/react/types-6-0'
import React from 'react'
import styled from 'styled-components'
import Component from './index'
const Wrapper = styled.div`
max-width: 150px;
`
export default {
title: 'Menu',
decorators: [
() => (
<Wrapper>
<Component />
</Wrapper>
),
],
}
const Template: Story<any> = (args) => <Component {...args} />
export const Menu = Template.bind({})
Menu.args = {}

View File

@@ -3,10 +3,11 @@ import { BookOpen, Code, Info, MessageCircle, PieChart } from 'react-feather'
import { Link } from 'react-router-dom'
import styled, { css } from 'styled-components'
import { ReactComponent as MenuIcon } from '../../assets/images/menu.svg'
import { useActiveWeb3React } from '../../hooks'
import { useActiveWeb3React } from '../../hooks/web3'
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
import { ApplicationModal } from '../../state/application/actions'
import { useModalOpen, useToggleModal } from '../../state/application/hooks'
import { Trans } from '@lingui/macro'
import { ExternalLink } from '../../theme'
import { ButtonPrimary } from '../Button'
@@ -142,27 +143,37 @@ export default function Menu() {
<MenuFlyout>
<MenuItem href="https://uniswap.org/">
<Info size={14} />
<div>About</div>
<div>
<Trans>About</Trans>
</div>
</MenuItem>
<MenuItem href="https://docs.uniswap.org/">
<BookOpen size={14} />
<div>Docs</div>
<div>
<Trans>Docs</Trans>
</div>
</MenuItem>
<MenuItem href={CODE_LINK}>
<Code size={14} />
<div>Code</div>
<div>
<Trans>Code</Trans>
</div>
</MenuItem>
<MenuItem href="https://discord.gg/FCfyBSbCU5">
<MessageCircle size={14} />
<div>Discord</div>
<div>
<Trans>Discord</Trans>
</div>
</MenuItem>
<MenuItem href="https://info.uniswap.org/">
<PieChart size={14} />
<div>Analytics</div>
<div>
<Trans>Analytics</Trans>
</div>
</MenuItem>
{account && (
<UNIbutton onClick={openClaimModal} padding="8px 16px" width="100%" borderRadius="12px" mt="0.5rem">
Claim UNI
<Trans>Claim UNI</Trans>
</UNIbutton>
)}
</MenuFlyout>

View File

@@ -3,7 +3,6 @@ import styled, { css } from 'styled-components'
import { animated, useTransition, useSpring } from 'react-spring'
import { DialogOverlay, DialogContent } from '@reach/dialog'
import { isMobile } from 'react-device-detect'
import '@reach/dialog/styles.css'
import { transparentize } from 'polished'
import { useGesture } from 'react-use-gesture'

View File

@@ -1,14 +1,15 @@
import React, { useContext } from 'react'
import { useActiveWeb3React } from '../../hooks'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { AutoColumn, ColumnCenter } from '../Column'
import styled, { ThemeContext } from 'styled-components'
import { RowBetween } from '../Row'
import { TYPE, CloseIcon, CustomLightSpinner } from '../../theme'
import { ArrowUpCircle } from 'react-feather'
import { Trans } from '@lingui/macro'
import Circle from '../../assets/images/blue-loader.svg'
import { getEtherscanLink } from '../../utils'
import { ExternalLink } from '../../theme/components'
const ConfirmOrLoadingWrapper = styled.div`
@@ -32,7 +33,9 @@ export function LoadingView({ children, onDismiss }: { children: any; onDismiss:
</ConfirmedIcon>
<AutoColumn gap="100px" justify={'center'}>
{children}
<TYPE.subHeader>Confirm this transaction in your wallet</TYPE.subHeader>
<TYPE.subHeader>
<Trans>Confirm this transaction in your wallet</Trans>
</TYPE.subHeader>
</AutoColumn>
</ConfirmOrLoadingWrapper>
)
@@ -62,8 +65,13 @@ export function SubmittedView({
<AutoColumn gap="100px" justify={'center'}>
{children}
{chainId && hash && (
<ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')} style={{ marginLeft: '4px' }}>
<TYPE.subHeader>View transaction on Etherscan</TYPE.subHeader>
<ExternalLink
href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}
style={{ marginLeft: '4px' }}
>
<TYPE.subHeader>
<Trans>View transaction on Explorer</Trans>
</TYPE.subHeader>
</ExternalLink>
)}
</AutoColumn>

View File

@@ -1,14 +1,15 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { darken } from 'polished'
import { useTranslation } from 'react-i18next'
import { NavLink, Link as HistoryLink } from 'react-router-dom'
import { Trans } from '@lingui/macro'
import { NavLink, Link as HistoryLink, useLocation } from 'react-router-dom'
import { Percent } from '@uniswap/sdk-core'
import { ArrowLeft } from 'react-feather'
import { RowBetween } from '../Row'
import Row, { RowBetween } from '../Row'
import SettingsTab from '../Settings'
import { useDispatch } from 'react-redux'
import { AppDispatch } from 'state'
import { useAppDispatch } from 'state/hooks'
import { resetMintState } from 'state/mint/actions'
import { resetMintState as resetMintV3State } from 'state/mint/v3/actions'
import { TYPE } from 'theme'
@@ -59,14 +60,13 @@ const StyledArrowLeft = styled(ArrowLeft)`
`
export function SwapPoolTabs({ active }: { active: 'swap' | 'pool' }) {
const { t } = useTranslation()
return (
<Tabs style={{ marginBottom: '20px', display: 'none', padding: '1rem 1rem 0 1rem' }}>
<StyledNavLink id={`swap-nav-link`} to={'/swap'} isActive={() => active === 'swap'}>
{t('swap')}
<Trans>Swap</Trans>
</StyledNavLink>
<StyledNavLink id={`pool-nav-link`} to={'/pool'} isActive={() => active === 'pool'}>
{t('pool')}
<Trans>Pool</Trans>
</StyledNavLink>
</Tabs>
)
@@ -79,8 +79,9 @@ export function FindPoolTabs({ origin }: { origin: string }) {
<HistoryLink to={origin}>
<StyledArrowLeft />
</HistoryLink>
<ActiveText>Import Pool</ActiveText>
<SettingsTab />
<ActiveText>
<Trans>Import V2 Pool</Trans>
</ActiveText>
</RowBetween>
</Tabs>
)
@@ -89,22 +90,29 @@ export function FindPoolTabs({ origin }: { origin: string }) {
export function AddRemoveTabs({
adding,
creating,
defaultSlippage,
positionID,
}: {
adding: boolean
creating: boolean
defaultSlippage: Percent
positionID?: string | undefined
}) {
const theme = useTheme()
// reset states on back
const dispatch = useDispatch<AppDispatch>()
const dispatch = useAppDispatch()
const location = useLocation()
// detect if back should redirect to v3 or v2 pool page
const poolLink = location.pathname.includes('add/v2')
? '/pool/v2'
: '/pool' + (!!positionID ? `/${positionID.toString()}` : '')
return (
<Tabs>
<RowBetween style={{ padding: '1rem 1rem 0 1rem' }}>
<HistoryLink
to={'/pool' + (!!positionID ? `/${positionID.toString()}` : '')}
to={poolLink}
onClick={() => {
if (adding) {
// not 100% sure both of these are needed
@@ -116,10 +124,29 @@ export function AddRemoveTabs({
<StyledArrowLeft stroke={theme.text2} />
</HistoryLink>
<TYPE.mediumHeader fontWeight={500} fontSize={20}>
{creating ? 'Create a pair' : adding ? 'Add Liquidity' : 'Remove Liquidity'}
{creating ? (
<Trans>Create a pair</Trans>
) : adding ? (
<Trans>Add Liquidity</Trans>
) : (
<Trans>Remove Liquidity</Trans>
)}
</TYPE.mediumHeader>
<SettingsTab />
<SettingsTab placeholderSlippage={defaultSlippage} />
</RowBetween>
</Tabs>
)
}
export function CreateProposalTabs() {
return (
<Tabs>
<Row style={{ padding: '1rem 1rem 0 1rem' }}>
<HistoryLink to="/vote">
<StyledArrowLeft />
</HistoryLink>
<ActiveText style={{ marginLeft: 'auto', marginRight: 'auto' }}>Create Proposal</ActiveText>
</Row>
</Tabs>
)
}

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { escapeRegExp } from '../../utils'
const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: string }>`

View File

@@ -2,7 +2,7 @@ import { Placement } from '@popperjs/core'
import { transparentize } from 'polished'
import React, { useCallback, useState } from 'react'
import { usePopper } from 'react-popper'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import useInterval from '../../hooks/useInterval'
import Portal from '@reach/portal'

View File

@@ -1,10 +1,12 @@
import { TokenAmount } from '@uniswap/sdk-core'
import React, { useEffect } from 'react'
import { X } from 'react-feather'
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import React, { useCallback, useEffect } from 'react'
import ReactGA from 'react-ga'
import { Heart, X } from 'react-feather'
import styled, { keyframes } from 'styled-components'
import tokenLogo from '../../assets/images/token-logo.png'
import { ButtonPrimary } from '../../components/Button'
import { useActiveWeb3React } from '../../hooks'
import { useActiveWeb3React } from '../../hooks/web3'
import { ApplicationModal } from '../../state/application/actions'
import {
useModalOpen,
@@ -62,14 +64,25 @@ export default function ClaimPopup() {
// toggle for showing this modal
const showClaimModal = useModalOpen(ApplicationModal.SELF_CLAIM)
const toggleSelfClaimModal = useToggleSelfClaimModal()
const handleToggleSelfClaimModal = useCallback(() => {
ReactGA.event({
category: 'MerkleDrop',
action: 'Toggle self claim modal',
})
toggleSelfClaimModal()
}, [toggleSelfClaimModal])
// const userHasAvailableclaim = useUserHasAvailableClaim()
const userHasAvailableclaim: boolean = useUserHasAvailableClaim(account)
const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(account)
// listen for available claim and show popup if needed
useEffect(() => {
if (userHasAvailableclaim) {
ReactGA.event({
category: 'MerkleDrop',
action: 'Show claim popup',
})
toggleShowClaimPopup()
}
// the toggleShowClaimPopup function changes every time the popup changes, so this will cause an infinite loop.
@@ -92,18 +105,20 @@ export default function ClaimPopup() {
<span role="img" aria-label="party">
🎉
</span>{' '}
UNI has arrived{' '}
<Trans>UNI has arrived</Trans>{' '}
<span role="img" aria-label="party">
🎉
</span>
</TYPE.white>
<TYPE.subHeader style={{ paddingTop: '0.5rem', textAlign: 'center' }} color="white">
{`Thanks for being part of the Uniswap community <3`}
<Trans>
Thanks for being part of the Uniswap community <Heart size={12} />
</Trans>
</TYPE.subHeader>
</AutoColumn>
<AutoColumn style={{ zIndex: 10 }} justify="center">
<ButtonPrimary padding="8px" borderRadius="8px" width={'fit-content'} onClick={toggleSelfClaimModal}>
Claim your UNI tokens
<ButtonPrimary padding="8px" borderRadius="8px" width={'fit-content'} onClick={handleToggleSelfClaimModal}>
<Trans>Claim your UNI tokens</Trans>
</ButtonPrimary>
</AutoColumn>
</StyledClaimPopup>

View File

@@ -1,112 +0,0 @@
import { diffTokenLists, TokenList } from '@uniswap/token-lists'
import React, { useCallback, useMemo } from 'react'
import ReactGA from 'react-ga'
import { useDispatch } from 'react-redux'
import { Text } from 'rebass'
import styled from 'styled-components'
import { AppDispatch } from '../../state'
import { useRemovePopup } from '../../state/application/hooks'
import { acceptListUpdate } from '../../state/lists/actions'
import { TYPE } from '../../theme'
import listVersionLabel from '../../utils/listVersionLabel'
import { ButtonSecondary } from '../Button'
import { AutoColumn } from '../Column'
import { AutoRow } from '../Row'
export const ChangesList = styled.ul`
max-height: 400px;
overflow: auto;
`
export default function ListUpdatePopup({
popKey,
listUrl,
oldList,
newList,
auto,
}: {
popKey: string
listUrl: string
oldList: TokenList
newList: TokenList
auto: boolean
}) {
const removePopup = useRemovePopup()
const removeThisPopup = useCallback(() => removePopup(popKey), [popKey, removePopup])
const dispatch = useDispatch<AppDispatch>()
const handleAcceptUpdate = useCallback(() => {
if (auto) return
ReactGA.event({
category: 'Lists',
action: 'Update List from Popup',
label: listUrl,
})
dispatch(acceptListUpdate(listUrl))
removeThisPopup()
}, [auto, dispatch, listUrl, removeThisPopup])
const { added: tokensAdded, changed: tokensChanged, removed: tokensRemoved } = useMemo(() => {
return diffTokenLists(oldList.tokens, newList.tokens)
}, [newList.tokens, oldList.tokens])
const numTokensChanged = useMemo(
() =>
Object.keys(tokensChanged).reduce((memo, chainId: any) => memo + Object.keys(tokensChanged[chainId]).length, 0),
[tokensChanged]
)
return (
<AutoRow>
<AutoColumn style={{ flex: '1' }} gap="8px">
{auto ? (
<TYPE.body fontWeight={500}>
The token list &quot;{oldList.name}&quot; has been updated to{' '}
<strong>{listVersionLabel(newList.version)}</strong>.
</TYPE.body>
) : (
<>
<div>
<Text>
An update is available for the token list &quot;{oldList.name}&quot; (
{listVersionLabel(oldList.version)} to {listVersionLabel(newList.version)}).
</Text>
<ChangesList>
{tokensAdded.length > 0 ? (
<li>
{tokensAdded.map((token, i) => (
<React.Fragment key={`${token.chainId}-${token.address}`}>
<strong title={token.address}>{token.symbol}</strong>
{i === tokensAdded.length - 1 ? null : ', '}
</React.Fragment>
))}{' '}
added
</li>
) : null}
{tokensRemoved.length > 0 ? (
<li>
{tokensRemoved.map((token, i) => (
<React.Fragment key={`${token.chainId}-${token.address}`}>
<strong title={token.address}>{token.symbol}</strong>
{i === tokensRemoved.length - 1 ? null : ', '}
</React.Fragment>
))}{' '}
removed
</li>
) : null}
{numTokensChanged > 0 ? <li>{numTokensChanged} tokens updated</li> : null}
</ChangesList>
</div>
<AutoRow>
<div style={{ flexGrow: 1, marginRight: 12 }}>
<ButtonSecondary onClick={handleAcceptUpdate}>Accept update</ButtonSecondary>
</div>
<div style={{ flexGrow: 1 }}>
<ButtonSecondary onClick={removeThisPopup}>Dismiss</ButtonSecondary>
</div>
</AutoRow>
</>
)}
</AutoColumn>
</AutoRow>
)
}

View File

@@ -5,7 +5,6 @@ import styled, { ThemeContext } from 'styled-components'
import { animated } from 'react-spring'
import { PopupContent } from '../../state/application/actions'
import { useRemovePopup } from '../../state/application/hooks'
import ListUpdatePopup from './ListUpdatePopup'
import TransactionPopup from './TransactionPopup'
export const StyledClose = styled(X)`
@@ -77,11 +76,6 @@ export default function PopupItem({
txn: { hash, success, summary },
} = content
popupContent = <TransactionPopup hash={hash} success={success} summary={summary} />
} else if ('listUpdate' in content) {
const {
listUpdate: { listUrl, oldList, newList, auto },
} = content
popupContent = <ListUpdatePopup popKey={popKey} listUrl={listUrl} oldList={oldList} newList={newList} auto={auto} />
}
const faderStyle = useSpring({

View File

@@ -1,10 +1,10 @@
import React, { useContext } from 'react'
import { AlertCircle, CheckCircle } from 'react-feather'
import styled, { ThemeContext } from 'styled-components'
import { useActiveWeb3React } from '../../hooks'
import { useActiveWeb3React } from '../../hooks/web3'
import { TYPE } from '../../theme'
import { ExternalLink } from '../../theme/components'
import { getEtherscanLink } from '../../utils'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { AutoColumn } from '../Column'
import { AutoRow } from '../Row'
@@ -33,7 +33,9 @@ export default function TransactionPopup({
<AutoColumn gap="8px">
<TYPE.body fontWeight={500}>{summary ?? 'Hash: ' + hash.slice(0, 8) + '...' + hash.slice(58, 65)}</TYPE.body>
{chainId && (
<ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')}>View on Etherscan</ExternalLink>
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}>
View on Explorer
</ExternalLink>
)}
</AutoColumn>
</RowNoFlex>

View File

@@ -1,5 +1,5 @@
import React from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useActivePopups } from '../../state/application/hooks'
import { AutoColumn } from '../Column'
import PopupItem from './PopupItem'
@@ -33,7 +33,7 @@ const MobilePopupInner = styled.div`
const FixedPopupColumn = styled(AutoColumn)<{ extraPadding: boolean }>`
position: fixed;
top: ${({ extraPadding }) => (extraPadding ? '72px' : '88px')};
top: ${({ extraPadding }) => (extraPadding ? '80px' : '88px')};
right: 1rem;
max-width: 355px !important;
width: 100%;

View File

@@ -2,9 +2,10 @@ import React from 'react'
import { Token } from '@uniswap/sdk-core'
import { Link } from 'react-router-dom'
import { Text } from 'rebass'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { Trans } from '@lingui/macro'
import { unwrappedToken } from '../../utils/wrappedCurrency'
import { unwrappedToken } from '../../utils/unwrappedToken'
import { ButtonEmpty } from '../Button'
import { transparentize } from 'polished'
import { CardNoise } from '../earn/styled'
@@ -48,7 +49,13 @@ export default function SushiPositionCard({ tokenA, tokenB, liquidityToken, bord
<AutoRow gap="8px">
<DoubleCurrencyLogo currency0={currency0} currency1={currency1} size={20} />
<Text fontWeight={500} fontSize={20}>
{!currency0 || !currency1 ? <Dots>Loading</Dots> : `${currency0.symbol}/${currency1.symbol}`}
{!currency0 || !currency1 ? (
<Dots>
<Trans>Loading</Trans>
</Dots>
) : (
`${currency0.symbol}/${currency1.symbol}`
)}
</Text>
<Badge variant={BadgeVariant.WARNING}>Sushi</Badge>
@@ -61,7 +68,7 @@ export default function SushiPositionCard({ tokenA, tokenB, liquidityToken, bord
as={Link}
to={`/migrate/v2/${liquidityToken.address}`}
>
Migrate
<Trans>Migrate</Trans>
</ButtonEmpty>
</RowFixed>
</FixedHeightRow>

View File

@@ -1,16 +1,18 @@
import JSBI from 'jsbi'
import React, { useState } from 'react'
import { Percent, TokenAmount } from '@uniswap/sdk-core'
import { JSBI, Pair } from '@uniswap/v2-sdk'
import { Percent, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { ChevronDown, ChevronUp } from 'react-feather'
import { Link } from 'react-router-dom'
import { Text } from 'rebass'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { Trans } from '@lingui/macro'
import { useActiveWeb3React } from '../../hooks'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTokenBalance } from '../../state/wallet/hooks'
import { currencyId } from '../../utils/currencyId'
import { unwrappedToken } from '../../utils/wrappedCurrency'
import { unwrappedToken } from '../../utils/unwrappedToken'
import { ButtonPrimary, ButtonSecondary, ButtonEmpty } from '../Button'
import { transparentize } from 'polished'
import { CardNoise } from '../earn/styled'
@@ -23,7 +25,7 @@ import CurrencyLogo from '../CurrencyLogo'
import DoubleCurrencyLogo from '../DoubleLogo'
import { RowBetween, RowFixed, AutoRow } from '../Row'
import { Dots } from '../swap/styleds'
import { BIG_INT_ZERO } from '../../constants'
import { BIG_INT_ZERO } from '../../constants/misc'
import { FixedHeightRow } from '.'
const StyledPositionCard = styled(LightCard)<{ bgColor: any }>`
@@ -38,7 +40,7 @@ interface PositionCardProps {
pair: Pair
showUnwrapped?: boolean
border?: string
stakedBalance?: TokenAmount // optional balance to indicate that liquidity is deposited in mining pool
stakedBalance?: CurrencyAmount<Token> // optional balance to indicate that liquidity is deposited in mining pool
}
export default function V2PositionCard({ pair, border, stakedBalance }: PositionCardProps) {
@@ -56,8 +58,10 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
const userPoolBalance = stakedBalance ? userDefaultPoolBalance?.add(stakedBalance) : userDefaultPoolBalance
const poolTokenPercentage =
!!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
!!userPoolBalance &&
!!totalPoolTokens &&
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? new Percent(userPoolBalance.quotient, totalPoolTokens.quotient)
: undefined
const [token0Deposited, token1Deposited] =
@@ -65,7 +69,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
!!totalPoolTokens &&
!!userPoolBalance &&
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? [
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
@@ -82,7 +86,13 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
<AutoRow gap="8px">
<DoubleCurrencyLogo currency0={currency0} currency1={currency1} size={20} />
<Text fontWeight={500} fontSize={20}>
{!currency0 || !currency1 ? <Dots>Loading</Dots> : `${currency0.symbol}/${currency1.symbol}`}
{!currency0 || !currency1 ? (
<Dots>
<Trans>Loading</Trans>
</Dots>
) : (
`${currency0.symbol}/${currency1.symbol}`
)}
</Text>
</AutoRow>
<RowFixed gap="8px">
@@ -94,12 +104,12 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
>
{showMore ? (
<>
Manage
<Trans>Manage</Trans>
<ChevronUp size="20" style={{ marginLeft: '10px' }} />
</>
) : (
<>
Manage
<Trans>Manage</Trans>
<ChevronDown size="20" style={{ marginLeft: '10px' }} />
</>
)}
@@ -111,7 +121,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
<AutoColumn gap="8px">
<FixedHeightRow>
<Text fontSize={16} fontWeight={500}>
Your total pool tokens:
<Trans>Your total pool tokens:</Trans>
</Text>
<Text fontSize={16} fontWeight={500}>
{userPoolBalance ? userPoolBalance.toSignificant(4) : '-'}
@@ -120,7 +130,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
{stakedBalance && (
<FixedHeightRow>
<Text fontSize={16} fontWeight={500}>
Pool tokens in rewards pool:
<Trans>Pool tokens in rewards pool:</Trans>
</Text>
<Text fontSize={16} fontWeight={500}>
{stakedBalance.toSignificant(4)}
@@ -130,7 +140,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
<FixedHeightRow>
<RowFixed>
<Text fontSize={16} fontWeight={500}>
Pooled {currency0.symbol}:
<Trans>Pooled {currency0.symbol}:</Trans>
</Text>
</RowFixed>
{token0Deposited ? (
@@ -148,7 +158,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
<FixedHeightRow>
<RowFixed>
<Text fontSize={16} fontWeight={500}>
Pooled {currency1.symbol}:
<Trans>Pooled {currency1.symbol}:</Trans>
</Text>
</RowFixed>
{token1Deposited ? (
@@ -165,7 +175,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
<FixedHeightRow>
<Text fontSize={16} fontWeight={500}>
Your pool share:
<Trans>Your pool share:</Trans>
</Text>
<Text fontSize={16} fontWeight={500}>
{poolTokenPercentage
@@ -174,7 +184,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
</Text>
</FixedHeightRow>
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.raw, BIG_INT_ZERO) && (
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.quotient, BIG_INT_ZERO) && (
<RowBetween marginTop="10px">
<ButtonPrimary
padding="8px"
@@ -183,7 +193,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
to={`/migrate/v2/${pair.liquidityToken.address}`}
width="64%"
>
Migrate
<Trans>Migrate</Trans>
</ButtonPrimary>
<ButtonSecondary
padding="8px"
@@ -192,7 +202,7 @@ export default function V2PositionCard({ pair, border, stakedBalance }: Position
width="32%"
to={`/remove/v2/${currencyId(currency0)}/${currencyId(currency1)}`}
>
Remove
<Trans>Remove</Trans>
</ButtonSecondary>
</RowBetween>
)}

View File

@@ -1,18 +1,20 @@
import { Percent, TokenAmount } from '@uniswap/sdk-core'
import { JSBI, Pair } from '@uniswap/v2-sdk'
import JSBI from 'jsbi'
import { Percent, CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { darken } from 'polished'
import React, { useState } from 'react'
import { ChevronDown, ChevronUp } from 'react-feather'
import { Link } from 'react-router-dom'
import { Text } from 'rebass'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { useTotalSupply } from '../../hooks/useTotalSupply'
import { Trans } from '@lingui/macro'
import { useActiveWeb3React } from '../../hooks'
import { useActiveWeb3React } from '../../hooks/web3'
import { useTokenBalance } from '../../state/wallet/hooks'
import { ExternalLink, TYPE } from '../../theme'
import { currencyId } from '../../utils/currencyId'
import { unwrappedToken } from '../../utils/wrappedCurrency'
import { unwrappedToken } from '../../utils/unwrappedToken'
import { ButtonPrimary, ButtonSecondary, ButtonEmpty } from '../Button'
import { transparentize } from 'polished'
import { CardNoise } from '../earn/styled'
@@ -25,7 +27,7 @@ import CurrencyLogo from '../CurrencyLogo'
import DoubleCurrencyLogo from '../DoubleLogo'
import { RowBetween, RowFixed, AutoRow } from '../Row'
import { Dots } from '../swap/styleds'
import { BIG_INT_ZERO } from '../../constants'
import { BIG_INT_ZERO } from '../../constants/misc'
export const FixedHeightRow = styled(RowBetween)`
height: 24px;
@@ -49,7 +51,7 @@ interface PositionCardProps {
pair: Pair
showUnwrapped?: boolean
border?: string
stakedBalance?: TokenAmount // optional balance to indicate that liquidity is deposited in mining pool
stakedBalance?: CurrencyAmount<Token> // optional balance to indicate that liquidity is deposited in mining pool
}
export function MinimalPositionCard({ pair, showUnwrapped = false, border }: PositionCardProps) {
@@ -64,8 +66,10 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
const totalPoolTokens = useTotalSupply(pair.liquidityToken)
const poolTokenPercentage =
!!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
!!userPoolBalance &&
!!totalPoolTokens &&
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? new Percent(userPoolBalance.quotient, totalPoolTokens.quotient)
: undefined
const [token0Deposited, token1Deposited] =
@@ -73,7 +77,7 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
!!totalPoolTokens &&
!!userPoolBalance &&
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? [
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
@@ -82,13 +86,13 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
return (
<>
{userPoolBalance && JSBI.greaterThan(userPoolBalance.raw, JSBI.BigInt(0)) ? (
{userPoolBalance && JSBI.greaterThan(userPoolBalance.quotient, JSBI.BigInt(0)) ? (
<GreyCard border={border}>
<AutoColumn gap="12px">
<FixedHeightRow>
<RowFixed>
<Text fontWeight={500} fontSize={16}>
Your position
<Trans>Your position</Trans>
</Text>
</RowFixed>
</FixedHeightRow>
@@ -108,7 +112,7 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
<AutoColumn gap="4px">
<FixedHeightRow>
<Text fontSize={16} fontWeight={500}>
Your pool share:
<Trans>Your pool share:</Trans>
</Text>
<Text fontSize={16} fontWeight={500}>
{poolTokenPercentage ? poolTokenPercentage.toFixed(6) + '%' : '-'}
@@ -151,8 +155,10 @@ export function MinimalPositionCard({ pair, showUnwrapped = false, border }: Pos
<span role="img" aria-label="wizard-icon">
</span>{' '}
By adding liquidity you&apos;ll earn 0.3% of all trades on this pair proportional to your share of the pool.
Fees are added to the pool, accrue in real time and can be claimed by withdrawing your liquidity.
<Trans>
By adding liquidity you&apos;ll earn 0.3% of all trades on this pair proportional to your share of the
pool. Fees are added to the pool, accrue in real time and can be claimed by withdrawing your liquidity.
</Trans>{' '}
</TYPE.subHeader>
</LightCard>
)}
@@ -175,8 +181,10 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
const userPoolBalance = stakedBalance ? userDefaultPoolBalance?.add(stakedBalance) : userDefaultPoolBalance
const poolTokenPercentage =
!!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
!!userPoolBalance &&
!!totalPoolTokens &&
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? new Percent(userPoolBalance.quotient, totalPoolTokens.quotient)
: undefined
const [token0Deposited, token1Deposited] =
@@ -184,7 +192,7 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
!!totalPoolTokens &&
!!userPoolBalance &&
// this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
JSBI.greaterThanOrEqual(totalPoolTokens.quotient, userPoolBalance.quotient)
? [
pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
@@ -198,28 +206,29 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
<CardNoise />
<AutoColumn gap="12px">
<FixedHeightRow>
<AutoRow gap="8px">
<AutoRow gap="8px" style={{ marginLeft: '8px' }}>
<DoubleCurrencyLogo currency0={currency0} currency1={currency1} size={20} />
<Text fontWeight={500} fontSize={20}>
{!currency0 || !currency1 ? <Dots>Loading</Dots> : `${currency0.symbol}/${currency1.symbol}`}
{!currency0 || !currency1 ? (
<Dots>
<Trans>Loading</Trans>
</Dots>
) : (
`${currency0.symbol}/${currency1.symbol}`
)}
</Text>
</AutoRow>
<RowFixed gap="8px">
<ButtonEmpty
padding="6px 8px"
borderRadius="12px"
width="fit-content"
onClick={() => setShowMore(!showMore)}
>
<RowFixed gap="8px" style={{ marginRight: '4px' }}>
<ButtonEmpty padding="6px 8px" borderRadius="12px" width="100%" onClick={() => setShowMore(!showMore)}>
{showMore ? (
<>
Manage
<ChevronUp size="20" style={{ marginLeft: '10px' }} />
<Trans>Manage</Trans>
<ChevronUp size="20" style={{ marginLeft: '8px', height: '20px', minWidth: '20px' }} />
</>
) : (
<>
Manage
<ChevronDown size="20" style={{ marginLeft: '10px' }} />
<Trans>Manage</Trans>
<ChevronDown size="20" style={{ marginLeft: '8px', height: '20px', minWidth: '20px' }} />
</>
)}
</ButtonEmpty>
@@ -230,7 +239,7 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
<AutoColumn gap="8px">
<FixedHeightRow>
<Text fontSize={16} fontWeight={500}>
Your total pool tokens:
<Trans>Your total pool tokens:</Trans>
</Text>
<Text fontSize={16} fontWeight={500}>
{userPoolBalance ? userPoolBalance.toSignificant(4) : '-'}
@@ -239,7 +248,7 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
{stakedBalance && (
<FixedHeightRow>
<Text fontSize={16} fontWeight={500}>
Pool tokens in rewards pool:
<Trans>Pool tokens in rewards pool:</Trans>
</Text>
<Text fontSize={16} fontWeight={500}>
{stakedBalance.toSignificant(4)}
@@ -249,7 +258,7 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
<FixedHeightRow>
<RowFixed>
<Text fontSize={16} fontWeight={500}>
Pooled {currency0.symbol}:
<Trans>Pooled {currency0.symbol}:</Trans>
</Text>
</RowFixed>
{token0Deposited ? (
@@ -267,7 +276,7 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
<FixedHeightRow>
<RowFixed>
<Text fontSize={16} fontWeight={500}>
Pooled {currency1.symbol}:
<Trans>Pooled {currency1.symbol}:</Trans>
</Text>
</RowFixed>
{token1Deposited ? (
@@ -284,12 +293,16 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
<FixedHeightRow>
<Text fontSize={16} fontWeight={500}>
Your pool share:
<Trans>Your pool share:</Trans>
</Text>
<Text fontSize={16} fontWeight={500}>
{poolTokenPercentage
? (poolTokenPercentage.toFixed(2) === '0.00' ? '<0.01' : poolTokenPercentage.toFixed(2)) + '%'
: '-'}
{poolTokenPercentage ? (
<Trans>
{poolTokenPercentage.toFixed(2) === '0.00' ? '<0.01' : poolTokenPercentage.toFixed(2)} %
</Trans>
) : (
'-'
)}
</Text>
</FixedHeightRow>
@@ -298,32 +311,43 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
style={{ width: '100%', textAlign: 'center' }}
href={`https://v2.info.uniswap.org/account/${account}`}
>
View accrued fees and analytics<span style={{ fontSize: '11px' }}></span>
<Trans>
View accrued fees and analytics<span style={{ fontSize: '11px' }}></span>
</Trans>
</ExternalLink>
</ButtonSecondary>
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.raw, BIG_INT_ZERO) && (
{userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.quotient, BIG_INT_ZERO) && (
<RowBetween marginTop="10px">
<ButtonPrimary
padding="8px"
borderRadius="8px"
as={Link}
to={`/add/v2/${currencyId(currency0)}/${currencyId(currency1)}`}
width="48%"
to={`/migrate/v2/${pair.liquidityToken.address}`}
width="32%"
>
Add
<Trans>Migrate</Trans>
</ButtonPrimary>
<ButtonPrimary
padding="8px"
borderRadius="8px"
as={Link}
width="48%"
to={`/add/v2/${currencyId(currency0)}/${currencyId(currency1)}`}
width="32%"
>
<Trans>Add</Trans>
</ButtonPrimary>
<ButtonPrimary
padding="8px"
borderRadius="8px"
as={Link}
width="32%"
to={`/remove/v2/${currencyId(currency0)}/${currencyId(currency1)}`}
>
Remove
<Trans>Remove</Trans>
</ButtonPrimary>
</RowBetween>
)}
{stakedBalance && JSBI.greaterThan(stakedBalance.raw, BIG_INT_ZERO) && (
{stakedBalance && JSBI.greaterThan(stakedBalance.quotient, BIG_INT_ZERO) && (
<ButtonPrimary
padding="8px"
borderRadius="8px"
@@ -331,7 +355,7 @@ export default function FullPositionCard({ pair, border, stakedBalance }: Positi
to={`/uni/${currencyId(currency0)}/${currencyId(currency1)}`}
width="100%"
>
Manage Liquidity in Rewards Pool
<Trans>Manage Liquidity in Rewards Pool</Trans>
</ButtonPrimary>
)}
</AutoColumn>

View File

@@ -1,53 +0,0 @@
// import { Story } from '@storybook/react/types-6-0'
// import React from 'react'
// import { Position } from 'types/position'
// import { basisPointsToPercent } from 'utils'
// import { DAI, WBTC } from '../../constants'
// import Component, { PositionListProps } from './index'
// import { TokenAmount } from '@uniswap/sdk-core'
// import JSBI from 'jsbi'
// const FEE_BIPS = {
// FIVE: basisPointsToPercent(5),
// THIRTY: basisPointsToPercent(30),
// ONE_HUNDRED: basisPointsToPercent(100),
// }
// const daiAmount = new TokenAmount(DAI, JSBI.BigInt(500 * 10 ** 18))
// const wbtcAmount = new TokenAmount(WBTC, JSBI.BigInt(10 ** 7))
// const positions = [
// {
// feesEarned: {
// DAI: 1000,
// WBTC: 0.005,
// },
// feeLevel: FEE_BIPS.FIVE,
// tokenAmount0: daiAmount,
// tokenAmount1: wbtcAmount,
// tickLower: 40000,
// tickUpper: 60000,
// },
// {
// feesEarned: {
// DAI: 1000,
// WBTC: 0.005,
// },
// feeLevel: FEE_BIPS.THIRTY,
// tokenAmount0: daiAmount,
// tokenAmount1: wbtcAmount,
// tickLower: 45000,
// tickUpper: 55000,
// },
// ]
// const positions: Position[] = []
export default {
title: 'PositionList',
}
// const Template: Story<PositionListProps> = (args) => <Component {...args} />
// export const PositionList = Template.bind({})
// PositionList.args = {
// positions,
// showUnwrapped: true,
// }

View File

@@ -1,7 +1,7 @@
import PositionListItem from 'components/PositionListItem'
import React from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import { Trans } from '@lingui/macro'
import styled from 'styled-components/macro'
import { MEDIA_WIDTHS } from 'theme'
import { PositionDetails } from 'types/position'
@@ -39,18 +39,20 @@ export type PositionListProps = React.PropsWithChildren<{
}>
export default function PositionList({ positions }: PositionListProps) {
const { t } = useTranslation()
return (
<>
<DesktopHeader>
<div>
{t('Your positions')}
<Trans>Your positions</Trans>
{positions && ' (' + positions.length + ')'}
</div>
<div>{t('Price range')}</div>
<div>
<Trans>Price range</Trans>
</div>
</DesktopHeader>
<MobileHeader>Your positions</MobileHeader>
<MobileHeader>
<Trans>Your positions</Trans>
</MobileHeader>
{positions.map((p) => {
return <PositionListItem key={p.tokenId.toString()} positionDetails={p} />
})}

View File

@@ -1,31 +0,0 @@
// import { Story } from '@storybook/react/types-6-0'
// import { FeeAmount, MAX_TICK, MIN_TICK, TICK_SPACINGS } from '@uniswap/v3-sdk'
// import { BigNumber } from 'ethers'
// import React from 'react'
// import { Position } from 'types/position'
// import Component, { PositionListItemProps } from './index'
// const position: Position = {
// nonce: BigNumber.from(0),
// operator: '',
// token0: '',
// token1: '',
// fee: FeeAmount.LOW,
// tickLower: MIN_TICK(TICK_SPACINGS[FeeAmount.LOW]),
// tickUpper: MAX_TICK(TICK_SPACINGS[FeeAmount.LOW]),
// liquidity,
// feeGrowthInside0LastX128fee
// feeGrowthInside0LastX128
// feeGrowthInside1LastX128
// tokensOwed0
// tokensOwed1
// }
export default {
title: 'PositionListItem',
}
// const Template: Story<PositionListItemProps> = (args) => <Component {...args} />
// export const PositionListItem = Template.bind({})
// PositionListItem.args = {position}

View File

@@ -1,25 +1,29 @@
import React, { useMemo, useState } from 'react'
import React, { useMemo } from 'react'
import { Position } from '@uniswap/v3-sdk'
import Badge from 'components/Badge'
import DoubleCurrencyLogo from 'components/DoubleLogo'
import { usePool } from 'hooks/usePools'
import { useToken } from 'hooks/Tokens'
import { Link } from 'react-router-dom'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { HideSmall, MEDIA_WIDTHS, SmallOnly } from 'theme'
import { PositionDetails } from 'types/position'
import { WETH9, Price, Token, Percent } from '@uniswap/sdk-core'
import { formatPrice } from 'utils/formatTokenAmount'
import { Price, Token, Percent } from '@uniswap/sdk-core'
import { formatPrice } from 'utils/formatCurrencyAmount'
import Loader from 'components/Loader'
import { unwrappedToken } from 'utils/wrappedCurrency'
import { DAI, USDC, USDT, WBTC } from '../../constants'
import { unwrappedToken } from 'utils/unwrappedToken'
import RangeBadge from 'components/Badge/RangeBadge'
import { RowFixed } from 'components/Row'
import HoverInlineText from 'components/HoverInlineText'
import { DAI, USDC, USDT, WBTC, WETH9_EXTENDED } from '../../constants/tokens'
import { Trans } from '@lingui/macro'
const Row = styled(Link)`
const LinkRow = styled(Link)`
align-items: center;
border-radius: 20px;
display: flex;
cursor: pointer;
user-select: none;
justify-content: space-between;
color: ${({ theme }) => theme.text1};
margin: 8px 0;
@@ -49,6 +53,7 @@ const Row = styled(Link)`
row-gap: 24px;
`};
`
const BadgeText = styled.div`
font-weight: 500;
font-size: 14px;
@@ -64,7 +69,6 @@ const DataLineItem = styled.div`
const RangeLineItem = styled(DataLineItem)`
display: flex;
flex-direction: row;
cursor: pointer;
align-items: center;
justify-self: flex-end;
@@ -117,11 +121,9 @@ export interface PositionListItemProps {
positionDetails: PositionDetails
}
export function getPriceOrderingFromPositionForUI(
position?: Position
): {
priceLower?: Price
priceUpper?: Price
export function getPriceOrderingFromPositionForUI(position?: Position): {
priceLower?: Price<Token, Token>
priceUpper?: Price<Token, Token>
quote?: Token
base?: Token
} {
@@ -129,8 +131,8 @@ export function getPriceOrderingFromPositionForUI(
return {}
}
const token0 = position.amount0.token
const token1 = position.amount1.token
const token0 = position.amount0.currency
const token1 = position.amount1.currency
// if token0 is a dollar-stable asset, set it as the quote token
const stables = [DAI, USDC, USDT]
@@ -144,7 +146,7 @@ export function getPriceOrderingFromPositionForUI(
}
// if token1 is an ETH-/BTC-stable asset, set it as the base token
const bases = [...Object.values(WETH9), WBTC]
const bases = [...Object.values(WETH9_EXTENDED), WBTC]
if (bases.some((base) => base.equals(token1))) {
return {
priceLower: position.token0PriceUpper.invert(),
@@ -200,25 +202,20 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
}, [liquidity, pool, tickLower, tickUpper])
// prices
let { priceLower, priceUpper, base, quote } = getPriceOrderingFromPositionForUI(position)
const inverted = token1 ? base?.equals(token1) : undefined
const currencyQuote = inverted ? currency1 : currency0
const currencyBase = inverted ? currency0 : currency1
const { priceLower, priceUpper, quote, base } = getPriceOrderingFromPositionForUI(position)
const currencyQuote = quote && unwrappedToken(quote)
const currencyBase = base && unwrappedToken(base)
// check if price is within range
const outOfRange: boolean = pool ? pool.tickCurrent < tickLower || pool.tickCurrent >= tickUpper : false
const positionSummaryLink = '/pool/' + positionDetails.tokenId
const [manuallyInverted, setManuallyInverted] = useState(true)
if (manuallyInverted) {
;[priceLower, priceUpper, base, quote] = [priceUpper?.invert(), priceLower?.invert(), quote, base]
}
const removed = liquidity?.eq(0)
return (
<Row to={positionSummaryLink}>
<LinkRow to={positionSummaryLink}>
<RowFixed>
<PrimaryPositionIdData>
<DoubleCurrencyLogo currency0={currencyBase} currency1={currencyQuote} size={18} margin />
@@ -227,42 +224,44 @@ export default function PositionListItem({ positionDetails }: PositionListItemPr
</DataText>
&nbsp;
<Badge>
<BadgeText>{new Percent(feeAmount, 1_000_000).toSignificant()}%</BadgeText>
<BadgeText>
<Trans>{new Percent(feeAmount, 1_000_000).toSignificant()}%</Trans>
</BadgeText>
</Badge>
</PrimaryPositionIdData>
<RangeBadge removed={removed} inRange={!outOfRange} />
</RowFixed>
{priceLower && priceUpper ? (
<>
<RangeLineItem
onClick={(e) => {
e.preventDefault()
e.stopPropagation()
setManuallyInverted(!manuallyInverted)
}}
>
<RangeText>
<ExtentsText>Min: </ExtentsText>
{formatPrice(priceLower, 4)} {manuallyInverted ? currencyQuote?.symbol : currencyBase?.symbol} {' / '}{' '}
{manuallyInverted ? currencyBase?.symbol : currencyQuote?.symbol}
</RangeText>{' '}
<HideSmall>
<DoubleArrow></DoubleArrow>{' '}
</HideSmall>
<SmallOnly>
<DoubleArrow></DoubleArrow>{' '}
</SmallOnly>
<RangeText>
<ExtentsText>Max:</ExtentsText>
{formatPrice(priceUpper, 4)} {manuallyInverted ? currencyQuote?.symbol : currencyBase?.symbol} {' / '}{' '}
{manuallyInverted ? currencyBase?.symbol : currencyQuote?.symbol}
</RangeText>{' '}
</RangeLineItem>
</>
<RangeLineItem>
<RangeText>
<ExtentsText>
<Trans>Min: </Trans>
</ExtentsText>
<Trans>
{formatPrice(priceLower, 5)} <HoverInlineText text={currencyQuote?.symbol} /> per{' '}
<HoverInlineText text={currencyBase?.symbol ?? ''} />
</Trans>
</RangeText>{' '}
<HideSmall>
<DoubleArrow></DoubleArrow>{' '}
</HideSmall>
<SmallOnly>
<DoubleArrow></DoubleArrow>{' '}
</SmallOnly>
<RangeText>
<ExtentsText>
<Trans>Max:</Trans>
</ExtentsText>
<Trans>
{formatPrice(priceUpper, 5)} <HoverInlineText text={currencyQuote?.symbol} /> per{' '}
<HoverInlineText maxCharacters={10} text={currencyBase?.symbol} />
</Trans>
</RangeText>
</RangeLineItem>
) : (
<Loader />
)}
</Row>
</LinkRow>
)
}

View File

@@ -1,19 +1,19 @@
import React, { useState, useCallback, useContext } from 'react'
import React, { useState, useCallback, useContext, ReactNode } from 'react'
import { Position } from '@uniswap/v3-sdk'
import { LightCard } from 'components/Card'
import { AutoColumn } from 'components/Column'
import { TYPE } from 'theme'
import { RowBetween, RowFixed } from 'components/Row'
import CurrencyLogo from 'components/CurrencyLogo'
import { unwrappedToken } from 'utils/wrappedCurrency'
import { unwrappedToken } from 'utils/unwrappedToken'
import { Break } from 'components/earn/styled'
import { useTranslation } from 'react-i18next'
import { Trans } from '@lingui/macro'
import { Currency } from '@uniswap/sdk-core'
import RateToggle from 'components/RateToggle'
import DoubleCurrencyLogo from 'components/DoubleLogo'
import RangeBadge from 'components/Badge/RangeBadge'
import { ThemeContext } from 'styled-components'
import { JSBI } from '@uniswap/v2-sdk'
import JSBI from 'jsbi'
export const PositionPreview = ({
position,
@@ -22,12 +22,10 @@ export const PositionPreview = ({
baseCurrencyDefault,
}: {
position: Position
title?: string
title?: ReactNode
inRange: boolean
baseCurrencyDefault?: Currency | undefined
}) => {
const { t } = useTranslation()
const theme = useContext(ThemeContext)
const currency0 = unwrappedToken(position.pool.token0)
@@ -97,8 +95,12 @@ export const PositionPreview = ({
</RowBetween>
<Break />
<RowBetween>
<TYPE.label>{t('feeTier')}</TYPE.label>
<TYPE.label>{position?.pool?.fee / 10000}%</TYPE.label>
<TYPE.label>
<Trans>Fee Tier</Trans>
</TYPE.label>
<TYPE.label>
<Trans>{position?.pool?.fee / 10000}%</Trans>
</TYPE.label>
</RowBetween>
</AutoColumn>
</LightCard>
@@ -116,40 +118,49 @@ export const PositionPreview = ({
<RowBetween>
<LightCard width="48%" padding="8px">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">Min Price</TYPE.main>
<TYPE.main fontSize="12px">
<Trans>Min Price</Trans>
</TYPE.main>
<TYPE.mediumHeader textAlign="center">{`${priceLower.toSignificant(5)}`}</TYPE.mediumHeader>
<TYPE.main
textAlign="center"
fontSize="12px"
>{` ${quoteCurrency.symbol}/${baseCurrency.symbol}`}</TYPE.main>
<TYPE.main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
Your position will be 100% composed of {baseCurrency?.symbol} at this price
<Trans>Your position will be 100% composed of {baseCurrency?.symbol} at this price</Trans>
</TYPE.small>
</AutoColumn>
</LightCard>
<LightCard width="48%" padding="8px">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">Max Price</TYPE.main>
<TYPE.main fontSize="12px">
<Trans>Max Price</Trans>
</TYPE.main>
<TYPE.mediumHeader textAlign="center">{`${priceUpper.toSignificant(5)}`}</TYPE.mediumHeader>
<TYPE.main
textAlign="center"
fontSize="12px"
>{` ${quoteCurrency.symbol}/${baseCurrency.symbol}`}</TYPE.main>
<TYPE.main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
<TYPE.small textAlign="center" color={theme.text3} style={{ marginTop: '4px' }}>
Your position will be 100% composed of {quoteCurrency?.symbol} at this price
<Trans>Your position will be 100% composed of {quoteCurrency?.symbol} at this price</Trans>
</TYPE.small>
</AutoColumn>
</LightCard>
</RowBetween>
<LightCard padding="12px ">
<AutoColumn gap="4px" justify="center">
<TYPE.main fontSize="12px">Current price</TYPE.main>
<TYPE.mediumHeader>{`${price.toSignificant(6)} `}</TYPE.mediumHeader>
<TYPE.main
textAlign="center"
fontSize="12px"
>{` ${quoteCurrency.symbol}/${baseCurrency.symbol}`}</TYPE.main>
<TYPE.main fontSize="12px">
<Trans>Current price</Trans>
</TYPE.main>
<TYPE.mediumHeader>{`${price.toSignificant(5)} `}</TYPE.mediumHeader>
<TYPE.main textAlign="center" fontSize="12px">
<Trans>
{quoteCurrency.symbol} per {baseCurrency.symbol}
</Trans>
</TYPE.main>
</AutoColumn>
</LightCard>
</AutoColumn>

View File

@@ -1,5 +1,5 @@
import React, { useContext } from 'react'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { AutoColumn } from '../Column'
import { ThemeContext } from 'styled-components'
import { TYPE } from '../../theme'

View File

@@ -1,5 +1,5 @@
import React, { useCallback, useState } from 'react'
import styled from 'styled-components'
import React, { ReactNode, useCallback, useState } from 'react'
import styled from 'styled-components/macro'
import Tooltip from '../Tooltip'
const QuestionWrapper = styled.div`
@@ -24,32 +24,11 @@ const QuestionWrapper = styled.div`
}
`
const LightQuestionWrapper = styled.div`
display: flex;
align-items: center;
justify-content: center;
padding: 0.2rem;
border: none;
background: none;
outline: none;
cursor: default;
border-radius: 36px;
width: 24px;
height: 24px;
background-color: rgba(255, 255, 255, 0.1);
color: ${({ theme }) => theme.white};
:hover,
:focus {
opacity: 0.7;
}
`
const QuestionMark = styled.span`
font-size: 14px;
`
export default function QuestionHelper({ text }: { text: string; size?: number }) {
export default function QuestionHelper({ text }: { text: ReactNode; size?: number }) {
const [show, setShow] = useState<boolean>(false)
const open = useCallback(() => setShow(true), [setShow])
@@ -65,20 +44,3 @@ export default function QuestionHelper({ text }: { text: string; size?: number }
</span>
)
}
export function LightQuestionHelper({ text }: { text: string }) {
const [show, setShow] = useState<boolean>(false)
const open = useCallback(() => setShow(true), [setShow])
const close = useCallback(() => setShow(false), [setShow])
return (
<span style={{ marginLeft: 4 }}>
<Tooltip text={text} show={show}>
<LightQuestionWrapper onClick={open} onMouseEnter={open} onMouseLeave={close}>
<QuestionMark>?</QuestionMark>
</LightQuestionWrapper>
</Tooltip>
</span>
)
}

View File

@@ -1,9 +1,8 @@
import { Trans } from '@lingui/macro'
import React from 'react'
import { Currency, Price } from '@uniswap/sdk-core'
import { Currency, Price, Token } from '@uniswap/sdk-core'
import StepCounter from 'components/InputStepCounter/InputStepCounter'
import { RowBetween } from 'components/Row'
import { useActiveWeb3React } from 'hooks'
import { wrappedCurrency } from 'utils/wrappedCurrency'
// currencyA is the base token
export default function RangeSelector({
@@ -19,8 +18,8 @@ export default function RangeSelector({
currencyB,
feeAmount,
}: {
priceLower?: Price
priceUpper?: Price
priceLower?: Price<Token, Token>
priceUpper?: Price<Token, Token>
getDecrementLower: () => string
getIncrementLower: () => string
getDecrementUpper: () => string
@@ -31,9 +30,8 @@ export default function RangeSelector({
currencyB?: Currency | null
feeAmount?: number
}) {
const { chainId } = useActiveWeb3React()
const tokenA = wrappedCurrency(currencyA ?? undefined, chainId)
const tokenB = wrappedCurrency(currencyB ?? undefined, chainId)
const tokenA = (currencyA ?? undefined)?.wrapped
const tokenB = (currencyB ?? undefined)?.wrapped
const isSorted = tokenA && tokenB && tokenA.sortsBefore(tokenB)
const leftPrice = isSorted ? priceLower : priceUpper?.invert()
@@ -49,7 +47,7 @@ export default function RangeSelector({
increment={isSorted ? getIncrementLower : getDecrementUpper}
feeAmount={feeAmount}
label={leftPrice ? `${currencyB?.symbol}` : '-'}
title={'Min Price'}
title={<Trans>Min Price</Trans>}
tokenA={currencyA?.symbol}
tokenB={currencyB?.symbol}
/>
@@ -63,7 +61,7 @@ export default function RangeSelector({
label={rightPrice ? `${currencyB?.symbol}` : '-'}
tokenA={currencyA?.symbol}
tokenB={currencyB?.symbol}
title={'Max Price'}
title={<Trans>Max Price</Trans>}
/>
</RowBetween>
)

View File

@@ -1,8 +1,7 @@
import { Trans } from '@lingui/macro'
import React from 'react'
import { Currency } from '@uniswap/sdk-core'
import { ToggleElement, ToggleWrapper } from 'components/Toggle/MultiToggle'
import { useActiveWeb3React } from 'hooks'
import { wrappedCurrency } from 'utils/wrappedCurrency'
// the order of displayed base currencies from left to right is always in sort order
// currencyA is treated as the preferred base currency
@@ -15,21 +14,19 @@ export default function RateToggle({
currencyB: Currency
handleRateToggle: () => void
}) {
const { chainId } = useActiveWeb3React()
const tokenA = wrappedCurrency(currencyA, chainId)
const tokenB = wrappedCurrency(currencyB, chainId)
const tokenA = currencyA?.wrapped
const tokenB = currencyB?.wrapped
const isSorted = tokenA && tokenB && tokenA.sortsBefore(tokenB)
return tokenA && tokenB ? (
<div style={{ width: 'fit-content', display: 'flex', alignItems: 'center' }}>
<div style={{ width: 'fit-content', display: 'flex', alignItems: 'center' }} onClick={handleRateToggle}>
<ToggleWrapper width="fit-content">
<ToggleElement isActive={isSorted} fontSize="12px" onClick={handleRateToggle}>
{isSorted ? currencyB.symbol + ' / ' + currencyA.symbol : currencyA.symbol + ' / ' + currencyB.symbol}{' '}
<ToggleElement isActive={isSorted} fontSize="12px">
<Trans>{isSorted ? currencyA.symbol : currencyB.symbol} price</Trans>
</ToggleElement>
<ToggleElement isActive={!isSorted} fontSize="12px" onClick={handleRateToggle}>
{isSorted ? currencyA.symbol + ' / ' + currencyB.symbol : currencyB.symbol + ' / ' + currencyA.symbol}
<ToggleElement isActive={!isSorted} fontSize="12px">
<Trans>{isSorted ? currencyB.symbol : currencyA.symbol} price</Trans>
</ToggleElement>
</ToggleWrapper>
</div>

View File

@@ -1,4 +1,4 @@
import styled from 'styled-components'
import styled from 'styled-components/macro'
import { Box } from 'rebass/styled-components'
const Row = styled(Box)<{

View File

@@ -1,9 +1,11 @@
import { Trans } from '@lingui/macro'
import React from 'react'
import { Text } from 'rebass'
import { ChainId, Currency, currencyEquals, Token, ETHER } from '@uniswap/sdk-core'
import styled from 'styled-components'
import { Currency } from '@uniswap/sdk-core'
import styled from 'styled-components/macro'
import { SUGGESTED_BASES } from '../../constants'
import { COMMON_BASES } from '../../constants/routing'
import { currencyId } from '../../utils/currencyId'
import { AutoColumn } from '../Column'
import QuestionHelper from '../QuestionHelper'
import { AutoRow } from '../Row'
@@ -21,8 +23,9 @@ const BaseWrapper = styled.div<{ disable?: boolean }>`
background-color: ${({ theme, disable }) => !disable && theme.bg2};
}
color: ${({ theme, disable }) => disable && theme.text3};
background-color: ${({ theme, disable }) => disable && theme.bg3};
opacity: ${({ disable }) => disable && '0.4'};
filter: ${({ disable }) => disable && 'grayscale(1)'};
`
export default function CommonBases({
@@ -30,44 +33,37 @@ export default function CommonBases({
onSelect,
selectedCurrency,
}: {
chainId?: ChainId
chainId?: number
selectedCurrency?: Currency | null
onSelect: (currency: Currency) => void
}) {
return (
const bases = typeof chainId !== 'undefined' ? COMMON_BASES[chainId] ?? [] : []
return bases.length > 0 ? (
<AutoColumn gap="md">
<AutoRow>
<Text fontWeight={500} fontSize={14}>
Common bases
<Trans>Common bases</Trans>
</Text>
<QuestionHelper text="These tokens are commonly paired with other tokens." />
<QuestionHelper text={<Trans>These tokens are commonly paired with other tokens.</Trans>} />
</AutoRow>
<AutoRow gap="4px">
<BaseWrapper
onClick={() => {
if (!selectedCurrency || !currencyEquals(selectedCurrency, ETHER)) {
onSelect(ETHER)
}
}}
disable={selectedCurrency === ETHER}
>
<CurrencyLogo currency={ETHER} style={{ marginRight: 8 }} />
<Text fontWeight={500} fontSize={16}>
ETH
</Text>
</BaseWrapper>
{(typeof chainId === 'number' ? SUGGESTED_BASES[chainId] ?? [] : []).map((token: Token) => {
const selected = selectedCurrency instanceof Token && selectedCurrency.address === token.address
{bases.map((currency: Currency) => {
const isSelected = selectedCurrency?.equals(currency)
return (
<BaseWrapper onClick={() => !selected && onSelect(token)} disable={selected} key={token.address}>
<CurrencyLogo currency={token} style={{ marginRight: 8 }} />
<BaseWrapper
onClick={() => !isSelected && onSelect(currency)}
disable={isSelected}
key={currencyId(currency)}
>
<CurrencyLogo currency={currency} style={{ marginRight: 8 }} />
<Text fontWeight={500} fontSize={16}>
{token.symbol}
{currency.symbol}
</Text>
</BaseWrapper>
)
})}
</AutoRow>
</AutoColumn>
)
) : null
}

View File

@@ -1,13 +1,15 @@
import { Currency, CurrencyAmount, currencyEquals, ETHER, Token } from '@uniswap/sdk-core'
import { Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'
import React, { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react'
import { FixedSizeList } from 'react-window'
import { Text } from 'rebass'
import styled from 'styled-components'
import { useActiveWeb3React } from '../../hooks'
import { WrappedTokenInfo, useCombinedActiveList } from '../../state/lists/hooks'
import styled from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks/web3'
import { useCombinedActiveList } from '../../state/lists/hooks'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
import { useCurrencyBalance } from '../../state/wallet/hooks'
import { TYPE } from '../../theme'
import { useIsUserAddedToken, useAllInactiveTokens } from '../../hooks/Tokens'
import { useIsUserAddedToken } from '../../hooks/Tokens'
import Column from '../Column'
import { RowFixed, RowBetween } from '../Row'
import CurrencyLogo from '../CurrencyLogo'
@@ -16,14 +18,13 @@ import { MenuItem } from './styleds'
import Loader from '../Loader'
import { isTokenOnList } from '../../utils'
import ImportRow from './ImportRow'
import { wrappedCurrency } from 'utils/wrappedCurrency'
import { LightGreyCard } from 'components/Card'
import TokenListLogo from '../../assets/svg/tokenlist.svg'
import QuestionHelper from 'components/QuestionHelper'
import useTheme from 'hooks/useTheme'
function currencyKey(currency: Currency): string {
return currency instanceof Token ? currency.address : currency === ETHER ? 'ETHER' : ''
return currency.isToken ? currency.address : 'ETHER'
}
const StyledBalanceText = styled(Text)`
@@ -55,7 +56,7 @@ const FixedContentRow = styled.div`
align-items: center;
`
function Balance({ balance }: { balance: CurrencyAmount }) {
function Balance({ balance }: { balance: CurrencyAmount<Currency> }) {
return <StyledBalanceText title={balance.toExact()}>{balance.toSignificant(4)}</StyledBalanceText>
}
@@ -103,17 +104,19 @@ function CurrencyRow({
isSelected,
otherSelected,
style,
showCurrencyAmount,
}: {
currency: Currency
onSelect: () => void
isSelected: boolean
otherSelected: boolean
style: CSSProperties
showCurrencyAmount?: boolean
}) {
const { account } = useActiveWeb3React()
const key = currencyKey(currency)
const selectedTokenList = useCombinedActiveList()
const isOnSelectedList = isTokenOnList(selectedTokenList, currency)
const isOnSelectedList = isTokenOnList(selectedTokenList, currency.isToken ? currency : undefined)
const customAdded = useIsUserAddedToken(currency)
const balance = useCurrencyBalance(account ?? undefined, currency)
@@ -132,95 +135,107 @@ function CurrencyRow({
{currency.symbol}
</Text>
<TYPE.darkGray ml="0px" fontSize={'12px'} fontWeight={300}>
{currency.name} {!isOnSelectedList && customAdded && '• Added by user'}
{!currency.isNative && !isOnSelectedList && customAdded ? (
<Trans>{currency.name} Added by user</Trans>
) : (
currency.name
)}
</TYPE.darkGray>
</Column>
<TokenTags currency={currency} />
<RowFixed style={{ justifySelf: 'flex-end' }}>
{balance ? <Balance balance={balance} /> : account ? <Loader /> : null}
</RowFixed>
{showCurrencyAmount && (
<RowFixed style={{ justifySelf: 'flex-end' }}>
{balance ? <Balance balance={balance} /> : account ? <Loader /> : null}
</RowFixed>
)}
</MenuItem>
)
}
const BREAK_LINE = 'BREAK'
type BreakLine = typeof BREAK_LINE
function isBreakLine(x: unknown): x is BreakLine {
return x === BREAK_LINE
}
function BreakLineComponent({ style }: { style: CSSProperties }) {
const theme = useTheme()
return (
<FixedContentRow style={style}>
<LightGreyCard padding="8px 12px" borderRadius="8px">
<RowBetween>
<RowFixed>
<TokenListLogoWrapper src={TokenListLogo} />
<TYPE.main ml="6px" fontSize="12px" color={theme.text1}>
<Trans>Expanded results from inactive Token Lists</Trans>
</TYPE.main>
</RowFixed>
<QuestionHelper
text={
<Trans>
Tokens from inactive lists. Import specific tokens below or click Manage to activate more lists.
</Trans>
}
/>
</RowBetween>
</LightGreyCard>
</FixedContentRow>
)
}
export default function CurrencyList({
height,
currencies,
otherListTokens,
selectedCurrency,
onCurrencySelect,
otherCurrency,
fixedListRef,
showETH,
showImportView,
setImportToken,
breakIndex,
showCurrencyAmount,
}: {
height: number
currencies: Currency[]
otherListTokens?: WrappedTokenInfo[]
selectedCurrency?: Currency | null
onCurrencySelect: (currency: Currency) => void
otherCurrency?: Currency | null
fixedListRef?: MutableRefObject<FixedSizeList | undefined>
showETH: boolean
showImportView: () => void
setImportToken: (token: Token) => void
breakIndex: number | undefined
showCurrencyAmount?: boolean
}) {
const itemData: (Currency | undefined)[] = useMemo(() => {
let formatted: (Currency | undefined)[] = showETH ? [Currency.ETHER, ...currencies] : currencies
if (breakIndex !== undefined) {
formatted = [...formatted.slice(0, breakIndex), undefined, ...formatted.slice(breakIndex, formatted.length)]
const itemData: (Currency | BreakLine)[] = useMemo(() => {
if (otherListTokens && otherListTokens?.length > 0) {
return [...currencies, BREAK_LINE, ...otherListTokens]
}
return formatted
}, [breakIndex, currencies, showETH])
const { chainId } = useActiveWeb3React()
const theme = useTheme()
const inactiveTokens: {
[address: string]: Token
} = useAllInactiveTokens()
return currencies
}, [currencies, otherListTokens])
const Row = useCallback(
({ data, index, style }) => {
const currency: Currency = data[index]
const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
const handleSelect = () => onCurrencySelect(currency)
function TokenRow({ data, index, style }) {
const row: Currency | BreakLine = data[index]
const token = wrappedCurrency(currency, chainId)
const showImport = inactiveTokens && token && Object.keys(inactiveTokens).includes(token.address)
if (index === breakIndex || !data) {
return (
<FixedContentRow style={style}>
<LightGreyCard padding="8px 12px" borderRadius="8px">
<RowBetween>
<RowFixed>
<TokenListLogoWrapper src={TokenListLogo} />
<TYPE.main ml="6px" fontSize="12px" color={theme.text1}>
Expanded results from inactive Token Lists
</TYPE.main>
</RowFixed>
<QuestionHelper text="Tokens from inactive lists. Import specific tokens below or click 'Manage' to activate more lists." />
</RowBetween>
</LightGreyCard>
</FixedContentRow>
)
if (isBreakLine(row)) {
return <BreakLineComponent style={style} />
}
const currency = row
const isSelected = Boolean(currency && selectedCurrency && selectedCurrency.equals(currency))
const otherSelected = Boolean(currency && otherCurrency && otherCurrency.equals(currency))
const handleSelect = () => currency && onCurrencySelect(currency)
const token = currency?.wrapped
const showImport = index > currencies.length
if (showImport && token) {
return (
<ImportRow
style={style}
token={token}
showImportView={showImportView}
setImportToken={setImportToken}
dim={true}
/>
<ImportRow style={style} token={token} showImportView={showImportView} setImportToken={setImportToken} dim />
)
} else {
} else if (currency) {
return (
<CurrencyRow
style={style}
@@ -228,24 +243,29 @@ export default function CurrencyList({
isSelected={isSelected}
onSelect={handleSelect}
otherSelected={otherSelected}
showCurrencyAmount={showCurrencyAmount}
/>
)
} else {
return null
}
},
[
chainId,
inactiveTokens,
currencies.length,
onCurrencySelect,
otherCurrency,
selectedCurrency,
setImportToken,
showImportView,
breakIndex,
theme.text1,
showCurrencyAmount,
]
)
const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
const itemKey = useCallback((index: number, data: typeof itemData) => {
const currency = data[index]
if (isBreakLine(currency)) return BREAK_LINE
return currencyKey(currency)
}, [])
return (
<FixedSizeList

View File

@@ -1,11 +1,12 @@
import { Currency, ETHER, Token } from '@uniswap/sdk-core'
import { Currency, Token } from '@uniswap/sdk-core'
import React, { KeyboardEvent, RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import ReactGA from 'react-ga'
import { useTranslation } from 'react-i18next'
import { t, Trans } from '@lingui/macro'
import { FixedSizeList } from 'react-window'
import { Text } from 'rebass'
import { useActiveWeb3React } from '../../hooks'
import { useAllTokens, useToken, useIsUserAddedToken, useFoundOnInactiveList } from '../../hooks/Tokens'
import { ExtendedEther } from '../../constants/tokens'
import { useActiveWeb3React } from '../../hooks/web3'
import { useAllTokens, useToken, useIsUserAddedToken, useSearchInactiveTokenLists } from '../../hooks/Tokens'
import { CloseIcon, TYPE, ButtonText, IconWrapper } from '../../theme'
import { isAddress } from '../../utils'
import Column from '../Column'
@@ -16,7 +17,7 @@ import { filterTokens, useSortedTokensByQuery } from './filtering'
import { useTokenComparator } from './sorting'
import { PaddedColumn, SearchInput, Separator } from './styleds'
import AutoSizer from 'react-virtualized-auto-sizer'
import styled from 'styled-components'
import styled from 'styled-components/macro'
import useToggle from 'hooks/useToggle'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
import useTheme from 'hooks/useTheme'
@@ -47,6 +48,8 @@ interface CurrencySearchProps {
onCurrencySelect: (currency: Currency) => void
otherSelectedCurrency?: Currency | null
showCommonBases?: boolean
showCurrencyAmount?: boolean
disableNonToken?: boolean
showManageView: () => void
showImportView: () => void
setImportToken: (token: Token) => void
@@ -57,13 +60,14 @@ export function CurrencySearch({
onCurrencySelect,
otherSelectedCurrency,
showCommonBases,
showCurrencyAmount,
disableNonToken,
onDismiss,
isOpen,
showManageView,
showImportView,
setImportToken,
}: CurrencySearchProps) {
const { t } = useTranslation()
const { chainId } = useActiveWeb3React()
const theme = useTheme()
@@ -94,11 +98,6 @@ export function CurrencySearch({
}
}, [isAddressSearch])
const showETH: boolean = useMemo(() => {
const s = debouncedQuery.toLowerCase().trim()
return s === '' || s === 'e' || s === 'et' || s === 'eth'
}, [debouncedQuery])
const tokenComparator = useTokenComparator(invertSearchOrder)
const filteredTokens: Token[] = useMemo(() => {
@@ -111,6 +110,16 @@ export function CurrencySearch({
const filteredSortedTokens = useSortedTokensByQuery(sortedTokens, debouncedQuery)
const ether = useMemo(() => chainId && ExtendedEther.onChain(chainId), [chainId])
const filteredSortedTokensWithETH: Currency[] = useMemo(() => {
const s = debouncedQuery.toLowerCase().trim()
if (s === '' || s === 'e' || s === 'et' || s === 'eth') {
return ether ? [ether, ...filteredSortedTokens] : filteredSortedTokens
}
return filteredSortedTokens
}, [debouncedQuery, ether, filteredSortedTokens])
const handleCurrencySelect = useCallback(
(currency: Currency) => {
onCurrencySelect(currency)
@@ -137,19 +146,19 @@ export function CurrencySearch({
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
const s = debouncedQuery.toLowerCase().trim()
if (s === 'eth') {
handleCurrencySelect(ETHER)
} else if (filteredSortedTokens.length > 0) {
if (s === 'eth' && ether) {
handleCurrencySelect(ether)
} else if (filteredSortedTokensWithETH.length > 0) {
if (
filteredSortedTokens[0].symbol?.toLowerCase() === debouncedQuery.trim().toLowerCase() ||
filteredSortedTokens.length === 1
filteredSortedTokensWithETH[0].symbol?.toLowerCase() === debouncedQuery.trim().toLowerCase() ||
filteredSortedTokensWithETH.length === 1
) {
handleCurrencySelect(filteredSortedTokens[0])
handleCurrencySelect(filteredSortedTokensWithETH[0])
}
}
}
},
[filteredSortedTokens, handleCurrencySelect, debouncedQuery]
[debouncedQuery, ether, filteredSortedTokensWithETH, handleCurrencySelect]
)
// menu ui
@@ -158,15 +167,16 @@ export function CurrencySearch({
useOnClickOutside(node, open ? toggle : undefined)
// if no results on main list, show option to expand into inactive
const inactiveTokens = useFoundOnInactiveList(debouncedQuery)
const filteredInactiveTokens: Token[] = useSortedTokensByQuery(inactiveTokens, debouncedQuery)
const filteredInactiveTokens = useSearchInactiveTokenLists(
filteredTokens.length === 0 || (debouncedQuery.length > 2 && !isAddressSearch) ? debouncedQuery : undefined
)
return (
<ContentWrapper>
<PaddedColumn gap="16px">
<RowBetween>
<Text fontWeight={500} fontSize={16}>
Select a token
<Trans>Select a token</Trans>
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
@@ -174,7 +184,7 @@ export function CurrencySearch({
<SearchInput
type="text"
id="token-search-input"
placeholder={t('tokenSearchPlaceholder')}
placeholder={t`Search name or paste address`}
autoComplete="off"
value={searchQuery}
ref={inputRef as RefObject<HTMLInputElement>}
@@ -197,17 +207,15 @@ export function CurrencySearch({
{({ height }) => (
<CurrencyList
height={height}
showETH={showETH}
currencies={
filteredInactiveTokens ? filteredSortedTokens.concat(filteredInactiveTokens) : filteredSortedTokens
}
breakIndex={inactiveTokens && filteredSortedTokens ? filteredSortedTokens.length : undefined}
currencies={disableNonToken ? filteredSortedTokens : filteredSortedTokensWithETH}
otherListTokens={filteredInactiveTokens}
onCurrencySelect={handleCurrencySelect}
otherCurrency={otherSelectedCurrency}
selectedCurrency={selectedCurrency}
fixedListRef={fixedList}
showImportView={showImportView}
setImportToken={setImportToken}
showCurrencyAmount={showCurrencyAmount}
/>
)}
</AutoSizer>
@@ -215,18 +223,20 @@ export function CurrencySearch({
) : (
<Column style={{ padding: '20px', height: '100%' }}>
<TYPE.main color={theme.text3} textAlign="center" mb="20px">
No results found.
<Trans>No results found.</Trans>
</TYPE.main>
</Column>
)}
<Footer>
<Row justify="center">
<ButtonText onClick={showManageView} color={theme.blue1} className="list-token-manage-button">
<ButtonText onClick={showManageView} color={theme.primary1} className="list-token-manage-button">
<RowFixed>
<IconWrapper size="16px" marginRight="6px">
<IconWrapper size="16px" marginRight="6px" stroke={theme.primaryText1}>
<Edit />
</IconWrapper>
<TYPE.main color={theme.blue1}>Manage Token Lists</TYPE.main>
<TYPE.main color={theme.primaryText1}>
<Trans>Manage Token Lists</Trans>
</TYPE.main>
</RowFixed>
</ButtonText>
</Row>

View File

@@ -1,6 +1,7 @@
import { Currency, Token } from '@uniswap/sdk-core'
import React, { useCallback, useEffect, useState } from 'react'
import useLast from '../../hooks/useLast'
import { WrappedTokenInfo } from '../../state/lists/wrappedTokenInfo'
import Modal from '../Modal'
import { CurrencySearch } from './CurrencySearch'
import { ImportToken } from './ImportToken'
@@ -16,6 +17,8 @@ interface CurrencySearchModalProps {
onCurrencySelect: (currency: Currency) => void
otherSelectedCurrency?: Currency | null
showCommonBases?: boolean
showCurrencyAmount?: boolean
disableNonToken?: boolean
}
export enum CurrencyModalView {
@@ -32,6 +35,8 @@ export default function CurrencySearchModal({
selectedCurrency,
otherSelectedCurrency,
showCommonBases = false,
showCurrencyAmount = true,
disableNonToken = false,
}: CurrencySearchModalProps) {
const [modalView, setModalView] = useState<CurrencyModalView>(CurrencyModalView.manage)
const lastOpen = useLast(isOpen)
@@ -73,6 +78,8 @@ export default function CurrencySearchModal({
selectedCurrency={selectedCurrency}
otherSelectedCurrency={otherSelectedCurrency}
showCommonBases={showCommonBases}
showCurrencyAmount={showCurrencyAmount}
disableNonToken={disableNonToken}
showImportView={() => setModalView(CurrencyModalView.importToken)}
setImportToken={setImportToken}
showManageView={() => setModalView(CurrencyModalView.manage)}
@@ -81,6 +88,7 @@ export default function CurrencySearchModal({
<ImportToken
tokens={[importToken]}
onDismiss={onDismiss}
list={importToken instanceof WrappedTokenInfo ? importToken.list : undefined}
onBack={() =>
setModalView(prevView && prevView !== CurrencyModalView.importToken ? prevView : CurrencyModalView.search)
}

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