Compare commits

..

271 Commits

Author SHA1 Message Date
Ian Lapham
72678ee667 Update token list (#3520) 2022-03-15 10:53:20 -04:00
Zach Pomerantz
4dd74f2144 fix: token img overflow (#3517) 2022-03-15 08:01:32 -05:00
Zach Pomerantz
e45c104135 fix: computed token img (#3519) 2022-03-15 08:00:46 -05:00
Crowdin Bot
98fcaacd9b chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-15 09:06:57 +00:00
Crowdin Bot
93551579e4 chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-14 20:11:46 +00:00
Zach Pomerantz
8a9388ed81 feat: make Expando element (#3515)
* feat: make Expando element

* fix: cleanup

* fix: simplify margin

* fix: summary height

* fix: special case gap transition
2022-03-14 12:03:40 -07:00
Ian Lapham
884bf41da7 fix: add check for undefined slot0 and liquidity call results (#3513)
* add check for undefined slot0 and liquidity call results

* update null check

* update code order
2022-03-14 14:02:03 -04:00
Zach Pomerantz
5b686aea97 fix: exhaustive dep (#3514) 2022-03-14 10:03:19 -07:00
Zach Pomerantz
c4a456a085 chore: simplify Price in its own component (#3508)
* chore: simplify Price in its own component

* fix: restore reversal

* fix: output usdc naming
2022-03-14 09:54:04 -07:00
Zach Pomerantz
4b9098a7bf fix: token button overflow (#3504)
Removes the overflow property from TokenButton, which prevents the vertical scrollbar from rendering.
2022-03-14 09:42:38 -07:00
Zach Pomerantz
71a246f25c fix: expando icon direction (#3507) 2022-03-14 09:42:24 -07:00
Zach Pomerantz
8de048bc84 fix: input amount lag (#3503)
Propagates the exact amount to the trade currency amount without waiting for the trade to be computed. This allows things like insufficient balance or approval to be reflected in the UI while typing, instead of having a lag.
2022-03-13 22:45:14 -07:00
Zach Pomerantz
163e2d5560 fix: override Rule width (#3502)
* fix: override Rule width

* fix: include max-width
2022-03-11 17:26:02 -06:00
Zach Pomerantz
0edb0fe5e2 fix: memoize on-chain results (#3493)
* fix: memo-ize onchain results

* fix: typeof omission
2022-03-11 14:56:05 -08:00
Zach Pomerantz
496408b3db fix: token list fetching performance (#3480)
* fix: token list fetching

* fix: simplify naming
2022-03-11 11:57:49 -08:00
Zach Pomerantz
78b6f5c72d fix: destructure currencies for ref equality (#3498) 2022-03-11 11:25:17 -08:00
Zach Pomerantz
f9fb71a803 fix(perf): cache pools to avoid cost of instantiation (#3499) 2022-03-11 08:20:16 -08:00
Crowdin Bot
59d0046411 chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-11 03:07:34 +00:00
Zach Pomerantz
b4e0234d07 fix: avoid summary wrap (#3497) 2022-03-10 15:59:45 -08:00
Zach Pomerantz
4a8dbda0b8 fix: memoize nested components (#3483) 2022-03-10 15:48:45 -08:00
Crowdin Bot
0cbb24c614 chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-10 23:06:32 +00:00
Ian Lapham
a9dba258ff fix: update wrap fail state callback and input values (#3495)
* update wrap fail state callback and input values

* add error check for wrap status

* update error catching logic

* update error catching
2022-03-10 17:07:52 -05:00
Zach Pomerantz
fa163cb938 feat: price impact update (#3496)
* feat: green text on neg price impact

* chore: propagate all of usdc price impact

* chore: pass price impact to summary details

* chore: propagate slippage and impact warnings

* feat: update warnings on summary dialog

* chore: rm todo
2022-03-10 13:07:37 -08:00
Curly Brackets
b52273932a fix(ui): Auto Router icon not appearing on safari/ios (#3444)
* fix(ui): Auto Router icon not appearing on safari/ios

Closes #3138

* refactor: remove auto-router svg that are no longer in use
2022-03-10 14:37:32 -05:00
Crowdin Bot
9ad8f80e4e chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-10 18:07:32 +00:00
Zach Pomerantz
69bc598dea feat: display "no results found" message (#3467)
* feat: display when no results

* chore: use body not subhead
2022-03-10 09:53:56 -08:00
Ian Lapham
7feba045fc fix: add formatting to USDC values (#3478)
* add formatting to USDC values

* update formatting of USDC amounts to en

* apply same formatting to summary
2022-03-10 12:38:59 -05:00
Zach Pomerantz
04cee0a07d chore: bump to v0.0.23-beta (#3492) 2022-03-10 09:02:17 -08:00
Zach Pomerantz
ea73260e56 fix: accomodate longer locales (#3468) 2022-03-10 08:57:36 -08:00
Zach Pomerantz
b4bd2973a9 fix: update input when prefixing 0 to decimal (#3487) 2022-03-10 08:56:06 -08:00
Zach Pomerantz
a071b8adb0 fix: summary line break (#3486) 2022-03-10 08:55:55 -08:00
Zach Pomerantz
610acb0191 fix: font family overrides (#3485) 2022-03-10 08:55:40 -08:00
Zach Pomerantz
63bad8f890 fix: summary expando height (#3484) 2022-03-10 08:54:42 -08:00
Zach Pomerantz
32f955693f fix: restructure web3 to memoize (#3472) 2022-03-09 15:08:04 -08:00
Zach Pomerantz
96c66a5846 fix: incorrectly memoized hooks (#3471)
* fix: incorrectly memoized hooks

* fix: finish memoizing useUSDCPrice
2022-03-09 12:33:35 -08:00
Sara Reynolds
8c269a6d39 feat: add optimism and arbitrum to gas estimate support (#3434)
* add optimism and arbitrum to gas estimate support

* update sor version

* move to dependencies
2022-03-09 14:52:19 -05:00
Justin Domingue
36f111fa6f chore: upgrade to redux-toolkit 1.8 (#3464) 2022-03-09 12:19:24 -05:00
Ian Lapham
e569dc2152 fix: update default tokens on unsupported networks (#3470)
* update default tokens on unsupported networks

* update supported network with hook

* update defaults

* fix on default input token
2022-03-08 20:35:23 -05:00
Crowdin Bot
1aa042c5ef chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-08 21:07:02 +00:00
Zach Pomerantz
1450315b98 chore: bump to v0.0.21-beta (#3466) 2022-03-08 09:54:59 -08:00
Zach Pomerantz
aefbb3d812 feat: price impact warning (#3437)
* chore: mv usdc price impact to hook

* fix: popover padding

* feat: warn on high price impact from toolbar

* fix: display price impact on warning too

* chore: rename useUSDCValue params

* fix: conform uses of price impact color
2022-03-08 09:53:40 -08:00
Moody Salem
c3f12398cd fix: reverts the defaulting behavior of 1 eth to usdc (#3465) 2022-03-08 11:31:52 -05:00
Zach Pomerantz
2272f2a01a chore: specify a module for CRAv4 (#3462) 2022-03-08 08:19:56 -08:00
Zach Pomerantz
fb71078ea2 fix: fully specify locales (#3461) 2022-03-08 08:19:31 -08:00
Zach Pomerantz
1c7c93191e fix: default input to native currency (#3456)
* fix: default to native

* chore: fix import
2022-03-08 08:19:23 -08:00
Zach Pomerantz
0713f730b3 fix: widget sizing (#3455) 2022-03-08 08:19:12 -08:00
Crowdin Bot
5f7a18b411 chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-08 16:07:25 +00:00
Curly Brackets
020c8d181a fix(ui): display wrapped currency symbol with current chain (#3441) 2022-03-08 09:06:31 -06:00
Zach Pomerantz
ab3f024031 fix: display loaded input amount (#3451) 2022-03-08 08:57:51 -06:00
Ian Lapham
d989c61de5 fix: update type on wrapped native currency (#3454)
* update wrapped native currency type

* fix build error on base check

* update type on mapping to permit undefined values

* undo unneeded changes

* update filter check
2022-03-07 21:04:21 -05:00
Zach Pomerantz
5dd8059734 fix: routing tooltip styles (#3459) 2022-03-07 15:08:01 -08:00
Zach Pomerantz
b50e5511ea chore: update loading colors (#3438)
* chore: update loading colors

* fix: loading opacity of 0.6
2022-03-07 09:40:15 -08:00
Crowdin Bot
1efe5e9cd5 chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-06 15:06:35 +00:00
Zach Pomerantz
2944dc4d0b chore: bump to v0.0.21-beta (#3439) 2022-03-04 14:30:25 -08:00
Jordan Frankfurt
29ae755f2a add new token image to widget (#3433) 2022-03-04 11:14:31 -06:00
Zach Pomerantz
27b831b301 chore: convert inline spinner to svg (#3432)
* chore: convert inline spinner to svg

* feat: inline spinner outline
2022-03-04 08:59:09 -08:00
Ian Lapham
6d9d38819e feat: update loading icon (#3428)
* update loading icon

* color update, update file for spinner

* update loader styling size

* update file naming for spinner
2022-03-04 11:07:02 -05:00
Zach Pomerantz
2de29129ed feat: export types (#3411)
* feat: export used types

* fix: clean defaulting names

* chore: rename to useSyncTokenDefaults
2022-03-03 14:21:03 -08:00
Crowdin Bot
52af0e506b chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-03 22:07:03 +00:00
Noah Zinsmeister
4d69c946bf fix: Improve Vote page (#3429)
* introduce useQuorum

introduce LATEST_GOVERNOR_INDEX

* use CurrencyAmounts and fix % logic

* gate useQuorum to mainnet, just to be safe

* comment
2022-03-03 16:27:59 -05:00
Zach Pomerantz
542bf0bf66 feat: user select (#3410)
* feat: make data user-selectable

* fix: consider the whole node for focus

* fix: back out lineheight typing

* fix: straggling occurences

* chore: comment on root user-select
2022-03-03 11:09:12 -08:00
Zach Pomerantz
a4fbfae4ba fix: set appropriate types to nowrap (#3392) 2022-03-03 10:39:44 -08:00
Crowdin Bot
b2288258f2 chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-03 18:11:42 +00:00
Ian Lapham
8703013b2d feat: use permit when valid on approvals (#3354)
* use permit when valid on approvals

* fix broken check for permit sig

* update conditionals

* update text

* remove unneeded else

* move permit and approve logic to combined hook

* update comment

* split txn and approval state, code clean

* organize disable conditions

* small changes

* update conditional check
2022-03-03 12:28:36 -05:00
Crowdin Bot
4f6173675d chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-03 09:11:25 +00:00
Crowdin Bot
2469eb58b9 chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-03 07:14:57 +00:00
Crowdin Bot
e0a8ac2408 chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-02 23:26:37 +00:00
Ian Lapham
0a736b5e62 feat: create donation banner (#3403)
* create donation banner

* update styling and copy

* only show banner on swap page

* dont use hard coded z index

* style updates
2022-03-02 17:48:12 -05:00
Jordan Frankfurt
b44eb8877c chore(widgets): export theme stuff from widget (#3409) 2022-03-02 14:20:55 -08:00
Zach Pomerantz
92e61fa34b fix: token balance reloading (#3408)
* fix: layout token balance on token select

* fix: do not clear block on window re-focus
2022-03-02 13:39:18 -08:00
Zach Pomerantz
ef62fd33b2 fix: error dialog transition (#3405) 2022-03-02 13:37:57 -08:00
Jordan Frankfurt
96a42f66d4 fix(widgets): disable interactions and don't show summary screen on unsupported networks (#3376)
* disable interactions and don't show summary screen on unsupported networks

* clear input values on unsupported network

* pr feedback

* pr feedback

* simpler active trade clearing

* rename some things
2022-03-02 13:45:31 -06:00
Crowdin Bot
c446f20d2f chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-02 19:11:16 +00:00
Jordan Frankfurt
5a1ef8fb7d feat(widgets): support wrapping native assets (#3301)
* feat(widgets): support wrapping native assets

* integrate wrap with swapInfo, start a useWrapCallback hook

* add loading state

* add pending state to (un)wrap transactions

* final cleanup

* janky merge conflict fix--disregard! this will change

* fixed

* 💢

* pr feedback

* z's pr feedback

* pr feedback

* zzmp pr feedback

* zzmp pr feedback
2022-03-02 12:36:35 -06:00
Zach Pomerantz
2863971640 fix: routing tooltip sizing (#3391) 2022-03-02 08:54:15 -08:00
Crowdin Bot
dcaf10ec29 chore(i18n): synchronize translations from crowdin [skip ci] 2022-03-02 07:31:50 +00:00
Zach Pomerantz
bca5113569 fix: connect wallet button (#3324)
* fix: make dialog provider an isolate

* fix: use button for connect wallet

* chore: document esoteric changes
2022-03-01 14:32:54 -08:00
David Walsh
6779c1a024 Fix #3117 - Open networks menu upon hover (#3378) 2022-03-01 14:45:22 -05:00
Ori Pomerantz
f79ef12494 fix(icons): Updated one of the Optimism images (#3357) 2022-03-01 14:37:18 -05:00
dependabot[bot]
7bcda46934 chore(deps): bump url-parse from 1.5.3 to 1.5.10 (#3371)
Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.5.3 to 1.5.10.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.5.3...1.5.10)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-01 14:35:54 -05:00
dependabot[bot]
f4ba24cfd5 chore(deps): bump nanoid from 3.1.28 to 3.2.0 (#3173)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.1.28 to 3.2.0.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.1.28...3.2.0)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-01 14:35:01 -05:00
Zach Pomerantz
59c6ab16dd fix: exports (#3379)
* fix: cjs in cra

* chore: wrap cjs for mjs

* chore: export cjs and esm

* chore: export chunks

* fix: correctly export locales

* chore: note exports compat

* fix: use cjs for common deps

* chore: bump to v0.0.20-beta

* chore: rm outdated comment
2022-03-01 11:32:55 -08:00
Ian Lapham
db17dcbf2c list update (#3389) 2022-03-01 14:05:13 -05:00
Moody Salem
1835de7f5f fix: the vote page could not render proposals without signature data
fixes https://github.com/Uniswap/interface/issues/3380
2022-02-28 18:16:24 -05:00
Crowdin Bot
00f158209c chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-28 19:11:43 +00:00
Zach Pomerantz
2108ceedd5 chore: reduce token list block period (#3353) 2022-02-28 10:47:36 -08:00
Zach Pomerantz
ad080470da fix: use explicit value in Plural tag (#3363)
one is non-functional (I don't know why), but _1 seems to work 🤷
2022-02-28 10:41:15 -08:00
Moody Salem
fc34912b53 feat(swap): default 1 native to usdc on the swap page (#3347)
* feat(swap): default 1 eth to usdc on the swap page

* fix unit tests

* fix tests

* fix the issue better

* use the token list logo

* fix integration tests for swap and add one for eth/usdc

* address comments
2022-02-28 13:30:37 -05:00
jaclyn
c25d2b894c fix: update walletlink-connector to 6.2.13 (#3315)
* fix: update walletlink-connector to 6.2.12

* fix: update walletlink-connector to 6.2.13

Co-authored-by: Jaclyn Chan <jaclyn.chan@coinbase.com>
2022-02-28 11:13:36 -05:00
Moody Salem
83c99b8c04 chore: remove unused exports and unused integration test build env variable 2022-02-28 11:03:05 -05:00
Zach Pomerantz
ccdf1e7575 fix: convert to commonjs (#3373)
* chore: use fully specified path for non-main imports

* chore: convert to commonjs

- Pin @web3-react to exact cjs versions

* chore: bump to v0.0.18-beta

* chore: fix fonts.css comment

* fix: @ethersproject/providers version skew

* fix: @web3-react state typings
2022-02-28 07:52:22 -08:00
Crowdin Bot
c9faafee5e chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-25 08:08:05 +00:00
Zach Pomerantz
26a44fb51b chore: bump to v0.0.15-beta (#3358) 2022-02-24 11:36:00 -08:00
Zach Pomerantz
1e16ac8449 fix: wrap Eip1193Bridge to fix outstanding bugs (#3355)
* fix: wrap Eip1193Bridge to fix outstanding bugs

* revert: widget height change
2022-02-24 11:20:09 -08:00
Crowdin Bot
5b5e76573d chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-24 09:06:47 +00:00
Crowdin Bot
27cdbd0d5f chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-23 23:06:39 +00:00
Zach Pomerantz
b2a30b9bf1 fix: style nits (#3352)
* fix: prefix output usdc with $

* fix: space in output estimate warning

* fix: reset slippage warnings

* fix: display link icon for etherscan
2022-02-23 14:56:49 -08:00
Zach Pomerantz
dfad7b89ab chore: nextjs compatibility (#3351)
* fix: esm/cjs exports

* fix: guard visibility state WebAPI

* fix: nextjs styled-components imports

* fix: add ethers' optional deps

* fix: document access in useHasFocus

* fix: suffix babel-plugin-macros config for commonjs

* chore: rollup sourcemaps

* chore: export fonts separately

* chore: mv redux to peer dep

* fix: run tests off cjs config

* fix: run cosmos off cjs config
2022-02-23 13:12:07 -08:00
Zach Pomerantz
4fe35ea42e fix: max on WebKit (#3349)
* chore: add walletconnect to cosmos

* fix: onClickMax for TokenInput

* chore: add setImmediate
2022-02-23 12:50:22 -08:00
Zach Pomerantz
0d852b6165 fix: apply user-select to widget, not to constituents (#3345) 2022-02-23 12:49:59 -08:00
Zach Pomerantz
8ac3b836bd fix: slippage input size (#3350) 2022-02-23 12:25:17 -08:00
Crowdin Bot
12bc5957b4 chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-23 20:06:40 +00:00
Ian Lapham
a33187c33b feat: routing tooltip for widget (#3259)
* start file updates for routing tooltip

* start tooltip UI

* fix styling

* remove use of px and add header

* UI updates;

* update styles

* update file structure

* update routing components and type

* small code fixes

* fix broken sizing bug

* nit fixes
2022-02-23 14:22:21 -05:00
Zach Pomerantz
248bc07cf1 fix: lazily instantiate supported router providers (#3348)
* fix: iterate over enum values

* fix: lazily instantiate router providers
2022-02-23 10:46:29 -08:00
Crowdin Bot
369f8c94e3 chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-18 00:13:06 +00:00
Crowdin Bot
de5f0541ee chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-17 23:07:10 +00:00
Zach Pomerantz
48b3efc612 chore: bump to v0.0.14-beta (#3333) 2022-02-17 12:03:44 -08:00
Zach Pomerantz
90c59f31f3 fix: return eip1193bridge chainId as hexa (#3332) 2022-02-17 12:03:35 -08:00
Zach Pomerantz
0e709c257b fix: import fonts through sass only (#3331) 2022-02-17 10:49:47 -08:00
Crowdin Bot
7a3bb8de1d chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-17 18:09:07 +00:00
Crowdin Bot
8018d1b9dc chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-17 15:11:21 +00:00
Zach Pomerantz
1297aa57d3 chore: bump to v0.0.13-beta (#3328) 2022-02-16 17:00:43 -08:00
Zach Pomerantz
30e30189e1 fix: use a void signer for ethers providers (#3327) 2022-02-16 17:00:31 -08:00
Zach Pomerantz
6a602cf6d7 chore: bump to v0.0.12-beta (#3325) 2022-02-16 14:17:41 -08:00
Zach Pomerantz
4c966caa2a feat: accept {provider, signer} as ethers provider (#3314) 2022-02-16 11:11:45 -08:00
Zach Pomerantz
a60ea703b0 fix: token select ux (#3321) 2022-02-16 11:11:10 -08:00
Zach Pomerantz
ae664dc264 fix: compute insufficient balance and approval off of input (#3312) 2022-02-16 11:10:40 -08:00
Zach Pomerantz
b152b11515 fix: token select input handling (#3303) 2022-02-15 19:35:14 -08:00
Zach Pomerantz
0f51991109 feat: improved warning ux (#3310) 2022-02-15 19:34:02 -08:00
Zach Pomerantz
da8884d87d fix: action prop warning (#3304) 2022-02-15 19:33:29 -08:00
Zach Pomerantz
79bdc0c5ee fix: summary details heights (#3302) 2022-02-15 19:33:09 -08:00
Zach Pomerantz
82c30681ea fix: ignore stale SOR fetches (#3313)
* fix: propagate ROUTE_NOT_FOUND and fallback appropriately

* fix: display insufficient liquidities

* fix: ignore stale SOR results

* fix: retain trade state while loading

* fix: mv debouncing to SOR logic for sync state
2022-02-14 18:23:55 -08:00
Ian Lapham
41ef961679 feat: optimize client side SOR for widgets (#3294)
* start SOR updates

* update pool providers to static

* update router config

* remove log

* udpate defaults for chainId

* small changes
2022-02-14 13:35:05 -07:00
Zach Pomerantz
7de63ab462 feat: focus and hover hooks (#3287)
* feat: add focus/hover hooks

* refactor: use focus/hover hooks
2022-02-14 06:32:11 -08:00
Crowdin Bot
59c5989721 chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-12 15:07:37 +00:00
Zach Pomerantz
b042d2b3b4 fix: i18n resolution (#3299) 2022-02-11 10:34:03 -08:00
Zach Pomerantz
897e7f4581 fix: approval action button (#3297) 2022-02-11 08:47:45 -08:00
Zach Pomerantz
a7fb7dc906 chore: v0.0.11-beta 2022-02-11 08:13:06 -08:00
Crowdin Bot
5fe89b9d6c chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-11 04:07:20 +00:00
Zach Pomerantz
acbcd3763c style: update type sizes (#3292) 2022-02-10 20:37:58 -07:00
Zach Pomerantz
01c467b48c fix: max button flashing on tabbing (#3291) 2022-02-10 20:37:13 -07:00
Zach Pomerantz
636abe3b7b fix: respond to updated amounts immediately (#3289) 2022-02-10 20:35:34 -07:00
Zach Pomerantz
8404c6076c feat: confirm price impact (#3288)
* refactor: action button naming

* feat: high price impact acknowledgement
2022-02-10 20:33:51 -07:00
Zach Pomerantz
b4aac94c2c fix: settings ux (#3282)
* fix: max slippage warning logic

* fix: option border specificity

* fix: dialog resizing through animation

* fix: initial warning states

* fix: hide Modal class
2022-02-10 14:22:54 -08:00
Zach Pomerantz
f47fcc9c17 feat: focus input on token select (#3286) 2022-02-10 14:12:24 -08:00
Crowdin Bot
b5d27e2063 chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-10 22:06:48 +00:00
Jordan Frankfurt
26275ca580 fix(widgets): remove trading header (#3263)
* fix(widgets): remove trading header

* correct height for removed title, more scalable/consistent transform values

* 347->346 height
2022-02-10 15:59:26 -06:00
Zach Pomerantz
92b7ca8f55 feat: hide balance on blur (#3285)
* feat: hide balance when blurred

* refactor: express focused through props

* refactor: share Input/Output code
2022-02-10 13:39:08 -08:00
Jordan Frankfurt
c5ea01ce19 fix(widgets): complete etherscan link and stop timer on tx inclusion (#3267)
* fix(widgets): complete etherscan link and stop timer on tx inclusion

* use preexisting helper for etherscan link

* use z's EtherscanLink component

* pr review
2022-02-10 15:35:19 -06:00
Ian Lapham
88712b5065 fix: adjust max button for native currencies (#3279)
* adjust max button for native currencies

* update var naming
2022-02-10 12:54:01 -08:00
Zach Pomerantz
1af34ae016 feat: EtherscanA component (#3284)
* feat: EtherscanA component

* refactor: EtherscanLink from ExternalLink
2022-02-10 09:14:54 -08:00
Zach Pomerantz
9cb19dd0ea fix: filter integrator fee (#3281) 2022-02-10 08:51:39 -08:00
Zach Pomerantz
02a77254c7 fix: retain sig figs in localized nums (#3280) 2022-02-10 08:51:29 -08:00
Zach Pomerantz
69ed7015ab chore: clean up old generated css (#3277) 2022-02-10 08:51:18 -08:00
Zach Pomerantz
ff16d3f18f fix: theme colors (#3274) 2022-02-10 08:51:11 -08:00
Zach Pomerantz
5175cb6d1f fix: leave intermediate artifacts in watch (#3272) 2022-02-10 08:50:56 -08:00
Zach Pomerantz
b33686855d fix: link footer to uniswap.org (#3283) 2022-02-10 08:49:24 -08:00
Crowdin Bot
75ecc5810e chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-10 09:06:53 +00:00
Crowdin Bot
c30eb89725 chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-10 02:15:57 +00:00
Zach Pomerantz
108feace02 fix: enable max swap amount (#3278)
* fix: enable max swap amount

* fix: bad syntax

* fix: unnecessary optional
2022-02-09 17:54:27 -08:00
Zach Pomerantz
e2c013a4d8 chore: clean up old generated assets (#3276) 2022-02-09 17:31:41 -08:00
Zach Pomerantz
66308257d6 feat: connect wallet ux (#3275)
* fix: wallet styling

* feat: onConnectWallet prop
2022-02-09 17:27:26 -08:00
Zach Pomerantz
fd160531cc chore: add dts to .gitignore (#3273) 2022-02-09 15:52:31 -08:00
Zach Pomerantz
da36e638c2 fix: update max slippage state (#3268)
* fix: max slippage state

* chore: rename to useAllowedSlippage

* nit: maxSlippageInput name
2022-02-09 15:52:14 -08:00
Ian Lapham
fad55b8dbc update sig figs (#3270) 2022-02-09 15:44:15 -08:00
Zach Pomerantz
c9c59698de fix: tooltip overflow and cursor (#3271)
* fix: tooltip cursor

* fix: only clip dialog

* nit: clean up class name
2022-02-09 15:35:50 -08:00
Zach Pomerantz
828967031f fix: use greaterThan (#3269) 2022-02-09 14:23:53 -08:00
Tina
440ac0cba0 feat: track google analytics clientIds (#3264)
* store client id in localstorage

* remove newline

* use React.ga

* fix import
2022-02-09 12:01:01 -08:00
Jordan Frankfurt
b5a72cd63b fix(widgets): remove extra } in Trade caption (#3262) 2022-02-09 09:40:12 -06:00
Crowdin Bot
37f273aab4 chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-09 03:06:30 +00:00
Zach Pomerantz
3acd993ec0 chore: bundling nits (#3258)
* refactor: mv governance contracts to governance

* refactor: mv merkle contract to claim

* refactor: mv staking contract to staking

* chore: 0.0.6-beta

* chore: add @reduxjs/toolkit to peerDeps

* chore: v0.0.7-beta

* chore: add @reduxjs/toolkit to deps

* chore: v0.0.8-beta

* chore: swap web3-react aliasing

* chore: v0.0.9-beta

* chore: v0.0.10-beta
2022-02-08 16:43:14 -08:00
Crowdin Bot
58778b5775 chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-08 22:07:44 +00:00
Ian Lapham
5bc21bebc3 update summary details (#3254) 2022-02-08 13:33:31 -08:00
Crowdin Bot
c3d6727438 chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-08 20:07:57 +00:00
Zach Pomerantz
290f4bc1cb feat: bundle widgets (#3244)
* fix: tsconfig emissions

* fix: avoid importing app state in lib

* fix: export theming

* fix: asset resolutions

* fix: bundle widget

* test: update failing snapshots

* fix: maintain i18n for cosmos

* fix: use npm-compatible aliasing

* fix: include fonts in bundle
2022-02-08 11:04:48 -08:00
Jordan Frankfurt
f95275d5ac feat(widgets): Localize CurrencyAmounts and Prices (#3247)
* add basic number formatting

* test formatLocaleNumber

* localize CurrencyAmounts and Prices

* use lingui locale hook

* pr review

* cleaner type assertions

* check if locale is supported when formatting

* pr feedback
2022-02-08 12:45:40 -06:00
Jordan Frankfurt
0ec2dd4173 fix(widgets): fix broken unsupported network message (#3256)
* fix(widgets): fix broken unsupported network message

* require that the user be on a Uniswap chainId AND a token-list supported chainID before fetching swap info

* use .some instead of .reduce
2022-02-08 12:45:30 -06:00
Ian Lapham
3b3db6f6d0 fix: update widget loading state detection (#3253)
* update loading state detection

* create custom hook for amount detection
2022-02-08 10:38:48 -08:00
Jordan Frankfurt
707abd0071 feat(widgets): ensure passed locale is supported (#3245)
* ensure passed locale is supported

* warn on locale mismatch

* export SUPPORTED_LOCALES
2022-02-07 19:57:26 -06:00
Jordan Frankfurt
2efc1fb372 fix(widgets): convert widget colors from hex to hsl (#3239)
* convert widget colors from hex to hsl

* nits
2022-02-07 17:15:24 -06:00
Jordan Frankfurt
55b37825f3 fix(widgets): white accentText color on some buttons (#3238)
* white accentText color on some buttons

* put color calculations in useMemo, change accentText name, make hsl hex

* onAccent -> onAccentText
2022-02-07 16:56:10 -06:00
Ian Lapham
bb27b7a2ef feat: widget loading animations polish (#3232)
* create use best trade hook for widgets

* update comment in hook file

* add loading states to input / output fields

* update to not use imports from app

* remove custom loading component

* update var name and syncing detection logic

* fix USD div type

* simplify loading css, small changes
2022-02-07 14:38:07 -08:00
Zach Pomerantz
c595ba951b fix: isolate infura (#3241)
* fix: rm infura urls from lib

* fix: use passed providers for client SOR

* fix: clean up supported chain ids

* nit: rename params with specificity

* fix: use public rpc urls for l2

* fix: special-case rpc urls
2022-02-07 10:12:45 -08:00
Zach Pomerantz
96a122d7b8 chore: rename web3-react-alpha (#3243)
Renames widgets-web3-react/* to @widgets/web3-react/*.
npm treats nested packages as scoped, and requires scoped packages to begin with @.
2022-02-07 08:50:01 -08:00
Zach Pomerantz
610f7d3581 fix: named imports (webpack 5 compat) (#3242)
* fix: avoid json named imports

This is required by webpack 5, and is done to keep the widgets library compatible.
See https://webpack.js.org/migrate/5/#using-named-exports-from-json-modules

Note that this must be done upstream as well, in @uniswap/v3-sdk and @uniswap/router-sdk.

* chore: bump v3-sdk to avoid json named imports
2022-02-07 08:49:48 -08:00
Zach Pomerantz
781e774ce7 fix: set dialog wrapper with callback (#3240) 2022-02-04 16:08:50 -08:00
Ian Lapham
2aa1e40481 feat: create use best trade hook for widgets (#3226)
* create use best trade hook for widgets

* update comment in hook file

* refactor loading state conditional

* update logic in use best trade

* clean code in best trade hook
2022-02-04 18:38:27 -05:00
Zach Pomerantz
1c278d5012 fix: close summary after confirmation (#3233) 2022-02-03 15:04:11 -08:00
Jordan Frankfurt
a323a5c48b feat(widgets): convenience fee (#3231)
* feat(widgets): support convenience fee in trades (#3219)

* feat(widgets): support convenience fee in trades

* update call signature

* pr feedback

* set default convenience fee to undefined

* pr feedback
2022-02-03 14:48:30 -06:00
Zach Pomerantz
43931dd689 feat: chain-specific ttls (#3228) 2022-02-03 11:30:50 -08:00
Zach Pomerantz
efa3d5529c fix: only show max where appropriate (#3229) 2022-02-03 11:30:24 -08:00
Zach Pomerantz
5c0246cfc6 feat: outline tooltips (#3230) 2022-02-03 11:30:05 -08:00
Jordan Frankfurt
ee32418ff8 Revert "feat(widgets): support convenience fee in trades (#3219)" (#3224)
This reverts commit 8064dd8ede.
2022-02-03 10:46:18 -06:00
Zach Pomerantz
6e22389791 fix: slippage and price impact ux (#3222) 2022-02-03 08:23:27 -08:00
Jordan Frankfurt
8064dd8ede feat(widgets): support convenience fee in trades (#3219)
* feat(widgets): support convenience fee in trades

* update call signature

* pr feedback
2022-02-03 09:38:42 -06:00
Crowdin Bot
921310ef52 chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-03 08:06:38 +00:00
Ian Lapham
7b90fe137e update list component (#3221) 2022-02-02 17:52:38 -05:00
Ian Lapham
05b2711a8a feat: update widget with client side SOR (#3210)
* start SOR by creating custom widget hook

* update best trade hook to use SOR in widget

* update organization for client side SOR logic

* fix auto router chain id import

* remove dependency on react GA for widget

* update dependencies for SOr

* remove new useBestTrade.ts

* update loading logic for fetching hook

* update dependencies with import from ethersproject

* update import version

* add try catch on SOR usage

* code cleanup, nit fixes
2022-02-02 17:47:49 -05:00
Crowdin Bot
d060782242 chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-02 22:07:03 +00:00
Zach Pomerantz
e19e8492c9 feat: ux warnings (#3220)
* chore: mv Toolbar to a directory

* refactor: clean up Toolbar

* refactor: simplify Toolbar Caption

* feat: warn on price impact in Summary

* refactor: add computeRealizedPriceImpact util
2022-02-02 13:55:36 -08:00
Ian Lapham
800b5e0bda fix: fix pricing displays (#3214)
* fix pricing displays

* update rate logic, code clean
2022-02-02 13:43:12 -05:00
Ian Lapham
fc637071f9 update deadline signature data (#3215) 2022-02-02 12:33:00 -05:00
Moody Salem
1b78ceec10 chore: lockfile update only from the walletlink connector update 2022-02-02 00:13:29 -05:00
Moody Salem
e5be3ebf8f chore: put back the integrity hashes that were removed by the walletlink change 2022-02-02 00:12:59 -05:00
Brendan Weinstein
1c73719766 fix: update walletlink-connector to 6.2.11 (#3213) 2022-02-02 00:10:01 -05:00
Crowdin Bot
14c91f9bba chore(i18n): synchronize translations from crowdin [skip ci] 2022-02-02 00:13:11 +00:00
Zach Pomerantz
4b762ef5c9 feat: slippage warning ux (#3211)
* feat: setting input spacings

* feat: popover icon props

* fix: slippage input border

* feat: slippage input warning ux

* feat: slippage summary warning ux

* fix: summary layout

* fix: large icon compatibility

* fix: input option style

* fix: large icon compatibility

* fix: popover dimensions

* feat: tooltip hook

* fix: better max slippage popovers

* feat: error color input on invalid slippage

* fix: use default tx ttl

* fix: type userDeadline
2022-02-01 15:03:55 -08:00
Zach Pomerantz
c82b4fae64 fix: branded footer nits (#3209)
* chore: export brand color

* fix: target only children for extracted color transitions

* fix: branded footer nits
2022-01-31 14:08:39 -06:00
Zach Pomerantz
ab8c1e3e90 fix: input/output value/balance styles (#3207)
* fix: right-align balance

* fix: set min-height on text
2022-01-31 10:46:10 -08:00
Ian Lapham
7055d60406 remove survey (#3206) 2022-01-31 13:17:51 -05:00
Ian Lapham
c641cec651 update button color (#3205) 2022-01-31 13:02:58 -05:00
Brendan Weinstein
b6a47c734f fix: support networks other than ethereum mainnet for walletlink/coinbase wallet (#3202) 2022-01-31 12:03:00 -05:00
Crowdin Bot
7aecf5d398 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-28 20:07:31 +00:00
Crowdin Bot
5bf2b81743 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-28 18:07:13 +00:00
Ian Lapham
ed247065a7 feat: format usd prices, add loading states (#3196)
* format usd prices, add loading states

* remove tildes, collapse details by default

* update swap deadline to use seconds

* update syntax for loading states
2022-01-28 12:59:23 -05:00
Crowdin Bot
0d0ad633fb chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-28 17:10:31 +00:00
Jordan Frankfurt
4a8f1d9b96 feat(widgets): move uniswap protocol branding from header to bottom of output (#3194)
* move branding from header to bottom of output

* remove old prop

* BrandingFooter component

* pr feedback
2022-01-28 10:45:35 -06:00
Zach Pomerantz
043fb95d22 chore: no default color extraction (#3192) 2022-01-27 13:24:50 -08:00
Zach Pomerantz
06536bc925 chore: comment out routing tooltip (#3191) 2022-01-27 13:24:39 -08:00
Ian Lapham
a598a15799 feat: Make pending txn status functional (#3193)
* update swap hooks to add swap txn confirmations

* fix: remove uneeded comments

* update with latest

* update utils to separate swap callback hooks

* create generic swap callabck to be used by both app and widget

* update app swap callback to use logic from lib

* update big number import

* add swap txn to state on submit

* remove redundant  fields in txn interfaces

* consolidate trade type logic
2022-01-27 13:38:35 -05:00
Crowdin Bot
b0265c081e chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-27 01:28:46 +00:00
Zach Pomerantz
47aff6ff74 feat: max slippage ui (#3190)
* style: input padding

* feat: expand Row grow

* style: polish max slippage
2022-01-26 16:44:21 -08:00
Zach Pomerantz
56717005e6 feat: pending tx state (#3189)
* refactor: state cleanup

* feat: add pending tx hash to swap state

* fix: update name to display tx hash
2022-01-26 16:39:10 -08:00
Ian Lapham
b50d10cbb2 feat: update swap hooks and add swap txn submission (#3187)
* update swap hooks to add swap txn confirmations

* fix: remove uneeded comments

* update with latest

* update utils to separate swap callback hooks

* create generic swap callabck to be used by both app and widget

* update app swap callback to use logic from lib

* update big number import
2022-01-26 19:21:10 -05:00
Jordan Frankfurt
ce96873a72 feat(widgets): use default input/output (#3161)
* feat: use default input/output on chain switch

* feat(widgets): ErrorGenerator -> PropValidator

* default prop validation

* useDefaults hook

* pr feedback

* fix cosmos

* drop token map changes

* add default inputs to cosmos fixture

* set up different validation layers for widget and swap

* split widget/swap prop types

* cleanup

* pr feedback

* clear defaults when they're no longer valid on the current chain

* remove state checks on validators

* stop using address in cosmos fixture

* pr feedback

* useMemo on useSwapDefaults args

* tell the user what they gave to error'd props

Co-authored-by: Zach Pomerantz <zzmp@uniswap.org>
2022-01-26 12:14:18 -06:00
Tina
779625a04e fix: chain parameter should be able to switch chains on initial load (#3180)
* fix switch network on load

* dont run useeffect when chainId isnt defined yet

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

* refactor: update transactions

* feat: pending approval ui

* chore: fix pending approval doc

* fix: clarify optimized trade

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

* refactor: update transactions

* chore: add ms to deps

* test: rm stale test

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

* fix: use approval callback from trade

* chore: pass optimized trade to summary

* start review screen UI updates

* chore: pass optimized trade to summary

* fix: pass Trade to summary

* remove uneeded value type

* remove uneeded styling

* code cleanup

* code styling, update props

* fix fixture bug, code style updates

* bug fix in details array

* update logic in details

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

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

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

* dont open network selector menu on url param change

* prompt network change when url changes

* keep url, network in sync

* use chain name instead of id in url param

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

* remove attempted styling for other PR

* back out UI changes, small naming updates

* remove UI work

* small code style changes, fix typo

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

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

* test: use infura urls

* fix: load native with chain

* fix: use currencyId for key

* feat: switch currencies when selecting other

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

* chore: add default exports

* refactor: update swap state to match biz logic

* feat: copy biz logic to widgets

* Hook up UI to updated swap state

* fix: decimal inputs

* fix max slippage

* fix error in settings

* fix: typing errors

* revert: useBestTrade changes

* fix: use client side trade for widgets

* fix: exhaustive deps

* chore: add router-sdk

* fix: gate old web3 on widget env

* fix building errors

* update trade imports

* update hook naming for swap amount and currencies

* small changes

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

* rename reporter to generator

* pr feedback

* refactor provider check

* add chainId, convenienceFee, and width errors

* pr feedback and convenienceFeeRecipient address enforcement

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

* fix: memoize current block timestamp

* fix: memoize price impact

* fix: memoize debounced value updates

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

* feat: include native currency in select

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

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

* test: update fixtures to use real currency

* fix: data uri color extraction

* fix: token img state

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

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

* update useEffect and add 24 hour window

* upate % logic

* update logic to show after duration

* update timestamp conditional

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

* chore: replace microbundle with rollup

* chore: use ts rollup config

* chore: rename lib to widgets

* chore: add rollup doc comment

* feat: rollup typings

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

* refactor: mv balance hooks to lib

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

* fix: add block updater

* fix: fast forward dep

* refactor: mv multicall to lib

* feat: add multicall to widget

* chore: update widget deps

* nit: pluralize updaters

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

* fix: add block updater

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

This reverts commit 6d9c0855d2.

* Revert "fix: use provider JsonRpcProvider"

This reverts commit dcbbab5e4d.

* chore: depend on @ethersprojects directly
2022-01-12 10:06:22 -08:00
willpote
aa97ec01d3 chore: bump sor to 2.5.10 (#3091) 2022-01-11 17:26:42 -05:00
Crowdin Bot
83b70f3aa6 chore(i18n): synchronize translations from crowdin [skip ci] 2022-01-11 21:06:53 +00:00
Noah Zinsmeister
e37dd77680 Revert "bump to beta (#3090)"
This reverts commit aa37b23126.
2022-01-11 16:00:52 -05:00
Noah Zinsmeister
aa37b23126 bump to beta (#3090) 2022-01-11 15:30:45 -05:00
381 changed files with 15574 additions and 9411 deletions

3
.env
View File

@@ -1 +1,2 @@
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
REACT_APP_LOCALES="locales"

View File

@@ -59,13 +59,17 @@
{
"paths": [
{
"name": "@lingui/macro",
"importNames": ["t"],
"message": "Please use <Trans> instead of t."
"name": "ethers",
"message": "Please import from '@ethersproject/module' directly to support tree-shaking."
},
{
"name": "styled-components",
"message": "Please import from styled-components/macro."
},
{
"name": "@lingui/macro",
"importNames": ["t"],
"message": "Please use <Trans> instead of t."
}
],
"patterns": [
@@ -73,10 +77,6 @@
"group": ["**/dist"],
"message": "Do not import from dist/ - this is an implementation detail, and breaks tree-shaking."
},
{
"group": ["@ethersproject"],
"message": "Please import from 'ethers' to support bundling."
},
{
"group": ["!styled-components/macro"]
}

View File

@@ -1,4 +1,4 @@
name: Bundle Dependency Check
name: Widgets
on:
push:
branches:
@@ -8,8 +8,8 @@ on:
- main
jobs:
depcheck:
name: Bundle depcheck
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -36,8 +36,5 @@ jobs:
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Bundle
run: yarn bundle
- name: Depcheck
run: yarn bundle:depcheck
- name: Build
run: yarn widgets:build

View File

@@ -38,10 +38,10 @@ jobs:
run: yarn install --frozen-lockfile
- run: yarn cypress install
- run: yarn build
env:
CI: false
REACT_APP_NETWORK_URL: 'https://mainnet.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847'
REACT_APP_SERVICE_WORKER: false
- run: yarn test:e2e

10
.gitignore vendored
View File

@@ -11,21 +11,17 @@
/src/locales/**/pseudo.po
/src/state/data/generated.ts
# generated assets
/src/lib/assets/svg/*.tsx
/src/lib/assets/fonts/*.css
# dependencies
/node_modules
# testing
/coverage
# production
# builds
/build
# bundle
/cosmos-export
/dist
/dts
# misc
.DS_Store

View File

@@ -4,6 +4,7 @@
],
"webpack": {
"configPath": "react-scripts/config/webpack.config",
"overridePath": "cosmos.override.js"
}
}
"overridePath": "cosmos.override.cjs"
},
"port": 5001
}

26
cosmos.override.cjs Normal file
View File

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

View File

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

View File

@@ -2,16 +2,27 @@ describe('Swap', () => {
beforeEach(() => {
cy.visit('/swap')
})
it('starts with ETH selected by default', () => {
cy.get('#swap-currency-input .token-amount-input').should('have.value', '')
cy.get('#swap-currency-input .token-symbol-container').should('contain.text', 'ETH')
cy.get('#swap-currency-output .token-amount-input').should('not.have.value')
cy.get('#swap-currency-output .token-symbol-container').should('contain.text', 'Select a token')
})
it('can enter an amount into input', () => {
cy.get('#swap-currency-input .token-amount-input').type('0.001', { delay: 200 }).should('have.value', '0.001')
cy.get('#swap-currency-input .token-amount-input')
.clear()
.type('0.001', { delay: 200 })
.should('have.value', '0.001')
})
it('zero swap amount', () => {
cy.get('#swap-currency-input .token-amount-input').type('0.0', { delay: 200 }).should('have.value', '0.0')
cy.get('#swap-currency-input .token-amount-input').clear().type('0.0', { delay: 200 }).should('have.value', '0.0')
})
it('invalid swap amount', () => {
cy.get('#swap-currency-input .token-amount-input').type('\\', { delay: 200 }).should('have.value', '')
cy.get('#swap-currency-input .token-amount-input').clear().type('\\', { delay: 200 }).should('have.value', '')
})
it('can enter an amount into output', () => {

View File

@@ -4,9 +4,9 @@
// https://on.cypress.io/custom-commands
// ***********************************************
// eslint-disable-next-line no-restricted-imports
import { Eip1193Bridge } from '@ethersproject/experimental/lib/eip1193-bridge'
import { providers, Wallet } from 'ethers'
import { JsonRpcProvider } from '@ethersproject/providers'
import { Wallet } from '@ethersproject/wallet'
// todo: figure out how env vars actually work in CI
// const TEST_PRIVATE_KEY = Cypress.env('INTEGRATION_TEST_PRIVATE_KEY')
@@ -81,7 +81,7 @@ Cypress.Commands.overwrite('visit', (original, url, options) => {
onBeforeLoad(win) {
options && options.onBeforeLoad && options.onBeforeLoad(win)
win.localStorage.clear()
const provider = new providers.JsonRpcProvider('https://rinkeby.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847', 4)
const provider = new JsonRpcProvider('https://rinkeby.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847', 4)
const signer = new Wallet(TEST_PRIVATE_KEY, provider)
win.ethereum = new CustomizedBridge(signer, provider)
},

View File

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

View File

@@ -1,29 +1,58 @@
{
"name": "@uniswap/interface",
"name": "@uniswap/widgets",
"version": "0.0.23-beta",
"description": "Uniswap Interface",
"homepage": ".",
"main": "dist/interface.js",
"module": "dist/interface.esm.js",
"types": "dist/index.d.ts",
"files": [
"lib",
"dist"
],
"private": true,
"type": "module",
"types": "dist/index.d.ts",
"main": "dist/cjs/index.cjs",
"module": "dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/cjs/index.cjs"
},
"./locales/*": {
"import": "./dist/locales/*.js",
"require": "./dist/cjs/locales/*.cjs"
},
"./fonts.css": {
"import": "./dist/fonts.css",
"require": "./dist/fonts.css"
}
},
"devDependencies": {
"@ethersproject/experimental": "^5.4.0",
"@babel/plugin-transform-runtime": "^7.17.0",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"@babel/preset-typescript": "^7.16.7",
"@gnosis.pm/safe-apps-web3-react": "^0.6.0",
"@graphql-codegen/cli": "1.21.5",
"@graphql-codegen/typescript": "1.22.3",
"@graphql-codegen/typescript-operations": "^1.18.2",
"@graphql-codegen/typescript-rtk-query": "^1.1.1",
"@lingui/cli": "^3.9.0",
"@lingui/core": "^3.9.0",
"@lingui/macro": "^3.9.0",
"@lingui/react": "^3.9.0",
"@metamask/jazzicon": "^2.0.0",
"@reach/dialog": "^0.10.3",
"@reach/portal": "^0.10.3",
"@react-hook/window-scroll": "^1.3.0",
"@reduxjs/toolkit": "^1.6.1",
"@svgr/cli": "^5.5.0",
"@rollup/plugin-alias": "^3.1.9",
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-eslint": "^8.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.1.3",
"@rollup/plugin-replace": "^3.0.1",
"@rollup/plugin-typescript": "^8.3.0",
"@rollup/plugin-url": "^6.1.0",
"@svgr/rollup": "^6.2.0",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.0.0",
"@testing-library/react-hooks": "^7.0.2",
@@ -52,25 +81,19 @@
"@types/wcag-contrast": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
"@uniswap/default-token-list": "^3.0.0",
"@uniswap/governance": "^1.0.2",
"@uniswap/liquidity-staker": "^1.0.2",
"@uniswap/merkle-distributor": "1.0.1",
"@uniswap/router-sdk": "^1.0.3",
"@uniswap/smart-order-router": "^2.5.9",
"@uniswap/v2-core": "1.0.0",
"@uniswap/v2-periphery": "^1.1.0-beta.0",
"@uniswap/v2-sdk": "^3.0.1",
"@uniswap/v3-core": "1.0.0",
"@uniswap/v3-periphery": "^1.1.1",
"@uniswap/v3-sdk": "^3.7.1",
"@web3-react/core": "^6.0.9",
"@web3-react/fortmatic-connector": "^6.0.9",
"@web3-react/injected-connector": "^6.0.7",
"@web3-react/portis-connector": "^6.0.9",
"@web3-react/walletconnect-connector": "^7.0.2-alpha.0",
"@web3-react/walletlink-connector": "^6.2.8",
"@web3-react/metamask": "8.0.13-beta.0",
"@web3-react/walletconnect": "8.0.18-beta.0",
"array.prototype.flat": "^1.2.4",
"array.prototype.flatmap": "^1.2.4",
"babel-plugin-macros": "^3.1.0",
"copy-to-clipboard": "^3.2.0",
"cross-env": "^7.0.3",
"cypress": "^7.7.0",
@@ -88,13 +111,13 @@
"graphql-request": "^3.4.0",
"inter-ui": "^3.13.1",
"jest-styled-components": "^7.0.5",
"microbundle": "^0.13.3",
"ms.macro": "^2.0.0",
"polyfill-object.fromentries": "^1.0.1",
"prettier": "^2.2.1",
"qs": "^6.9.4",
"react": "^17.0.1",
"react-confetti": "^6.0.0",
"react-cosmos": "^5.6.3",
"react-cosmos": "^5.6.6",
"react-dom": "^17.0.1",
"react-ga": "^2.5.7",
"react-is": "^17.0.2",
"react-markdown": "^4.3.1",
@@ -103,17 +126,33 @@
"react-scripts": "^4.0.3",
"react-spring": "^8.0.27",
"react-use-gesture": "^6.0.14",
"redux": "^4.1.2",
"redux-localstorage-simple": "^2.3.1",
"rollup": "^2.63.0",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-delete": "^2.0.0",
"rollup-plugin-dts": "^4.1.0",
"rollup-plugin-multi-input": "^1.3.1",
"rollup-plugin-node-externals": "^3.1.2",
"rollup-plugin-scss": "^3.0.0",
"rollup-plugin-typescript2": "^0.31.1",
"sass": "^1.45.1",
"serve": "^11.3.2",
"start-server-and-test": "^1.11.0",
"typechain": "^5.0.0",
"typescript": "^4.2.3",
"typescript": "^4.4.3",
"ua-parser-js": "^0.7.28",
"use-count-up": "^2.2.5",
"use-resize-observer": "^8.0.0",
"wcag-contrast": "^3.0.0",
"web-vitals": "^2.1.0",
"web3-react-abstract-connector": "npm:@web3-react/abstract-connector@^6.0.7",
"web3-react-fortmatic-connector": "npm:@web3-react/fortmatic-connector@^6.0.9",
"web3-react-injected-connector": "npm:@web3-react/injected-connector@^6.0.7",
"web3-react-portis-connector": "npm:@web3-react/portis-connector@^6.0.9",
"web3-react-types": "npm:@web3-react/types@^6.0.7",
"web3-react-walletconnect-connector": "npm:@web3-react/walletconnect-connector@^7.0.2-alpha.0",
"web3-react-walletlink-connector": "npm:@web3-react/walletlink-connector@^6.2.13",
"workbox-core": "^6.1.0",
"workbox-precaching": "^6.1.0",
"workbox-routing": "^6.1.0"
@@ -130,17 +169,14 @@
"i18n:extract": "lingui extract --locale en-US",
"i18n:compile": "yarn i18n:extract && lingui compile",
"i18n:pseudo": "lingui extract --locale pseudo && lingui compile",
"postinstall": "yarn contracts:compile && yarn graphql:generate && yarn i18n:compile && yarn assets:generate",
"prepare": "yarn contracts:compile && yarn graphql:generate && yarn i18n:compile",
"prepublishOnly": "yarn widgets:build",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=./custom-test-env.js",
"test:e2e": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run'",
"assets:generate": "yarn assets:svg:generate && yarn assets:font:generate",
"assets:svg:generate": "svgr -d src/lib/assets/svg --ext tsx --typescript src/lib/assets/svg && rm src/lib/assets/svg/index.tsx",
"assets:font:generate": "sass src/lib/assets/fonts/index.scss src/lib/assets/fonts/index.css --no-source-map -I node_modules",
"bundle": "microbundle --define process.env.REACT_APP_IS_WIDGET=true --tsconfig tsconfig.lib.json src/lib/index.tsx --format esm,cjs",
"bundle:depcheck": "node depcheck.js",
"cosmos": "cross-env FAST_REFRESH=false REACT_APP_IS_WIDGET=true cosmos"
"test": "react-scripts test --env=./custom-test-env.cjs",
"test:e2e": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run --record'",
"widgets:start": "cosmos",
"widgets:build": "rollup --config --failAfterWarnings --configPlugin typescript2"
},
"browserslist": {
"production": [
@@ -156,43 +192,72 @@
},
"license": "GPL-3.0-or-later",
"dependencies": {
"@babel/runtime": "^7.17.0",
"@ethersproject/abi": "^5.4.1",
"@ethersproject/abstract-provider": "^5.4.1",
"@ethersproject/abstract-signer": "^5.4.1",
"@ethersproject/address": "^5.4.0",
"@ethersproject/bignumber": "^5.4.2",
"@ethersproject/bytes": "^5.4.0",
"@ethersproject/constants": "^5.4.0",
"@ethersproject/contracts": "^5.4.1",
"@ethersproject/experimental": "^5.4.0",
"@ethersproject/hash": "^5.4.0",
"@ethersproject/providers": "^5.4.0",
"@ethersproject/solidity": "^5.4.0",
"@ethersproject/strings": "^5.4.0",
"@ethersproject/units": "^5.4.0",
"@ethersproject/wallet": "^5.4.0",
"@fontsource/ibm-plex-mono": "^4.5.1",
"@fontsource/inter": "^4.5.1",
"@lingui/core": "^3.9.0",
"@lingui/macro": "^3.9.0",
"@lingui/react": "^3.9.0",
"@popperjs/core": "^2.4.4",
"@reduxjs/toolkit": "^1.6.1",
"@uniswap/redux-multicall": "^1.0.0",
"@uniswap/router-sdk": "^1.0.3",
"@uniswap/sdk-core": "^3.0.1",
"@uniswap/smart-order-router": "^2.5.20",
"@uniswap/token-lists": "^1.0.0-beta.27",
"@uniswap/v2-sdk": "^3.0.1",
"@uniswap/v3-sdk": "^3.8.2",
"@web3-react/core": "8.0.17-beta.0",
"@web3-react/eip1193": "8.0.12-beta.0",
"@web3-react/empty": "8.0.10-beta.0",
"@web3-react/types": "8.0.10-beta.0",
"@web3-react/url": "8.0.12-beta.0",
"ajv": "^6.12.3",
"cids": "^1.0.0",
"ethers": "^5.4.6",
"immer": "^9.0.6",
"jotai": "^1.3.7",
"jsbi": "^3.1.4",
"make-plural": "^7.0.0",
"ms.macro": "^2.0.0",
"multicodec": "^3.0.1",
"multihashes": "^4.0.2",
"node-vibrant": "^3.2.1-alpha.1",
"polished": "^3.3.2",
"popper-max-size-modifier": "^0.2.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-feather": "^2.0.8",
"react-popper": "^2.2.3",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.5",
"rebass": "^4.0.7",
"redux": "^4.1.2",
"setimmediate": "^1.0.5",
"styled-components": "^5.3.0",
"tiny-invariant": "^1.2.0",
"wcag-contrast": "^3.0.0",
"wicg-inert": "^3.1.1",
"widgets-web3-react/core": "npm:@web3-react/core@8.0.16-alpha.0",
"widgets-web3-react/eip1193": "npm:@web3-react/eip1193@8.0.16-alpha.0",
"widgets-web3-react/empty": "npm:@web3-react/empty@8.0.17-alpha.0",
"widgets-web3-react/metamask": "npm:@web3-react/metamask@8.0.16-alpha.0",
"widgets-web3-react/types": "npm:@web3-react/types@8.0.16-alpha.0",
"widgets-web3-react/url": "npm:@web3-react/url@8.0.17-alpha.0"
"web3-react-core": "npm:@web3-react/core@^6.0.9",
"wicg-inert": "^3.1.1"
},
"peerDependencies": {
"@babel/runtime": "^7.17.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-redux": "^7.2.2",
"redux": "^4.1.2"
},
"optionalDependencies": {
"bufferutil": "^4.0.6",
"encoding": "^0.1.13",
"utf-8-validate": "^5.0.8"
}
}
}

176
rollup.config.ts Normal file
View File

@@ -0,0 +1,176 @@
/**
* Bundles the widgets library, which is released independently of the interface application.
* This library lives in src/lib, but shares code with the interface application.
*/
import alias from '@rollup/plugin-alias'
import babel from '@rollup/plugin-babel'
import commonjs from '@rollup/plugin-commonjs'
import json from '@rollup/plugin-json'
import resolve from '@rollup/plugin-node-resolve'
import replace from '@rollup/plugin-replace'
import typescript from '@rollup/plugin-typescript'
import url from '@rollup/plugin-url'
import svgr from '@svgr/rollup'
import path from 'path'
import { RollupWarning } from 'rollup'
import copy from 'rollup-plugin-copy'
import del from 'rollup-plugin-delete'
import dts from 'rollup-plugin-dts'
// @ts-ignore // missing types
import multi from 'rollup-plugin-multi-input'
import externals from 'rollup-plugin-node-externals'
import sass from 'rollup-plugin-scss'
import { CompilerOptions } from 'typescript'
const REPLACEMENTS = {
'process.env.REACT_APP_IS_WIDGET': true,
'process.env.REACT_APP_LOCALES': '"./locales"',
// esm requires fully-specified paths:
'react/jsx-runtime': 'react/jsx-runtime.js',
}
const EXTENSIONS = ['.js', '.jsx', '.ts', '.tsx']
const ASSET_EXTENSIONS = ['.png', '.svg']
function isAsset(source: string) {
const extname = path.extname(source)
return extname && [...ASSET_EXTENSIONS, '.css', '.scss'].includes(extname)
}
const TS_CONFIG = './tsconfig.lib.json'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { baseUrl, paths }: CompilerOptions = require(TS_CONFIG).compilerOptions
const aliases = Object.entries({ ...paths }).flatMap(([find, replacements]) => {
return replacements.map((replacement) => ({
find: path.dirname(find),
replacement: path.join(__dirname, baseUrl || '.', path.dirname(replacement)),
}))
})
const plugins = [
// Dependency resolution
resolve({ extensions: EXTENSIONS }), // resolves third-party modules within node_modules/
alias({ entries: aliases }), // resolves paths aliased through the tsconfig (babel does not use tsconfig path resolution)
// Source code transformation
replace({ ...REPLACEMENTS, preventAssignment: true }),
json(), // imports json as ES6; doing so enables type-checking and module resolution
]
const check = {
input: 'src/lib/index.tsx',
output: { file: 'dist/widgets.tsc', inlineDynamicImports: true },
external: isAsset,
plugins: [
externals({ exclude: ['constants'], deps: true, peerDeps: true }), // marks builtins, dependencies, and peerDependencies external
...plugins,
typescript({ tsconfig: TS_CONFIG }),
],
onwarn: squelchTranspilationWarnings, // this pipeline is only for typechecking and generating definitions
}
const type = {
input: 'dist/dts/lib/index.d.ts',
output: { file: 'dist/index.d.ts' },
external: isAsset,
plugins: [
externals({ exclude: ['constants'], deps: true, peerDeps: true }),
dts({ compilerOptions: { baseUrl: 'dist/dts' } }),
process.env.ROLLUP_WATCH ? undefined : del({ hook: 'buildEnd', targets: ['dist/widgets.tsc', 'dist/dts'] }),
],
}
/**
* This exports scheme works for nextjs and for CRA5.
*
* It will also work for CRA4 if you use direct imports:
* instead of `import { SwapWidget } from '@uniswap/widgets'`,
* `import { SwapWidget } from '@uniswap/widgets/dist/index.js'`.
* I do not know why CRA4 does not seem to use exports for resolution.
*
* Note that chunks are enabled. This is so the tokenlist spec can be loaded async,
* to improve first load time (due to ajv). Locales are also in separate chunks.
*
* Lastly, note that JSON and lingui are bundled into the library, as neither are fully
* supported/compatible with ES Modules. Both _could_ be bundled only with esm, but this
* yields a less complex pipeline.
*/
const transpile = {
input: 'src/lib/index.tsx',
output: [
{
dir: 'dist',
format: 'esm',
sourcemap: false,
},
{
dir: 'dist/cjs',
entryFileNames: '[name].cjs',
chunkFileNames: '[name]-[hash].cjs',
format: 'cjs',
sourcemap: false,
},
],
plugins: [
externals({
exclude: [
'constants',
/@lingui\/(core|react)/, // @lingui incorrectly exports esm, so it must be bundled in
/\.json$/, // esm does not support JSON loading, so it must be bundled in
],
deps: true,
peerDeps: true,
}),
...plugins,
// Source code transformation
url({ include: ASSET_EXTENSIONS.map((extname) => '**/*' + extname), limit: Infinity }), // imports assets as data URIs
svgr({ exportType: 'named', svgo: false }), // imports svgs as React components
sass({ output: 'dist/fonts.css' }), // generates fonts.css
commonjs(), // transforms cjs dependencies into tree-shakeable ES modules
babel({
babelHelpers: 'runtime',
presets: ['@babel/preset-env', ['@babel/preset-react', { runtime: 'automatic' }], '@babel/preset-typescript'],
extensions: EXTENSIONS,
plugins: [
'macros', // enables @lingui and styled-components macros
'@babel/plugin-transform-runtime', // embeds the babel runtime for library distribution
],
}),
],
onwarn: squelchTypeWarnings, // this pipeline is only for transpilation
}
const locales = {
input: 'src/locales/*.js',
output: [
{
dir: 'dist',
format: 'esm',
sourcemap: false,
},
],
plugins: [
copy({
copyOnce: true,
targets: [{ src: 'src/locales/*.js', dest: 'dist/cjs/locales', rename: (name) => `${name}.cjs` }],
}),
commonjs(),
multi(),
],
}
const config = [check, type, transpile, locales]
export default config
function squelchTranspilationWarnings(warning: RollupWarning, warn: (warning: RollupWarning) => void) {
if (warning.pluginCode === 'TS5055') return
warn(warning)
}
function squelchTypeWarnings(warning: RollupWarning, warn: (warning: RollupWarning) => void) {
if (warning.code === 'UNUSED_EXTERNAL_IMPORT') return
warn(warning)
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

View File

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

Before

Width:  |  Height:  |  Size: 233 B

After

Width:  |  Height:  |  Size: 233 B

View File

@@ -1,16 +1,5 @@
<svg width="170" height="168" viewBox="0 0 170 168" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path opacity="0.6" d="M85.05 168C132.022 168 170.1 130.105 170.1 83.3593C170.1 36.6135 0 36.6135 0 83.3593C0 130.105 38.0782 168 85.05 168Z" fill="#FF505F"/>
<path opacity="0.6" d="M85.05 168C132.022 168 170.1 130.105 170.1 83.3593C170.1 36.6135 0 36.6135 0 83.3593C0 130.105 38.0782 168 85.05 168Z" fill="#FF0320"/>
<path d="M85.05 0C132.022 0 170.1 37.8949 170.1 84.6407C170.1 131.386 0 131.386 0 84.6407C0 37.8949 38.0782 0 85.05 0Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M144.665 64.0394L112.444 12.3742L89.0263 78.9477L144.665 64.0394Z" fill="#FF4E65"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M143.777 64.215L112.444 12.3742L165.349 58.4347L143.777 64.215Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M144.551 63.613L142.479 124.467L88.912 78.5213L144.551 63.613Z" fill="#D0001A"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M143.663 63.7886L142.479 124.467L165.235 58.0083L143.663 63.7886Z" fill="#FF697B"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="170" height="168" fill="white"/>
</clipPath>
</defs>
<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="250" cy="250" r="250" fill="#FF0420"/>
<path d="M177.133 316.446C162.247 316.446 150.051 312.943 140.544 305.938C131.162 298.808 126.471 288.676 126.471 275.541C126.471 272.789 126.784 269.411 127.409 265.408C129.036 256.402 131.35 245.581 134.352 232.947C142.858 198.547 164.812 181.347 200.213 181.347C209.845 181.347 218.476 182.973 226.107 186.225C233.738 189.352 239.742 194.106 244.12 200.486C248.498 206.74 250.688 214.246 250.688 223.002C250.688 225.629 250.375 228.944 249.749 232.947C247.873 244.08 245.621 254.901 242.994 265.408C238.616 282.546 231.048 295.368 220.29 303.874C209.532 312.255 195.147 316.446 177.133 316.446ZM179.76 289.426C186.766 289.426 192.707 287.362 197.586 283.234C202.59 279.106 206.155 272.789 208.281 264.283C211.158 252.524 213.348 242.266 214.849 233.51C215.349 230.883 215.599 228.194 215.599 225.441C215.599 214.058 209.657 208.366 197.774 208.366C190.768 208.366 184.764 210.43 179.76 214.558C174.882 218.687 171.379 225.004 169.253 233.51C167.001 241.891 164.749 252.149 162.498 264.283C161.997 266.784 161.747 269.411 161.747 272.163C161.747 283.672 167.752 289.426 179.76 289.426Z" fill="white"/>
<path d="M259.303 314.57C257.927 314.57 256.863 314.132 256.113 313.256C255.487 312.255 255.3 311.13 255.55 309.879L281.444 187.914C281.694 186.538 282.382 185.412 283.508 184.536C284.634 183.661 285.822 183.223 287.073 183.223H336.985C350.87 183.223 362.003 186.1 370.384 191.854C378.891 197.609 383.144 205.927 383.144 216.81C383.144 219.937 382.769 223.19 382.018 226.567C378.891 240.953 372.574 251.586 363.067 258.466C353.685 265.346 340.8 268.786 324.413 268.786H299.082L290.451 309.879C290.2 311.255 289.512 312.38 288.387 313.256C287.261 314.132 286.072 314.57 284.822 314.57H259.303ZM325.727 242.892C330.98 242.892 335.546 241.453 339.424 238.576C343.427 235.699 346.054 231.571 347.305 226.192C347.68 224.065 347.868 222.189 347.868 220.563C347.868 216.935 346.805 214.183 344.678 212.307C342.551 210.305 338.924 209.305 333.795 209.305H311.278L304.148 242.892H325.727Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

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

View File

@@ -1,15 +1,15 @@
import { Trans } from '@lingui/macro'
import { AbstractConnector } from '@web3-react/abstract-connector'
import { Connector } from '@web3-react/types'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useCallback, useContext } from 'react'
import { ExternalLink as LinkIcon } from 'react-feather'
import { useAppDispatch } from 'state/hooks'
import styled, { ThemeContext } from 'styled-components/macro'
import { Connector } from 'widgets-web3-react/types'
import { AbstractConnector } from 'web3-react-abstract-connector'
import { ReactComponent as Close } from '../../assets/images/x.svg'
import { injected, portis, walletlink } from '../../connectors'
import { SUPPORTED_WALLETS } from '../../constants/wallet'
import { useActiveWeb3React } from '../../hooks/web3'
import { clearAllTransactions } from '../../state/transactions/actions'
import { ExternalLink, LinkStyledButton, ThemedText } from '../../theme'
import { shortenAddress } from '../../utils'

View File

@@ -1,11 +1,11 @@
import { Trans } from '@lingui/macro'
// eslint-disable-next-line no-restricted-imports
import { t } from '@lingui/macro'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { ReactNode, useCallback, useContext } from 'react'
import styled, { ThemeContext } from 'styled-components/macro'
import useENS from '../../hooks/useENS'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink, ThemedText } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
import { AutoColumn } from '../Column'

View File

@@ -1,8 +1,7 @@
import { Trans } from '@lingui/macro'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { ReactNode, useMemo } from 'react'
import { useActiveWeb3React } from '../../hooks/web3'
// SDN OFAC addresses
const BLOCKED_ADDRESSES: string[] = [
'0x7Db418b5D567A4e0E8c59Ad71BE1FcE48f3E6107',
@@ -32,6 +31,8 @@ const BLOCKED_ADDRESSES: string[] = [
'0x6acdfba02d390b97ac2b2d42a63e85293bcc160e',
'0x48549a34ae37b12f6a30566245176994e17c6b4a',
'0x5512d943ed1f7c8a43f3435c85f7ab68b30121b0',
'0xc455f7fd3e0e12afd51fba5c106909934d8a0e4a',
'0x629e7Da20197a5429d30da36E77d06CdF796b71A',
]
export default function Blocklist({ children }: { children: ReactNode }) {

View File

@@ -3,6 +3,7 @@ import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { darken } from 'polished'
import { ReactNode, useCallback, useState } from 'react'
import { Lock } from 'react-feather'
@@ -11,7 +12,6 @@ import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import useTheme from '../../hooks/useTheme'
import { useActiveWeb3React } from '../../hooks/web3'
import { useCurrencyBalance } from '../../state/wallet/hooks'
import { ThemedText } from '../../theme'
import { ButtonGray } from '../Button'

View File

@@ -1,60 +1,18 @@
import { Currency } from '@uniswap/sdk-core'
import EthereumLogo from 'assets/images/ethereum-logo.png'
import MaticLogo from 'assets/svg/matic-token-icon.svg'
import { SupportedChainId } from 'constants/chains'
import useHttpLocations from 'hooks/useHttpLocations'
import React, { useMemo } from 'react'
import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo'
import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs'
import React from 'react'
import styled from 'styled-components/macro'
import Logo from '../Logo'
type Network = 'ethereum' | 'arbitrum' | 'optimism'
function chainIdToNetworkName(networkId: SupportedChainId): Network {
switch (networkId) {
case SupportedChainId.MAINNET:
return 'ethereum'
case SupportedChainId.ARBITRUM_ONE:
return 'arbitrum'
case SupportedChainId.OPTIMISM:
return 'optimism'
default:
return 'ethereum'
}
}
export const getTokenLogoURL = (
address: string,
chainId: SupportedChainId = SupportedChainId.MAINNET
): string | void => {
const networkName = chainIdToNetworkName(chainId)
const networksWithUrls = [SupportedChainId.ARBITRUM_ONE, SupportedChainId.MAINNET, SupportedChainId.OPTIMISM]
if (networksWithUrls.includes(chainId)) {
return `https://raw.githubusercontent.com/Uniswap/assets/master/blockchains/${networkName}/assets/${address}/logo.png`
}
}
const StyledNativeLogo = styled.img<{ size: string }>`
width: ${({ size }) => size};
height: ${({ size }) => size};
background: radial-gradient(white 50%, #ffffff00 calc(75% + 1px), #ffffff00 100%);
border-radius: 50%;
-mox-box-shadow: 0 0 1px white;
-webkit-box-shadow: 0 0 1px white;
box-shadow: 0 0 1px white;
border: 0px solid rgba(255, 255, 255, 0);
`
const StyledLogo = styled(Logo)<{ size: string }>`
const StyledLogo = styled(Logo)<{ size: string; native: boolean }>`
width: ${({ size }) => size};
height: ${({ size }) => size};
background: radial-gradient(white 50%, #ffffff00 calc(75% + 1px), #ffffff00 100%);
border-radius: 50%;
-mox-box-shadow: 0 0 1px black;
-webkit-box-shadow: 0 0 1px black;
box-shadow: 0 0 1px black;
-mox-box-shadow: 0 0 1px ${({ native }) => (native ? 'white' : 'black')};
-webkit-box-shadow: 0 0 1px ${({ native }) => (native ? 'white' : 'black')};
box-shadow: 0 0 1px ${({ native }) => (native ? 'white' : 'black')};
border: 0px solid rgba(255, 255, 255, 0);
`
@@ -68,38 +26,16 @@ export default function CurrencyLogo({
size?: string
style?: React.CSSProperties
}) {
const uriLocations = useHttpLocations(currency instanceof WrappedTokenInfo ? currency.logoURI : undefined)
const logoURIs = useCurrencyLogoURIs(currency)
const srcs: string[] = useMemo(() => {
if (!currency || currency.isNative) return []
if (currency.isToken) {
const defaultUrls = []
const url = getTokenLogoURL(currency.address, currency.chainId)
if (url) {
defaultUrls.push(url)
}
if (currency instanceof WrappedTokenInfo) {
return [...uriLocations, ...defaultUrls]
}
return defaultUrls
}
return []
}, [currency, uriLocations])
if (currency?.isNative) {
let nativeLogoUrl: string
switch (currency.chainId) {
case SupportedChainId.POLYGON_MUMBAI:
case SupportedChainId.POLYGON:
nativeLogoUrl = MaticLogo
break
default:
nativeLogoUrl = EthereumLogo
break
}
return <StyledNativeLogo src={nativeLogoUrl} alt="ethereum logo" size={size} style={style} {...rest} />
}
return <StyledLogo size={size} srcs={srcs} alt={`${currency?.symbol ?? 'token'} logo`} style={style} {...rest} />
return (
<StyledLogo
size={size}
native={currency?.isNative ?? false}
srcs={logoURIs}
alt={`${currency?.symbol ?? 'token'} logo`}
style={style}
{...rest}
/>
)
}

View File

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

View File

@@ -5,10 +5,10 @@ import { ButtonGray } from 'components/Button'
import Card from 'components/Card'
import { AutoColumn } from 'components/Column'
import { RowBetween } from 'components/Row'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useFeeTierDistribution } from 'hooks/useFeeTierDistribution'
import { PoolState, usePools } from 'hooks/usePools'
import usePrevious from 'hooks/usePrevious'
import { useActiveWeb3React } from 'hooks/web3'
import { DynamicSection } from 'pages/AddLiquidity/styled'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import ReactGA from 'react-ga'

View File

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

View File

@@ -1,13 +1,19 @@
import { Trans } from '@lingui/macro'
import { CHAIN_INFO, SupportedChainId } from 'constants/chains'
import { CHAIN_INFO } from 'constants/chainInfo'
import { CHAIN_IDS_TO_NAMES, SupportedChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useOnClickOutside } from 'hooks/useOnClickOutside'
import { useActiveWeb3React } from 'hooks/web3'
import { useCallback, useRef } from 'react'
import useParsedQueryString from 'hooks/useParsedQueryString'
import usePrevious from 'hooks/usePrevious'
import { ParsedQs } from 'qs'
import { useCallback, useEffect, useRef } from 'react'
import { ArrowDownCircle, ChevronDown } from 'react-feather'
import { useHistory } from 'react-router-dom'
import { useModalOpen, useToggleModal } from 'state/application/hooks'
import { addPopup, ApplicationModal } from 'state/application/reducer'
import styled from 'styled-components/macro'
import { ExternalLink, MEDIA_WIDTHS } from 'theme'
import { replaceURLParam } from 'utils/routes'
import { useAppDispatch } from '../../state/hooks'
import { switchToNetwork } from '../../utils/switchToNetwork'
@@ -45,6 +51,16 @@ const FlyoutHeader = styled.div`
font-weight: 400;
`
const FlyoutMenu = styled.div`
position: absolute;
top: 54px;
width: 272px;
z-index: 99;
padding-top: 10px;
@media screen and (min-width: ${MEDIA_WIDTHS.upToSmall}px) {
top: 40px;
}
`
const FlyoutMenuContents = styled.div`
align-items: flex-start;
background-color: ${({ theme }) => theme.bg0};
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
@@ -55,16 +71,9 @@ const FlyoutMenu = styled.div`
font-size: 16px;
overflow: auto;
padding: 16px;
position: absolute;
top: 64px;
width: 272px;
z-index: 99;
& > *:not(:last-child) {
margin-bottom: 12px;
}
@media screen and (min-width: ${MEDIA_WIDTHS.upToSmall}px) {
top: 50px;
}
`
const FlyoutRow = styled.div<{ active: boolean }>`
align-items: center;
@@ -210,51 +219,112 @@ function Row({
return rowContent
}
const getParsedChainId = (parsedQs?: ParsedQs) => {
const chain = parsedQs?.chain
if (!chain || typeof chain !== 'string') return { urlChain: undefined, urlChainId: undefined }
return { urlChain: chain.toLowerCase(), urlChainId: getChainIdFromName(chain) }
}
const getChainIdFromName = (name: string) => {
const entry = Object.entries(CHAIN_IDS_TO_NAMES).find(([_, n]) => n === name)
const chainId = entry?.[0]
return chainId ? parseInt(chainId) : undefined
}
const getChainNameFromId = (id: string | number) => {
// casting here may not be right but fine to return undefined if it's not a supported chain ID
return CHAIN_IDS_TO_NAMES[id as SupportedChainId] || ''
}
export default function NetworkSelector() {
const { chainId, library } = useActiveWeb3React()
const parsedQs = useParsedQueryString()
const { urlChain, urlChainId } = getParsedChainId(parsedQs)
const prevChainId = usePrevious(chainId)
const node = useRef<HTMLDivElement>()
const open = useModalOpen(ApplicationModal.NETWORK_SELECTOR)
const toggle = useToggleModal(ApplicationModal.NETWORK_SELECTOR)
useOnClickOutside(node, open ? toggle : undefined)
const history = useHistory()
const info = chainId ? CHAIN_INFO[chainId] : undefined
const dispatch = useAppDispatch()
const handleRowClick = useCallback(
(targetChain: number) => {
const handleChainSwitch = useCallback(
(targetChain: number, skipToggle?: boolean) => {
if (!library) return
switchToNetwork({ library, chainId: targetChain })
.then(() => toggle())
.then(() => {
if (!skipToggle) {
toggle()
}
history.replace({
search: replaceURLParam(history.location.search, 'chain', getChainNameFromId(targetChain)),
})
})
.catch((error) => {
console.error('Failed to switch networks', error)
toggle()
// we want app network <-> chainId param to be in sync, so if user changes the network by changing the URL
// but the request fails, revert the URL back to current chainId
if (chainId) {
history.replace({ search: replaceURLParam(history.location.search, 'chain', getChainNameFromId(chainId)) })
}
if (!skipToggle) {
toggle()
}
dispatch(addPopup({ content: { failedSwitchNetwork: targetChain }, key: `failed-network-switch` }))
})
},
[dispatch, library, toggle]
[dispatch, library, toggle, history, chainId]
)
useEffect(() => {
if (!chainId || !prevChainId) return
// when network change originates from wallet or dropdown selector, just update URL
if (chainId !== prevChainId) {
history.replace({ search: replaceURLParam(history.location.search, 'chain', getChainNameFromId(chainId)) })
// otherwise assume network change originates from URL
} else if (urlChainId && urlChainId !== chainId) {
handleChainSwitch(urlChainId, true)
}
}, [chainId, urlChainId, prevChainId, handleChainSwitch, history])
// set chain parameter on initial load if not there
useEffect(() => {
if (chainId && !urlChainId) {
history.replace({ search: replaceURLParam(history.location.search, 'chain', getChainNameFromId(chainId)) })
}
}, [chainId, history, urlChainId, urlChain])
if (!chainId || !info || !library) {
return null
}
return (
<SelectorWrapper ref={node as any}>
<SelectorControls onClick={toggle} interactive>
<SelectorWrapper ref={node as any} onMouseEnter={toggle} onMouseLeave={toggle}>
<SelectorControls interactive>
<SelectorLogo interactive src={info.logoUrl} />
<SelectorLabel>{info.label}</SelectorLabel>
<StyledChevronDown />
</SelectorControls>
{open && (
<FlyoutMenu onMouseLeave={toggle}>
<FlyoutHeader>
<Trans>Select a network</Trans>
</FlyoutHeader>
<Row onSelectChain={handleRowClick} targetChain={SupportedChainId.MAINNET} />
<Row onSelectChain={handleRowClick} targetChain={SupportedChainId.POLYGON} />
<Row onSelectChain={handleRowClick} targetChain={SupportedChainId.OPTIMISM} />
<Row onSelectChain={handleRowClick} targetChain={SupportedChainId.ARBITRUM_ONE} />
<FlyoutMenu>
<FlyoutMenuContents>
<FlyoutHeader>
<Trans>Select a network</Trans>
</FlyoutHeader>
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.MAINNET} />
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.POLYGON} />
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.OPTIMISM} />
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.ARBITRUM_ONE} />
</FlyoutMenuContents>
</FlyoutMenu>
)}
</SelectorWrapper>

View File

@@ -1,15 +1,15 @@
import { Trans } from '@lingui/macro'
import { RowFixed } from 'components/Row'
import { CHAIN_INFO } from 'constants/chains'
import { CHAIN_INFO } from 'constants/chainInfo'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
import useGasPrice from 'hooks/useGasPrice'
import useMachineTimeMs from 'hooks/useMachineTime'
import useTheme from 'hooks/useTheme'
import { useActiveWeb3React } from 'hooks/web3'
import JSBI from 'jsbi'
import useBlockNumber from 'lib/hooks/useBlockNumber'
import ms from 'ms.macro'
import { useEffect, useState } from 'react'
import { useBlockNumber } from 'state/application/hooks'
import styled, { keyframes } from 'styled-components/macro'
import { ExternalLink, ThemedText } from 'theme'
import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink'

View File

@@ -1,6 +1,8 @@
import { Trans } from '@lingui/macro'
import useScrollPosition from '@react-hook/window-scroll'
import { CHAIN_INFO, SupportedChainId } from 'constants/chains'
import { CHAIN_INFO } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useTheme from 'hooks/useTheme'
import { darken } from 'polished'
import { NavLink } from 'react-router-dom'
@@ -13,7 +15,6 @@ import { useNativeCurrencyBalances } from 'state/wallet/hooks'
import styled from 'styled-components/macro'
import { ReactComponent as Logo } from '../../assets/svg/logo.svg'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink, ThemedText } from '../../theme'
import ClaimModal from '../claim/ClaimModal'
import { CardNoise } from '../earn/styled'
@@ -263,9 +264,7 @@ export default function Header() {
const {
infoLink,
addNetworkInfo: {
nativeCurrency: { symbol: nativeCurrencySymbol },
},
nativeCurrency: { symbol: nativeCurrencySymbol },
} = CHAIN_INFO[chainId ? chainId : SupportedChainId.MAINNET]
return (

View File

@@ -1,5 +1,5 @@
import { AbstractConnector } from '@web3-react/abstract-connector'
import { Connector } from 'widgets-web3-react/types'
import { Connector } from '@web3-react/types'
import { AbstractConnector } from 'web3-react-abstract-connector'
import CoinbaseWalletIcon from '../../assets/images/coinbaseWalletIcon.svg'
import FortmaticIcon from '../../assets/images/fortmaticIcon.png'

View File

@@ -1,10 +1,9 @@
import jazzicon from '@metamask/jazzicon'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useENSAvatar from 'hooks/useENSAvatar'
import { useLayoutEffect, useMemo, useRef, useState } from 'react'
import styled from 'styled-components/macro'
import { useActiveWeb3React } from '../../hooks/web3'
const StyledIdenticon = styled.div`
height: 1rem;
width: 1rem;

View File

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

View File

@@ -4,6 +4,7 @@ import { PrivacyPolicyModal } from 'components/PrivacyPolicy'
import { L2_CHAIN_IDS } from 'constants/chains'
import { LOCALE_LABEL, SUPPORTED_LOCALES, SupportedLocale } from 'constants/locales'
import { useActiveLocale } from 'hooks/useActiveLocale'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useLocationLinkProps } from 'hooks/useLocationLinkProps'
import React, { useEffect, useRef, useState } from 'react'
import {
@@ -25,7 +26,6 @@ import styled, { css } from 'styled-components/macro'
import { ReactComponent as MenuIcon } from '../../assets/images/menu.svg'
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
import { useActiveWeb3React } from '../../hooks/web3'
import { useModalOpen, useToggleModal } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { ExternalLink } from '../../theme'

View File

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

View File

@@ -1,12 +1,12 @@
import { Trans } from '@lingui/macro'
import { CHAIN_INFO } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { ArrowUpRight } from 'react-feather'
import { useDarkModeManager } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { ExternalLink, HideSmall } from 'theme'
import { CHAIN_INFO } from '../../constants/chains'
import { AutoRow } from '../Row'
const L2Icon = styled.img`

View File

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

View File

@@ -0,0 +1,139 @@
import { Trans } from '@lingui/macro'
import FlagImage from 'assets/images/ukraine.png'
import { AutoColumn } from 'components/Column'
import { RowBetween, RowFixed } from 'components/Row'
import { X } from 'react-feather'
import ReactGA from 'react-ga'
import { useDarkModeManager, useShowDonationLink } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { ExternalLink, ThemedText, Z_INDEX } from 'theme'
const darkGradient = `radial-gradient(87.53% 3032.45% at 5.16% 10.13%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%),
linear-gradient(0deg, rgba(0, 91, 187, 0.35), rgba(0, 91, 187, 0.35)), #000000;`
const lightGradient = `radial-gradient(87.53% 3032.45% at 5.16% 10.13%, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%), linear-gradient(0deg, #CBE4FF, #CBE4FF), linear-gradient(0deg, rgba(255, 255, 255, 0.09), rgba(255, 255, 255, 0.09)), radial-gradient(100% 93.36% at 0% 6.64%, #8BC4FF 0%, #FFF5BF 100%);`
const Wrapper = styled(AutoColumn)<{ darkMode: boolean }>`
background: #edeef2;
position: fixed;
bottom: 40px;
border-radius: 12px;
padding: 18px;
max-width: 360px;
background: ${({ darkMode }) => (darkMode ? darkGradient : lightGradient)};
color: ${({ theme }) => theme.text1};
z-index: ${Z_INDEX.deprecated_content};
:hover {
opacity: 0.8;
}
& > * {
z-index: ${Z_INDEX.fixed};
}
overflow: hidden;
:before {
background-image: url(${FlagImage});
background-repeat: no-repeat;
overflow: hidden;
background-size: 300px;
content: '';
height: 1200px;
width: 400px;
opacity: 0.1;
position: absolute;
transform: rotate(25deg) translate(-140px, -60px);
width: 300px;
z-index: ${Z_INDEX.deprecated_zero};
}
${({ theme }) => theme.mediaWidth.upToSmall`
max-width: 100%;
`}
${({ theme }) => theme.mediaWidth.upToMedium`
position: relative;
bottom: unset;
`}
`
const WrappedCloseIcon = styled(X)`
stroke: ${({ theme }) => theme.text2};
z-index: ${Z_INDEX.tooltip};
:hover {
cursor: pointer;
opacity: 0.8;
}
`
export const StyledFlagImage = styled.div`
margin-right: 12px;
width: 18px;
height: 18px;
border-radius: 100%;
&:before,
&:after {
content: '';
width: 9px;
height: 18px;
}
&:before {
float: left;
border-top-left-radius: 9px;
border-bottom-left-radius: 9px;
background: #005bbb;
}
&:after {
float: right;
border-top-right-radius: 9px;
border-bottom-right-radius: 9px;
background: #ffd500;
}
transform: rotate(90deg);
`
const StyledLink = styled(ExternalLink)`
text-decoration: none !important;
`
export default function DonationLink() {
const [darkMode] = useDarkModeManager()
const [, setVisible] = useShowDonationLink()
return (
<Wrapper
gap="10px"
darkMode={darkMode}
as={StyledLink}
target="https://donate.uniswap.org/#/swap"
href="https://donate.uniswap.org/#/swap"
onClickCapture={() => {
ReactGA.event({
category: 'Donate',
action: 'Link to Ukraine site.',
})
}}
>
<RowBetween>
<RowFixed>
<StyledFlagImage />
<ThemedText.Body fontWeight={600} fontSize={'18px'}>
<Trans>Donate to Ukraine</Trans>
</ThemedText.Body>
</RowFixed>
<WrappedCloseIcon
onClick={(e) => {
e.preventDefault()
e.stopPropagation()
setVisible(false)
return false
}}
/>
</RowBetween>
<ThemedText.Body fontWeight={400} fontSize="12px" color="text2">
<Trans>Directly support the Ukrainian government by donating tokens.</Trans>
</ThemedText.Body>
</Wrapper>
)
}

View File

@@ -1,9 +1,10 @@
import { Trans } from '@lingui/macro'
import { CHAIN_INFO } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains'
import { useContext } from 'react'
import { AlertCircle } from 'react-feather'
import styled, { ThemeContext } from 'styled-components/macro'
import { CHAIN_INFO, SupportedChainId } from '../../constants/chains'
import { ThemedText } from '../../theme'
import { AutoColumn } from '../Column'
import { AutoRow } from '../Row'

View File

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

View File

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

View File

@@ -1,12 +1,14 @@
import { SupportedChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useLocation } from 'react-router-dom'
import styled from 'styled-components/macro'
import { MEDIA_WIDTHS } from 'theme'
import { useActivePopups } from '../../state/application/hooks'
import { useURLWarningVisible } from '../../state/user/hooks'
import { useShowDonationLink, useURLWarningVisible } from '../../state/user/hooks'
import { AutoColumn } from '../Column'
import ClaimPopup from './ClaimPopup'
import DonationLink from './DonationLink'
import PopupItem from './PopupItem'
const MobilePopupWrapper = styled.div<{ height: string | number }>`
@@ -14,11 +16,12 @@ const MobilePopupWrapper = styled.div<{ height: string | number }>`
max-width: 100%;
height: ${({ height }) => height};
margin: ${({ height }) => (height ? '0 auto;' : 0)};
margin-bottom: ${({ height }) => (height ? '20px' : 0)}};
margin-bottom: ${({ height }) => (height ? '20px' : 0)};
display: none;
${({ theme }) => theme.mediaWidth.upToSmall`
display: block;
padding-top: 20px;
`};
`
@@ -65,6 +68,11 @@ export default function Popups() {
const { chainId } = useActiveWeb3React()
const isNotOnMainnet = Boolean(chainId && chainId !== SupportedChainId.MAINNET)
const location = useLocation()
const isOnSwapPage = location.pathname.includes('swap')
const [donationVisible] = useShowDonationLink()
const showDonation = donationVisible && isOnSwapPage
return (
<>
<FixedPopupColumn gap="20px" extraPadding={urlWarningActive} xlPadding={isNotOnMainnet}>
@@ -72,9 +80,11 @@ export default function Popups() {
{activePopups.map((item) => (
<PopupItem key={item.key} content={item.content} popKey={item.key} removeAfterMs={item.removeAfterMs} />
))}
{showDonation ? <DonationLink /> : null}
</FixedPopupColumn>
<MobilePopupWrapper height={activePopups?.length > 0 ? 'fit-content' : 0}>
<MobilePopupWrapper height={activePopups?.length > 0 || showDonation ? 'fit-content' : 0}>
<MobilePopupInner>
{showDonation ? <DonationLink /> : null}
{activePopups // reverse so new items up front
.slice(0)
.reverse()

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
import { Protocol } from '@uniswap/router-sdk'
import { Currency, Percent } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk'
import { DAI, USDC, WBTC } from 'constants/tokens'
import { DAI, USDC_MAINNET, WBTC } from 'constants/tokens'
import { render } from 'test-utils'
import RoutingDiagram, { RoutingDiagramEntry } from './RoutingDiagram'
@@ -10,16 +10,16 @@ const percent = (strings: TemplateStringsArray) => new Percent(parseInt(strings[
const singleRoute: RoutingDiagramEntry = {
percent: percent`100`,
path: [[USDC, DAI, FeeAmount.LOW]],
path: [[USDC_MAINNET, DAI, FeeAmount.LOW]],
protocol: Protocol.V3,
}
const multiRoute: RoutingDiagramEntry[] = [
{ percent: percent`75`, path: [[USDC, DAI, FeeAmount.LOWEST]], protocol: Protocol.V2 },
{ percent: percent`75`, path: [[USDC_MAINNET, DAI, FeeAmount.LOWEST]], protocol: Protocol.V2 },
{
percent: percent`25`,
path: [
[USDC, WBTC, FeeAmount.MEDIUM],
[USDC_MAINNET, WBTC, FeeAmount.MEDIUM],
[WBTC, DAI, FeeAmount.HIGH],
],
protocol: Protocol.V3,
@@ -47,16 +47,16 @@ jest.mock('hooks/useTokenInfoFromActiveList', () => ({
}))
it('renders when no routes are provided', () => {
const { asFragment } = render(<RoutingDiagram currencyIn={DAI} currencyOut={USDC} routes={[]} />)
const { asFragment } = render(<RoutingDiagram currencyIn={DAI} currencyOut={USDC_MAINNET} routes={[]} />)
expect(asFragment()).toMatchSnapshot()
})
it('renders single route', () => {
const { asFragment } = render(<RoutingDiagram currencyIn={USDC} currencyOut={DAI} routes={[singleRoute]} />)
const { asFragment } = render(<RoutingDiagram currencyIn={USDC_MAINNET} currencyOut={DAI} routes={[singleRoute]} />)
expect(asFragment()).toMatchSnapshot()
})
it('renders multi route', () => {
const { asFragment } = render(<RoutingDiagram currencyIn={USDC} currencyOut={DAI} routes={multiRoute} />)
const { asFragment } = render(<RoutingDiagram currencyIn={USDC_MAINNET} currencyOut={DAI} routes={multiRoute} />)
expect(asFragment()).toMatchSnapshot()
})

View File

@@ -1,12 +1,12 @@
import { Trans } from '@lingui/macro'
import { Protocol } from '@uniswap/router-sdk'
import { Currency, Percent } from '@uniswap/sdk-core'
import { Currency } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk'
import Badge from 'components/Badge'
import CurrencyLogo from 'components/CurrencyLogo'
import DoubleCurrencyLogo from 'components/DoubleLogo'
import Row, { AutoRow } from 'components/Row'
import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList'
import { RoutingDiagramEntry } from 'lib/components/Swap/RoutingDiagram/utils'
import { Box } from 'rebass'
import styled from 'styled-components/macro'
import { ThemedText, Z_INDEX } from 'theme'
@@ -14,12 +14,6 @@ import { ThemedText, Z_INDEX } from 'theme'
import { ReactComponent as DotLine } from '../../assets/svg/dot_line.svg'
import { MouseoverTooltip } from '../Tooltip'
export interface RoutingDiagramEntry {
percent: Percent
path: [Currency, Currency, FeeAmount][]
protocol: Protocol
}
const Wrapper = styled(Box)`
align-items: center;
width: 100%;

View File

@@ -3,45 +3,45 @@
exports[`renders multi route 1`] = `
<DocumentFragment>
<div
class="RoutingDiagram__Wrapper-sc-o1ook0-0 ePDWDk css-vurnku"
class="RoutingDiagram__Wrapper-sc-i2tbb-0 ivndgC css-vurnku"
>
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteContainerRow-sc-o1ook0-1 lmTMKd itvFNV ibRCpr"
class="sc-bdnxRM Row-sc-u7azg8-0 RoutingDiagram__RouteContainerRow-sc-i2tbb-1 lmTMKd hLLNig hDkZVB"
>
CurrencyLogo currency=USDC
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteRow-sc-o1ook0-2 lmTMKd itvFNV fzMiot"
class="sc-bdnxRM Row-sc-u7azg8-0 RoutingDiagram__RouteRow-sc-i2tbb-2 lmTMKd hLLNig hUDqOH"
>
<div
class="RoutingDiagram__DottedLine-sc-o1ook0-4 kkXINS"
class="RoutingDiagram__DottedLine-sc-i2tbb-4 cKqYfU"
>
<svg
class="RoutingDiagram__DotColor-sc-o1ook0-5 kgYqrO"
class="RoutingDiagram__DotColor-sc-i2tbb-5 fhSaBA"
>
dot_line.svg
</svg>
</div>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-6 gayll OurGh"
class="Badge-sc-3epor3-0 RoutingDiagram__OpaqueBadge-sc-i2tbb-6 knpfHF gGARxH"
>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__ProtocolBadge-sc-o1ook0-7 gayll bNVqMw"
class="Badge-sc-3epor3-0 RoutingDiagram__ProtocolBadge-sc-i2tbb-7 knpfHF lbdUti"
>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-15li2d9"
class="theme__TextWrapper-sc-5lu8um-0 chxxqs RoutingDiagram__BadgeText-sc-i2tbb-8 ijjHig css-15li2d9"
>
V2
</div>
</div>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-1aekuku"
class="theme__TextWrapper-sc-5lu8um-0 chxxqs RoutingDiagram__BadgeText-sc-i2tbb-8 ijjHig css-1aekuku"
style="min-width: auto;"
>
75%
</div>
</div>
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 Row__AutoRow-sc-nrd8cx-3 iqvZFe itvFNV kkMfuq"
class="sc-bdnxRM Row-sc-u7azg8-0 Row__AutoRow-sc-u7azg8-3 iqvZFe hLLNig cUhARX"
style="justify-content: space-evenly; z-index: 2;"
width="100%"
>
@@ -51,42 +51,42 @@ exports[`renders multi route 1`] = `
CurrencyLogo currency=DAI
</div>
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteContainerRow-sc-o1ook0-1 lmTMKd itvFNV ibRCpr"
class="sc-bdnxRM Row-sc-u7azg8-0 RoutingDiagram__RouteContainerRow-sc-i2tbb-1 lmTMKd hLLNig hDkZVB"
>
CurrencyLogo currency=USDC
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteRow-sc-o1ook0-2 lmTMKd itvFNV fzMiot"
class="sc-bdnxRM Row-sc-u7azg8-0 RoutingDiagram__RouteRow-sc-i2tbb-2 lmTMKd hLLNig hUDqOH"
>
<div
class="RoutingDiagram__DottedLine-sc-o1ook0-4 kkXINS"
class="RoutingDiagram__DottedLine-sc-i2tbb-4 cKqYfU"
>
<svg
class="RoutingDiagram__DotColor-sc-o1ook0-5 kgYqrO"
class="RoutingDiagram__DotColor-sc-i2tbb-5 fhSaBA"
>
dot_line.svg
</svg>
</div>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-6 gayll OurGh"
class="Badge-sc-3epor3-0 RoutingDiagram__OpaqueBadge-sc-i2tbb-6 knpfHF gGARxH"
>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__ProtocolBadge-sc-o1ook0-7 gayll bNVqMw"
class="Badge-sc-3epor3-0 RoutingDiagram__ProtocolBadge-sc-i2tbb-7 knpfHF lbdUti"
>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-15li2d9"
class="theme__TextWrapper-sc-5lu8um-0 chxxqs RoutingDiagram__BadgeText-sc-i2tbb-8 ijjHig css-15li2d9"
>
V3
</div>
</div>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-1aekuku"
class="theme__TextWrapper-sc-5lu8um-0 chxxqs RoutingDiagram__BadgeText-sc-i2tbb-8 ijjHig css-1aekuku"
style="min-width: auto;"
>
25%
</div>
</div>
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 Row__AutoRow-sc-nrd8cx-3 iqvZFe itvFNV kkMfuq"
class="sc-bdnxRM Row-sc-u7azg8-0 Row__AutoRow-sc-u7azg8-3 iqvZFe hLLNig cUhARX"
style="justify-content: space-evenly; z-index: 2;"
width="100%"
>
@@ -102,45 +102,45 @@ exports[`renders multi route 1`] = `
exports[`renders single route 1`] = `
<DocumentFragment>
<div
class="RoutingDiagram__Wrapper-sc-o1ook0-0 ePDWDk css-vurnku"
class="RoutingDiagram__Wrapper-sc-i2tbb-0 ivndgC css-vurnku"
>
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteContainerRow-sc-o1ook0-1 lmTMKd itvFNV ibRCpr"
class="sc-bdnxRM Row-sc-u7azg8-0 RoutingDiagram__RouteContainerRow-sc-i2tbb-1 lmTMKd hLLNig hDkZVB"
>
CurrencyLogo currency=USDC
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 RoutingDiagram__RouteRow-sc-o1ook0-2 lmTMKd itvFNV fzMiot"
class="sc-bdnxRM Row-sc-u7azg8-0 RoutingDiagram__RouteRow-sc-i2tbb-2 lmTMKd hLLNig hUDqOH"
>
<div
class="RoutingDiagram__DottedLine-sc-o1ook0-4 kkXINS"
class="RoutingDiagram__DottedLine-sc-i2tbb-4 cKqYfU"
>
<svg
class="RoutingDiagram__DotColor-sc-o1ook0-5 kgYqrO"
class="RoutingDiagram__DotColor-sc-i2tbb-5 fhSaBA"
>
dot_line.svg
</svg>
</div>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__OpaqueBadge-sc-o1ook0-6 gayll OurGh"
class="Badge-sc-3epor3-0 RoutingDiagram__OpaqueBadge-sc-i2tbb-6 knpfHF gGARxH"
>
<div
class="Badge-sc-1mhw5si-0 RoutingDiagram__ProtocolBadge-sc-o1ook0-7 gayll bNVqMw"
class="Badge-sc-3epor3-0 RoutingDiagram__ProtocolBadge-sc-i2tbb-7 knpfHF lbdUti"
>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-15li2d9"
class="theme__TextWrapper-sc-5lu8um-0 chxxqs RoutingDiagram__BadgeText-sc-i2tbb-8 ijjHig css-15li2d9"
>
V3
</div>
</div>
<div
class="theme__TextWrapper-sc-18nh1jk-0 cWOfab RoutingDiagram__BadgeText-sc-o1ook0-8 dYpdfO css-1aekuku"
class="theme__TextWrapper-sc-5lu8um-0 chxxqs RoutingDiagram__BadgeText-sc-i2tbb-8 ijjHig css-1aekuku"
style="min-width: auto;"
>
100%
</div>
</div>
<div
class="sc-bdnxRM Row-sc-nrd8cx-0 Row__AutoRow-sc-nrd8cx-3 iqvZFe itvFNV kkMfuq"
class="sc-bdnxRM Row-sc-u7azg8-0 Row__AutoRow-sc-u7azg8-3 iqvZFe hLLNig cUhARX"
style="justify-content: space-evenly; z-index: 2;"
width="100%"
>
@@ -156,7 +156,7 @@ exports[`renders single route 1`] = `
exports[`renders when no routes are provided 1`] = `
<DocumentFragment>
<div
class="RoutingDiagram__Wrapper-sc-o1ook0-0 ePDWDk css-vurnku"
class="RoutingDiagram__Wrapper-sc-i2tbb-0 ivndgC css-vurnku"
/>
</DocumentFragment>
`;

View File

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

View File

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

View File

@@ -48,7 +48,7 @@ export function ImportToken(props: ImportProps) {
<RowBetween>
{onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div />}
<ThemedText.MediumHeader>
<Plural value={tokens.length} one="Import token" other="Import tokens" />
<Plural value={tokens.length} _1="Import token" other="Import tokens" />
</ThemedText.MediumHeader>
{onDismiss ? <CloseIcon onClick={onDismiss} /> : <div />}
</RowBetween>

View File

@@ -3,8 +3,8 @@ import { t, Trans } from '@lingui/macro'
import { TokenList } from '@uniswap/token-lists'
import Card from 'components/Card'
import { UNSUPPORTED_LIST_URLS } from 'constants/lists'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useListColor } from 'hooks/useColor'
import { useActiveWeb3React } from 'hooks/web3'
import parseENSAddress from 'lib/utils/parseENSAddress'
import uriToHttp from 'lib/utils/uriToHttp'
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'

View File

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

View File

@@ -6,7 +6,7 @@ import { AutoColumn } from 'components/Column'
import CurrencyLogo from 'components/CurrencyLogo'
import ListLogo from 'components/ListLogo'
import { RowFixed } from 'components/Row'
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { transparentize } from 'polished'
import { AlertCircle } from 'react-feather'
import styled, { useTheme } from 'styled-components/macro'

View File

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

View File

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

View File

@@ -1,12 +1,12 @@
// eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro'
import { Percent } from '@uniswap/sdk-core'
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { AUTO_ROUTER_SUPPORTED_CHAINS } from 'lib/hooks/routing/clientSideSmartOrderRouter'
import { useContext, useRef, useState } from 'react'
import { Settings, X } from 'react-feather'
import ReactGA from 'react-ga'
import { Text } from 'rebass'
import { AUTO_ROUTER_SUPPORTED_CHAINS } from 'state/routing/clientSideSmartOrderRouter/constants'
import styled, { ThemeContext } from 'styled-components/macro'
import { useOnClickOutside } from '../../hooks/useOnClickOutside'

View File

@@ -1,7 +1,9 @@
import { Trans } from '@lingui/macro'
import { Currency } from '@uniswap/sdk-core'
import Badge from 'components/Badge'
import { CHAIN_INFO, L2_CHAIN_IDS, SupportedL2ChainId } from 'constants/chains'
import { CHAIN_INFO } from 'constants/chainInfo'
import { L2_CHAIN_IDS, SupportedL2ChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useAddTokenToMetamask from 'hooks/useAddTokenToMetamask'
import { ReactNode, useContext } from 'react'
import { AlertCircle, AlertTriangle, ArrowUpCircle, CheckCircle } from 'react-feather'
@@ -11,7 +13,6 @@ import styled, { ThemeContext } from 'styled-components/macro'
import Circle from '../../assets/images/blue-loader.svg'
import MetaMaskLogo from '../../assets/images/metamask.png'
import { useActiveWeb3React } from '../../hooks/web3'
import { ExternalLink } from '../../theme'
import { CloseIcon, CustomLightSpinner } from '../../theme'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'

View File

@@ -2,7 +2,7 @@ import { Trans } from '@lingui/macro'
import { Percent } from '@uniswap/sdk-core'
import { L2_CHAIN_IDS } from 'constants/chains'
import { DEFAULT_DEADLINE_FROM_NOW } from 'constants/misc'
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import ms from 'ms.macro'
import { darken } from 'polished'
import { useContext, useState } from 'react'

View File

@@ -1,7 +1,7 @@
import { Trans } from '@lingui/macro'
import { AbstractConnector } from '@web3-react/abstract-connector'
import { darken } from 'polished'
import styled from 'styled-components/macro'
import { AbstractConnector } from 'web3-react-abstract-connector'
import { injected } from '../../connectors'
import { SUPPORTED_WALLETS } from '../../constants/wallet'

View File

@@ -1,7 +1,4 @@
import { Trans } from '@lingui/macro'
import { AbstractConnector } from '@web3-react/abstract-connector'
import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core'
import { WalletConnectConnector } from '@web3-react/walletconnect-connector'
import { AutoColumn } from 'components/Column'
import { PrivacyPolicy } from 'components/PrivacyPolicy'
import Row, { AutoRow, RowBetween } from 'components/Row'
@@ -10,6 +7,9 @@ import { useEffect, useState } from 'react'
import { ArrowLeft, ArrowRight, Info } from 'react-feather'
import ReactGA from 'react-ga'
import styled from 'styled-components/macro'
import { AbstractConnector } from 'web3-react-abstract-connector'
import { UnsupportedChainIdError, useWeb3React } from 'web3-react-core'
import { WalletConnectConnector } from 'web3-react-walletconnect-connector'
import MetamaskIcon from '../../assets/images/metamask.png'
import { ReactComponent as Close } from '../../assets/images/x.svg'

View File

@@ -1,7 +1,7 @@
import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core'
import { useEffect } from 'react'
import styled from 'styled-components/macro'
import { useWeb3React } from 'web3-react-core'
import { network } from '../../connectors'
import { NetworkContextName } from '../../constants/misc'

View File

@@ -1,12 +1,12 @@
// eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro'
import { AbstractConnector } from '@web3-react/abstract-connector'
import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core'
import { Connector } from '@web3-react/types'
import { darken } from 'polished'
import { useMemo } from 'react'
import { Activity } from 'react-feather'
import styled, { css } from 'styled-components/macro'
import { Connector } from 'widgets-web3-react/types'
import { AbstractConnector } from 'web3-react-abstract-connector'
import { UnsupportedChainIdError, useWeb3React } from 'web3-react-core'
import { NetworkContextName } from '../../constants/misc'
import useENSName from '../../hooks/useENSName'

View File

@@ -1,9 +1,11 @@
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useEffect } from 'react'
import ReactGA from 'react-ga'
import { RouteComponentProps } from 'react-router-dom'
import { getCLS, getFCP, getFID, getLCP, Metric } from 'web-vitals'
import { GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY } from './index'
function reportWebVitals({ name, delta, id }: Metric) {
ReactGA.timing({
category: 'Web Vitals',
@@ -31,5 +33,15 @@ export default function GoogleAnalyticsReporter({ location: { pathname, search }
useEffect(() => {
ReactGA.pageview(`${pathname}${search}`)
}, [pathname, search])
useEffect(() => {
// typed as 'any' in react-ga -.-
ReactGA.ga((tracker: any) => {
if (!tracker) return
const clientId = tracker.get('clientId')
window.localStorage.setItem(GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY, clientId)
})
}, [])
return null
}

View File

@@ -1,12 +1,17 @@
import ReactGA from 'react-ga'
import { isMobile } from 'utils/userAgent'
export const GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY = 'ga_client_id'
const GOOGLE_ANALYTICS_ID: string | undefined = process.env.REACT_APP_GOOGLE_ANALYTICS_ID
const storedClientId = window.localStorage.getItem(GOOGLE_ANALYTICS_CLIENT_ID_STORAGE_KEY)
if (typeof GOOGLE_ANALYTICS_ID === 'string') {
ReactGA.initialize(GOOGLE_ANALYTICS_ID, {
gaOptions: {
storage: 'none',
storeGac: false,
clientId: storedClientId ?? undefined,
},
})
ReactGA.set({

View File

@@ -1,6 +1,7 @@
import { isAddress } from '@ethersproject/address'
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { isAddress } from 'ethers/lib/utils'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useState } from 'react'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
@@ -8,7 +9,6 @@ import styled from 'styled-components/macro'
import Circle from '../../assets/images/blue-loader.svg'
import tokenLogo from '../../assets/images/token-logo.png'
import useENS from '../../hooks/useENS'
import { useActiveWeb3React } from '../../hooks/web3'
import { useClaimCallback, useUserHasAvailableClaim, useUserUnclaimedAmount } from '../../state/claim/hooks'
import { useIsTransactionPending } from '../../state/transactions/hooks'
import { CloseIcon, CustomLightSpinner, ExternalLink, ThemedText, UniTokenAnimated } from '../../theme'

View File

@@ -1,6 +1,7 @@
import { isAddress } from '@ethersproject/address'
import { Trans } from '@lingui/macro'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { isAddress } from 'ethers/lib/utils'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import JSBI from 'jsbi'
import { useEffect, useState } from 'react'
import { Text } from 'rebass'
@@ -8,7 +9,6 @@ import styled from 'styled-components/macro'
import Circle from '../../assets/images/blue-loader.svg'
import tokenLogo from '../../assets/images/token-logo.png'
import { useActiveWeb3React } from '../../hooks/web3'
import { useModalOpen, useToggleSelfClaimModal } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { useClaimCallback, useUserClaimData, useUserUnclaimedAmount } from '../../state/claim/hooks'

View File

@@ -1,10 +1,11 @@
import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import type { providers } from 'ethers'
import StakingRewardsJson from '@uniswap/liquidity-staker/build/StakingRewards.json'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { ReactNode, useState } from 'react'
import styled from 'styled-components/macro'
import { useStakingContract } from '../../hooks/useContract'
import { useActiveWeb3React } from '../../hooks/web3'
import { useContract } from '../../hooks/useContract'
import { StakingInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'
@@ -15,6 +16,12 @@ import Modal from '../Modal'
import { LoadingView, SubmittedView } from '../ModalViews'
import { RowBetween } from '../Row'
const { abi: STAKING_REWARDS_ABI } = StakingRewardsJson
function useStakingContract(stakingAddress?: string, withSignerIfPossible?: boolean) {
return useContract(stakingAddress, STAKING_REWARDS_ABI, withSignerIfPossible)
}
const ContentWrapper = styled(AutoColumn)`
width: 100%;
padding: 1rem;
@@ -47,7 +54,7 @@ export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: Sta
setAttempting(true)
await stakingContract
.getReward({ gasLimit: 350000 })
.then((response: providers.TransactionResponse) => {
.then((response: TransactionResponse) => {
addTransaction(response, {
type: TransactionType.CLAIM,
recipient: account,

View File

@@ -1,15 +1,16 @@
import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import StakingRewardsJson from '@uniswap/liquidity-staker/build/StakingRewards.json'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import type { providers } from 'ethers'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useV2LiquidityTokenPermit } from 'hooks/useV2LiquidityTokenPermit'
import { useCallback, useState } from 'react'
import styled from 'styled-components/macro'
import { ApprovalState, useApproveCallback } from '../../hooks/useApproveCallback'
import { usePairContract, useStakingContract, useV2RouterContract } from '../../hooks/useContract'
import { useV2LiquidityTokenPermit } from '../../hooks/useERC20Permit'
import { useContract, usePairContract, useV2RouterContract } from '../../hooks/useContract'
import useTransactionDeadline from '../../hooks/useTransactionDeadline'
import { useActiveWeb3React } from '../../hooks/web3'
import { StakingInfo, useDerivedStakeInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'
@@ -24,6 +25,12 @@ import { LoadingView, SubmittedView } from '../ModalViews'
import ProgressCircles from '../ProgressSteps'
import { RowBetween } from '../Row'
const { abi: STAKING_REWARDS_ABI } = StakingRewardsJson
function useStakingContract(stakingAddress?: string, withSignerIfPossible?: boolean) {
return useContract(stakingAddress, STAKING_REWARDS_ABI, withSignerIfPossible)
}
const HypotheticalRewardRate = styled.div<{ dim: boolean }>`
display: flex;
justify-content: space-between;
@@ -105,7 +112,7 @@ export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiqui
signatureData.s,
{ gasLimit: 350000 }
)
.then((response: providers.TransactionResponse) => {
.then((response: TransactionResponse) => {
addTransaction(response, {
type: TransactionType.DEPOSIT_LIQUIDITY_STAKING,
token0Address: stakingInfo.tokens[0].address,

View File

@@ -1,10 +1,11 @@
import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
import type { providers } from 'ethers'
import StakingRewardsJson from '@uniswap/liquidity-staker/build/StakingRewards.json'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { ReactNode, useState } from 'react'
import styled from 'styled-components/macro'
import { useStakingContract } from '../../hooks/useContract'
import { useActiveWeb3React } from '../../hooks/web3'
import { useContract } from '../../hooks/useContract'
import { StakingInfo } from '../../state/stake/hooks'
import { TransactionType } from '../../state/transactions/actions'
import { useTransactionAdder } from '../../state/transactions/hooks'
@@ -16,6 +17,12 @@ import Modal from '../Modal'
import { LoadingView, SubmittedView } from '../ModalViews'
import { RowBetween } from '../Row'
const { abi: STAKING_REWARDS_ABI } = StakingRewardsJson
function useStakingContract(stakingAddress?: string, withSignerIfPossible?: boolean) {
return useContract(stakingAddress, STAKING_REWARDS_ABI, withSignerIfPossible)
}
const ContentWrapper = styled(AutoColumn)`
width: 100%;
padding: 1rem;
@@ -48,7 +55,7 @@ export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: Staki
setAttempting(true)
await stakingContract
.exit({ gasLimit: 300000 })
.then((response: providers.TransactionResponse) => {
.then((response: TransactionResponse) => {
addTransaction(response, {
type: TransactionType.WITHDRAW_LIQUIDITY_STAKING,
token0Address: stakingInfo.tokens[0].address,

View File

@@ -2,7 +2,8 @@ import { Trans } from '@lingui/macro'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import Card from 'components/Card'
import { LoadingRows } from 'components/Loader/styled'
import { useActiveWeb3React } from 'hooks/web3'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useContext, useMemo } from 'react'
import { InterfaceTrade } from 'state/routing/types'
import styled, { ThemeContext } from 'styled-components/macro'
@@ -12,7 +13,6 @@ import { computeRealizedLPFeePercent } from '../../utils/prices'
import { AutoColumn } from '../Column'
import { RowBetween, RowFixed } from '../Row'
import FormattedPriceImpact from './FormattedPriceImpact'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from './GasEstimateBadge'
const StyledCard = styled(Card)`
padding: 0;

View File

@@ -0,0 +1,35 @@
import { useRef } from 'react'
let uniqueId = 0
const getUniqueId = () => uniqueId++
export default function AutoRouterIcon({ className, id }: { className?: string; id?: string }) {
const componentIdRef = useRef(id ?? getUniqueId())
const componentId = `AutoRouterIconGradient${componentIdRef.current}`
return (
<svg
width="23"
height="20"
viewBox="0 0 23 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<defs>
<linearGradient id={componentId} x1="0" y1="0" x2="1" y2="0" gradientTransform="rotate(95)">
<stop id="stop1" offset="0" stopColor="#2274E2" />
<stop id="stop1" offset="0.5" stopColor="#2274E2" />
<stop id="stop2" offset="1" stopColor="#3FB672" />
</linearGradient>
</defs>
<path
d="M16 16C10 16 9 10 5 10M16 16C16 17.6569 17.3431 19 19 19C20.6569 19 22 17.6569 22 16C22 14.3431 20.6569 13 19 13C17.3431 13 16 14.3431 16 16ZM5 10C9 10 10 4 16 4M5 10H1.5M16 4C16 5.65685 17.3431 7 19 7C20.6569 7 22 5.65685 22 4C22 2.34315 20.6569 1 19 1C17.3431 1 16 2.34315 16 4Z"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
stroke={`url(#${componentId})`}
/>
</svg>
)
}

View File

@@ -3,6 +3,7 @@ import { Trade } from '@uniswap/router-sdk'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { ReactNode, useCallback, useMemo } from 'react'
import { InterfaceTrade } from 'state/routing/types'
import { tradeMeaningfullyDiffers } from 'utils/tradeMeaningFullyDiffer'
import TransactionConfirmationModal, {
ConfirmationModalContent,
@@ -11,23 +12,6 @@ import TransactionConfirmationModal, {
import SwapModalFooter from './SwapModalFooter'
import SwapModalHeader from './SwapModalHeader'
/**
* Returns true if the trade requires a confirmation of details before we can submit it
* @param args either a pair of V2 trades or a pair of V3 trades
*/
function tradeMeaningfullyDiffers(
...args: [Trade<Currency, Currency, TradeType>, Trade<Currency, Currency, TradeType>]
): boolean {
const [tradeA, tradeB] = args
return (
tradeA.tradeType !== tradeB.tradeType ||
!tradeA.inputAmount.currency.equals(tradeB.inputAmount.currency) ||
!tradeA.inputAmount.equalTo(tradeB.inputAmount) ||
!tradeA.outputAmount.currency.equals(tradeB.outputAmount.currency) ||
!tradeA.outputAmount.equalTo(tradeB.outputAmount)
)
}
export default function ConfirmSwapModal({
trade,
originalTrade,

View File

@@ -10,7 +10,6 @@ import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { ReactComponent as GasIcon } from '../../assets/images/gas-icon.svg'
import { SupportedChainId } from '../../constants/chains'
import { ResponsiveTooltipContainer } from './styleds'
import SwapRoute from './SwapRoute'
@@ -32,8 +31,6 @@ const StyledGasIcon = styled(GasIcon)`
}
`
export const SUPPORTED_GAS_ESTIMATE_CHAIN_IDS = [SupportedChainId.MAINNET, SupportedChainId.POLYGON]
export default function GasEstimateBadge({
trade,
loading,

View File

@@ -3,8 +3,8 @@ import useAutoRouterSupported from 'hooks/useAutoRouterSupported'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { ReactComponent as AutoRouterIcon } from '../../assets/svg/auto_router.svg'
import { ReactComponent as StaticRouterIcon } from '../../assets/svg/static_route.svg'
import AutoRouterIcon from './AutoRouterIcon'
const StyledAutoRouterIcon = styled(AutoRouterIcon)`
height: 16px;

View File

@@ -6,7 +6,8 @@ import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer } from 'components/Loader/styled'
import Row, { RowBetween, RowFixed } from 'components/Row'
import { MouseoverTooltipContent } from 'components/Tooltip'
import { useActiveWeb3React } from 'hooks/web3'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { darken } from 'polished'
import { useState } from 'react'
import { ChevronDown, Info } from 'react-feather'
@@ -15,7 +16,7 @@ import styled, { keyframes, useTheme } from 'styled-components/macro'
import { HideSmall, ThemedText } from 'theme'
import { AdvancedSwapDetails } from './AdvancedSwapDetails'
import GasEstimateBadge, { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from './GasEstimateBadge'
import GasEstimateBadge from './GasEstimateBadge'
import { ResponsiveTooltipContainer } from './styleds'
import SwapRoute from './SwapRoute'
import TradePrice from './TradePrice'

View File

@@ -1,14 +1,14 @@
import { Trans } from '@lingui/macro'
import { Trade } from '@uniswap/router-sdk'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { Currency, TradeType } from '@uniswap/sdk-core'
import AnimatedDropdown from 'components/AnimatedDropdown'
import { AutoColumn } from 'components/Column'
import { LoadingRows } from 'components/Loader/styled'
import RoutingDiagram, { RoutingDiagramEntry } from 'components/RoutingDiagram/RoutingDiagram'
import RoutingDiagram from 'components/RoutingDiagram/RoutingDiagram'
import { AutoRow, RowBetween } from 'components/Row'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useAutoRouterSupported from 'hooks/useAutoRouterSupported'
import { useActiveWeb3React } from 'hooks/web3'
import { getTokenPath } from 'lib/components/Swap/RoutingDiagram/utils'
import { memo, useState } from 'react'
import { Plus } from 'react-feather'
import { InterfaceTrade } from 'state/routing/types'
@@ -16,7 +16,6 @@ import { useDarkModeManager } from 'state/user/hooks'
import styled from 'styled-components/macro'
import { Separator, ThemedText } from 'theme'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from './GasEstimateBadge'
import { AutoRouterLabel, AutoRouterLogo } from './RouterLabel'
const Wrapper = styled(AutoColumn)<{ darkMode?: boolean; fixedOpen?: boolean }>`
@@ -39,8 +38,6 @@ const OpenCloseIcon = styled(Plus)<{ open?: boolean }>`
}
`
const V2_DEFAULT_FEE_TIER = 3000
interface SwapRouteProps extends React.HTMLAttributes<HTMLDivElement> {
trade: InterfaceTrade<Currency, Currency, TradeType>
syncing: boolean
@@ -109,35 +106,3 @@ export default memo(function SwapRoute({ trade, syncing, fixedOpen = false, ...r
</Wrapper>
)
})
function getTokenPath(trade: Trade<Currency, Currency, TradeType>): RoutingDiagramEntry[] {
return trade.swaps.map(({ route: { path: tokenPath, pools, protocol }, inputAmount, outputAmount }) => {
const portion =
trade.tradeType === TradeType.EXACT_INPUT
? inputAmount.divide(trade.inputAmount)
: outputAmount.divide(trade.outputAmount)
const percent = new Percent(portion.numerator, portion.denominator)
const path: RoutingDiagramEntry['path'] = []
for (let i = 0; i < pools.length; i++) {
const nextPool = pools[i]
const tokenIn = tokenPath[i]
const tokenOut = tokenPath[i + 1]
const entry: RoutingDiagramEntry['path'][0] = [
tokenIn,
tokenOut,
nextPool instanceof Pair ? V2_DEFAULT_FEE_TIER : nextPool.fee,
]
path.push(entry)
}
return {
percent,
path,
protocol,
}
})
}

View File

@@ -16,7 +16,7 @@ const StyledPriceContainer = styled.button`
background-color: transparent;
border: none;
cursor: pointer;
align-items: center
align-items: center;
justify-content: flex-start;
padding: 0;
grid-template-columns: 1fr auto;

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
import { FortmaticConnector as FortmaticConnectorCore } from '@web3-react/fortmatic-connector'
import { FortmaticConnector as FortmaticConnectorCore } from 'web3-react-fortmatic-connector'
export const OVERLAY_READY = 'OVERLAY_READY'

View File

@@ -1,6 +1,6 @@
import { AbstractConnector } from '@web3-react/abstract-connector'
import { ConnectorUpdate } from '@web3-react/types'
import invariant from 'tiny-invariant'
import { AbstractConnector } from 'web3-react-abstract-connector'
import { ConnectorUpdate } from 'web3-react-types'
interface NetworkConnectorArguments {
urls: { [chainId: number]: string }

View File

@@ -1,12 +1,13 @@
import { Web3Provider } from '@ethersproject/providers'
import { SafeAppConnector } from '@gnosis.pm/safe-apps-web3-react'
import { InjectedConnector } from '@web3-react/injected-connector'
import { PortisConnector } from '@web3-react/portis-connector'
import { WalletConnectConnector } from '@web3-react/walletconnect-connector'
import { WalletLinkConnector } from '@web3-react/walletlink-connector'
import type { providers } from 'ethers'
import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from 'constants/chains'
import { INFURA_NETWORK_URLS } from 'constants/infura'
import { InjectedConnector } from 'web3-react-injected-connector'
import { PortisConnector } from 'web3-react-portis-connector'
import { WalletConnectConnector } from 'web3-react-walletconnect-connector'
import { WalletLinkConnector } from 'web3-react-walletlink-connector'
import UNISWAP_LOGO_URL from '../assets/svg/logo.svg'
import { ALL_SUPPORTED_CHAIN_IDS, INFURA_NETWORK_URLS, SupportedChainId } from '../constants/chains'
import getLibrary from '../utils/getLibrary'
import { FortmaticConnector } from './Fortmatic'
import { NetworkConnector } from './NetworkConnector'
@@ -19,8 +20,8 @@ export const network = new NetworkConnector({
defaultChainId: 1,
})
let networkLibrary: providers.Web3Provider | undefined
export function getNetworkLibrary(): providers.Web3Provider {
let networkLibrary: Web3Provider | undefined
export function getNetworkLibrary(): Web3Provider {
return (networkLibrary = networkLibrary ?? getLibrary(network.provider))
}
@@ -52,5 +53,5 @@ export const walletlink = new WalletLinkConnector({
url: INFURA_NETWORK_URLS[SupportedChainId.MAINNET],
appName: 'Uniswap',
appLogoUrl: UNISWAP_LOGO_URL,
supportedChainIds: [SupportedChainId.MAINNET, SupportedChainId.POLYGON],
supportedChainIds: ALL_SUPPORTED_CHAIN_IDS,
})

View File

@@ -107,3 +107,8 @@ export const V3_MIGRATOR_ADDRESSES: AddressMap = constructSameAddressMap('0xA564
SupportedChainId.POLYGON_MUMBAI,
SupportedChainId.POLYGON,
])
export const TICK_LENS_ADDRESSES: AddressMap = {
[SupportedChainId.ARBITRUM_ONE]: '0xbfd8137f7d1516D3ea5cA83523914859ec47F573',
[SupportedChainId.ARBITRUM_RINKEBY]: '0xbfd8137f7d1516D3ea5cA83523914859ec47F573',
}

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

@@ -0,0 +1,170 @@
import ethereumLogoUrl from 'assets/images/ethereum-logo.png'
import arbitrumLogoUrl from 'assets/svg/arbitrum_logo.svg'
import optimismLogoUrl from 'assets/svg/optimistic_ethereum.svg'
import polygonMaticLogo from 'assets/svg/polygon-matic-logo.svg'
import ms from 'ms.macro'
import { SupportedChainId, SupportedL1ChainId, SupportedL2ChainId } from './chains'
import { ARBITRUM_LIST, OPTIMISM_LIST } from './lists'
export enum NetworkType {
L1,
L2,
}
interface BaseChainInfo {
readonly networkType: NetworkType
readonly blockWaitMsBeforeWarning?: number
readonly docs: string
readonly bridge?: string
readonly explorer: string
readonly infoLink: string
readonly logoUrl: string
readonly label: string
readonly helpCenterUrl?: string
readonly nativeCurrency: {
name: string // e.g. 'Goerli ETH',
symbol: string // e.g. 'gorETH',
decimals: number // e.g. 18,
}
}
export interface L1ChainInfo extends BaseChainInfo {
readonly networkType: NetworkType.L1
}
export interface L2ChainInfo extends BaseChainInfo {
readonly networkType: NetworkType.L2
readonly bridge: string
readonly statusPage?: string
readonly defaultListUrl: string
}
export type ChainInfoMap = { readonly [chainId: number]: L1ChainInfo | L2ChainInfo } & {
readonly [chainId in SupportedL2ChainId]: L2ChainInfo
} &
{ readonly [chainId in SupportedL1ChainId]: L1ChainInfo }
export const CHAIN_INFO: ChainInfoMap = {
[SupportedChainId.MAINNET]: {
networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/',
explorer: 'https://etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Ethereum',
logoUrl: ethereumLogoUrl,
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
},
[SupportedChainId.RINKEBY]: {
networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/',
explorer: 'https://rinkeby.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Rinkeby',
logoUrl: ethereumLogoUrl,
nativeCurrency: { name: 'Rinkeby Ether', symbol: 'rETH', decimals: 18 },
},
[SupportedChainId.ROPSTEN]: {
networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/',
explorer: 'https://ropsten.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Ropsten',
logoUrl: ethereumLogoUrl,
nativeCurrency: { name: 'Ropsten Ether', symbol: 'ropETH', decimals: 18 },
},
[SupportedChainId.KOVAN]: {
networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/',
explorer: 'https://kovan.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Kovan',
logoUrl: ethereumLogoUrl,
nativeCurrency: { name: 'Kovan Ether', symbol: 'kovETH', decimals: 18 },
},
[SupportedChainId.GOERLI]: {
networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/',
explorer: 'https://goerli.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/',
label: 'Görli',
logoUrl: ethereumLogoUrl,
nativeCurrency: { name: 'Görli Ether', symbol: 'görETH', decimals: 18 },
},
[SupportedChainId.OPTIMISM]: {
networkType: NetworkType.L2,
blockWaitMsBeforeWarning: ms`25m`,
bridge: 'https://gateway.optimism.io/?chainId=1',
defaultListUrl: OPTIMISM_LIST,
docs: 'https://optimism.io/',
explorer: 'https://optimistic.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/optimism/',
label: 'Optimism',
logoUrl: optimismLogoUrl,
statusPage: 'https://optimism.io/status',
helpCenterUrl: 'https://help.uniswap.org/en/collections/3137778-uniswap-on-optimistic-ethereum-oξ',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
},
[SupportedChainId.OPTIMISTIC_KOVAN]: {
networkType: NetworkType.L2,
blockWaitMsBeforeWarning: ms`25m`,
bridge: 'https://gateway.optimism.io/',
defaultListUrl: OPTIMISM_LIST,
docs: 'https://optimism.io/',
explorer: 'https://optimistic.etherscan.io/',
infoLink: 'https://info.uniswap.org/#/optimism/',
label: 'Optimistic Kovan',
logoUrl: optimismLogoUrl,
statusPage: 'https://optimism.io/status',
helpCenterUrl: 'https://help.uniswap.org/en/collections/3137778-uniswap-on-optimistic-ethereum-oξ',
nativeCurrency: { name: 'Optimistic Kovan Ether', symbol: 'kovOpETH', decimals: 18 },
},
[SupportedChainId.ARBITRUM_ONE]: {
networkType: NetworkType.L2,
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://bridge.arbitrum.io/',
docs: 'https://offchainlabs.com/',
explorer: 'https://arbiscan.io/',
infoLink: 'https://info.uniswap.org/#/arbitrum',
label: 'Arbitrum',
logoUrl: arbitrumLogoUrl,
defaultListUrl: ARBITRUM_LIST,
helpCenterUrl: 'https://help.uniswap.org/en/collections/3137787-uniswap-on-arbitrum',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
},
[SupportedChainId.ARBITRUM_RINKEBY]: {
networkType: NetworkType.L2,
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://bridge.arbitrum.io/',
docs: 'https://offchainlabs.com/',
explorer: 'https://rinkeby-explorer.arbitrum.io/',
infoLink: 'https://info.uniswap.org/#/arbitrum/',
label: 'Arbitrum Rinkeby',
logoUrl: arbitrumLogoUrl,
defaultListUrl: ARBITRUM_LIST,
helpCenterUrl: 'https://help.uniswap.org/en/collections/3137787-uniswap-on-arbitrum',
nativeCurrency: { name: 'Rinkeby Arbitrum Ether', symbol: 'rinkArbETH', decimals: 18 },
},
[SupportedChainId.POLYGON]: {
networkType: NetworkType.L1,
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://wallet.polygon.technology/bridge',
docs: 'https://polygon.io/',
explorer: 'https://polygonscan.com/',
infoLink: 'https://info.uniswap.org/#/polygon/',
label: 'Polygon',
logoUrl: polygonMaticLogo,
nativeCurrency: { name: 'Polygon Matic', symbol: 'MATIC', decimals: 18 },
},
[SupportedChainId.POLYGON_MUMBAI]: {
networkType: NetworkType.L1,
blockWaitMsBeforeWarning: ms`10m`,
bridge: 'https://wallet.polygon.technology/bridge',
docs: 'https://polygon.io/',
explorer: 'https://mumbai.polygonscan.com/',
infoLink: 'https://info.uniswap.org/#/polygon/',
label: 'Polygon Mumbai',
logoUrl: polygonMaticLogo,
nativeCurrency: { name: 'Polygon Mumbai Matic', symbol: 'mMATIC', decimals: 18 },
},
}

View File

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

View File

@@ -12,6 +12,8 @@ export const COMMON_CONTRACT_NAMES: Record<number, { [address: string]: string }
[TIMELOCK_ADDRESS[SupportedChainId.MAINNET]]: 'Timelock',
[GOVERNANCE_ALPHA_V0_ADDRESSES[SupportedChainId.MAINNET]]: 'Governance (V0)',
[GOVERNANCE_ALPHA_V1_ADDRESSES[SupportedChainId.MAINNET]]: 'Governance',
'0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e': 'ENS Registry',
'0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41': 'ENS Public Resolver',
},
}
@@ -21,3 +23,5 @@ export const DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS = 13
export const AVERAGE_BLOCK_TIME_IN_SECS: { [chainId: number]: number } = {
1: DEFAULT_AVERAGE_BLOCK_TIME_IN_SECS,
}
export const LATEST_GOVERNOR_INDEX = 2

23
src/constants/infura.ts Normal file
View File

@@ -0,0 +1,23 @@
import { SupportedChainId } from './chains'
const INFURA_KEY = process.env.REACT_APP_INFURA_KEY
if (typeof INFURA_KEY === 'undefined') {
throw new Error(`REACT_APP_INFURA_KEY must be a defined environment variable`)
}
/**
* These are the network URLs used by the interface when there is not another available source of chain data
*/
export const INFURA_NETWORK_URLS: { [key in SupportedChainId]: string } = {
[SupportedChainId.MAINNET]: `https://mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.RINKEBY]: `https://rinkeby.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.ROPSTEN]: `https://ropsten.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.GOERLI]: `https://goerli.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.KOVAN]: `https://kovan.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.OPTIMISM]: `https://optimism-mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.OPTIMISTIC_KOVAN]: `https://optimism-kovan.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.ARBITRUM_ONE]: `https://arbitrum-mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.ARBITRUM_RINKEBY]: `https://arbitrum-rinkeby.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.POLYGON]: `https://polygon-mainnet.infura.io/v3/${INFURA_KEY}`,
[SupportedChainId.POLYGON_MUMBAI]: `https://polygon-mumbai.infura.io/v3/${INFURA_KEY}`,
}

View File

@@ -32,11 +32,11 @@ export const SUPPORTED_LOCALES = [
'vi-VN',
'zh-CN',
'zh-TW',
] as const
]
export type SupportedLocale = typeof SUPPORTED_LOCALES[number] | 'pseudo'
// eslint-disable-next-line import/first
import * as enUS from '../locales/en-US'
import * as enUS from 'locales/en-US'
export const DEFAULT_LOCALE: SupportedLocale = 'en-US'
export const DEFAULT_CATALOG = enUS

View File

@@ -18,8 +18,8 @@ import {
sETH2,
SWISE,
TRIBE,
USDC,
USDC_ARBITRUM,
USDC_MAINNET,
USDC_OPTIMISM,
USDC_POLYGON,
USDT,
@@ -44,13 +44,21 @@ type ChainCurrencyList = {
}
const WRAPPED_NATIVE_CURRENCIES_ONLY: ChainTokenList = Object.fromEntries(
Object.entries(WRAPPED_NATIVE_CURRENCY).map(([key, value]) => [key, [value]])
Object.entries(WRAPPED_NATIVE_CURRENCY)
.map(([key, value]) => [key, [value]])
.filter(Boolean)
)
// used to construct intermediary pairs for trading
export const BASES_TO_CHECK_TRADES_AGAINST: ChainTokenList = {
...WRAPPED_NATIVE_CURRENCIES_ONLY,
[SupportedChainId.MAINNET]: [...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.MAINNET], DAI, USDC, USDT, WBTC],
[SupportedChainId.MAINNET]: [
...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.MAINNET],
DAI,
USDC_MAINNET,
USDT,
WBTC,
],
[SupportedChainId.OPTIMISM]: [
...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.OPTIMISM],
DAI_OPTIMISM,
@@ -90,7 +98,7 @@ export const ADDITIONAL_BASES: { [chainId: number]: { [tokenAddress: string]: To
*/
export const CUSTOM_BASES: { [chainId: number]: { [tokenAddress: string]: Token[] } } = {
[SupportedChainId.MAINNET]: {
[AMPL.address]: [DAI, WRAPPED_NATIVE_CURRENCY[SupportedChainId.MAINNET]],
[AMPL.address]: [DAI, WRAPPED_NATIVE_CURRENCY[SupportedChainId.MAINNET] as Token],
},
}
@@ -101,32 +109,38 @@ export const COMMON_BASES: ChainCurrencyList = {
[SupportedChainId.MAINNET]: [
nativeOnChain(SupportedChainId.MAINNET),
DAI,
USDC,
USDC_MAINNET,
USDT,
WBTC,
WRAPPED_NATIVE_CURRENCY[SupportedChainId.MAINNET],
WRAPPED_NATIVE_CURRENCY[SupportedChainId.MAINNET] as Token,
],
[SupportedChainId.ROPSTEN]: [
nativeOnChain(SupportedChainId.ROPSTEN),
WRAPPED_NATIVE_CURRENCY[SupportedChainId.ROPSTEN],
WRAPPED_NATIVE_CURRENCY[SupportedChainId.ROPSTEN] as Token,
],
[SupportedChainId.RINKEBY]: [
nativeOnChain(SupportedChainId.RINKEBY),
WRAPPED_NATIVE_CURRENCY[SupportedChainId.RINKEBY],
WRAPPED_NATIVE_CURRENCY[SupportedChainId.RINKEBY] as Token,
],
[SupportedChainId.GOERLI]: [
nativeOnChain(SupportedChainId.GOERLI),
WRAPPED_NATIVE_CURRENCY[SupportedChainId.GOERLI] as Token,
],
[SupportedChainId.KOVAN]: [
nativeOnChain(SupportedChainId.KOVAN),
WRAPPED_NATIVE_CURRENCY[SupportedChainId.KOVAN] as Token,
],
[SupportedChainId.GOERLI]: [nativeOnChain(SupportedChainId.GOERLI), WRAPPED_NATIVE_CURRENCY[SupportedChainId.GOERLI]],
[SupportedChainId.KOVAN]: [nativeOnChain(SupportedChainId.KOVAN), WRAPPED_NATIVE_CURRENCY[SupportedChainId.KOVAN]],
[SupportedChainId.ARBITRUM_ONE]: [
nativeOnChain(SupportedChainId.ARBITRUM_ONE),
DAI_ARBITRUM_ONE,
USDC_ARBITRUM,
USDT_ARBITRUM_ONE,
WBTC_ARBITRUM_ONE,
WRAPPED_NATIVE_CURRENCY[SupportedChainId.ARBITRUM_ONE],
WRAPPED_NATIVE_CURRENCY[SupportedChainId.ARBITRUM_ONE] as Token,
],
[SupportedChainId.ARBITRUM_RINKEBY]: [
nativeOnChain(SupportedChainId.ARBITRUM_RINKEBY),
WRAPPED_NATIVE_CURRENCY[SupportedChainId.ARBITRUM_RINKEBY],
WRAPPED_NATIVE_CURRENCY[SupportedChainId.ARBITRUM_RINKEBY] as Token,
],
[SupportedChainId.OPTIMISM]: [
nativeOnChain(SupportedChainId.OPTIMISM),
@@ -146,7 +160,7 @@ export const COMMON_BASES: ChainCurrencyList = {
],
[SupportedChainId.POLYGON_MUMBAI]: [
nativeOnChain(SupportedChainId.POLYGON_MUMBAI),
WRAPPED_NATIVE_CURRENCY[SupportedChainId.POLYGON_MUMBAI],
WRAPPED_NATIVE_CURRENCY[SupportedChainId.POLYGON_MUMBAI] as Token,
WETH_POLYGON_MUMBAI,
],
}
@@ -154,7 +168,13 @@ export const COMMON_BASES: ChainCurrencyList = {
// used to construct the list of all pairs we consider by default in the frontend
export const BASES_TO_TRACK_LIQUIDITY_FOR: ChainTokenList = {
...WRAPPED_NATIVE_CURRENCIES_ONLY,
[SupportedChainId.MAINNET]: [...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.MAINNET], DAI, USDC, USDT, WBTC],
[SupportedChainId.MAINNET]: [
...WRAPPED_NATIVE_CURRENCIES_ONLY[SupportedChainId.MAINNET],
DAI,
USDC_MAINNET,
USDT,
WBTC,
],
}
export const PINNED_PAIRS: { readonly [chainId: number]: [Token, Token][] } = {
[SupportedChainId.MAINNET]: [
@@ -168,7 +188,7 @@ export const PINNED_PAIRS: { readonly [chainId: number]: [Token, Token][] } = {
'Compound USD Coin'
),
],
[USDC, USDT],
[USDC_MAINNET, USDT],
[DAI, USDT],
],
}

View File

@@ -1101,6 +1101,20 @@
"name": "BMEX",
"symbol": "BMEX",
"decimals": 18
},
{
"chainId": 1,
"address": "0x322A46E88fa3C78F9c9E3DBb0254b61664a06109",
"name": "Ukraine DAO",
"symbol": "Ukraine",
"decimals": 18
},
{
"chainId": 1,
"address": "0x8290D7a64F25e6b5002d98367E8367c1b532b534",
"name": "oneUNI",
"symbol": "oneUNI",
"decimals": 18
}
]
}

View File

@@ -1,8 +1,24 @@
import { Currency, Ether, NativeCurrency, Token, WETH9 } from '@uniswap/sdk-core'
import {
USDC_ARBITRUM,
USDC_ARBITRUM_RINKEBY,
USDC_GÖRLI,
USDC_KOVAN,
USDC_MAINNET,
USDC_OPTIMISM,
USDC_OPTIMISTIC_KOVAN,
USDC_POLYGON,
USDC_POLYGON_MUMBAI,
USDC_RINKEBY,
USDC_ROPSTEN,
} from '@uniswap/smart-order-router'
import invariant from 'tiny-invariant'
import { UNI_ADDRESS } from './addresses'
import { SupportedChainId } from './chains'
export { USDC_ARBITRUM, USDC_MAINNET, USDC_OPTIMISM, USDC_POLYGON }
export const AMPL = new Token(
SupportedChainId.MAINNET,
'0xD46bA6D942050d489DBd938a2C909A5d5039A161',
@@ -31,27 +47,19 @@ export const DAI_OPTIMISM = new Token(
'DAI',
'Dai stable coin'
)
export const USDC = new Token(
SupportedChainId.MAINNET,
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
6,
'USDC',
'USD//C'
)
export const USDC_ARBITRUM = new Token(
SupportedChainId.ARBITRUM_ONE,
'0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8',
6,
'USDC',
'USD//C'
)
export const USDC_POLYGON = new Token(
SupportedChainId.POLYGON,
'0x2791bca1f2de4661ed88a30c99a7a9449aa84174',
6,
'USDC',
'USD//C'
)
export const USDC: { [chainId in SupportedChainId]: Token } = {
[SupportedChainId.MAINNET]: USDC_MAINNET,
[SupportedChainId.ARBITRUM_ONE]: USDC_ARBITRUM,
[SupportedChainId.OPTIMISM]: USDC_OPTIMISM,
[SupportedChainId.ARBITRUM_RINKEBY]: USDC_ARBITRUM_RINKEBY,
[SupportedChainId.OPTIMISTIC_KOVAN]: USDC_OPTIMISTIC_KOVAN,
[SupportedChainId.POLYGON]: USDC_POLYGON,
[SupportedChainId.POLYGON_MUMBAI]: USDC_POLYGON_MUMBAI,
[SupportedChainId.GOERLI]: USDC_GÖRLI,
[SupportedChainId.RINKEBY]: USDC_RINKEBY,
[SupportedChainId.KOVAN]: USDC_KOVAN,
[SupportedChainId.ROPSTEN]: USDC_ROPSTEN,
}
export const DAI_POLYGON = new Token(
SupportedChainId.POLYGON,
'0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063',
@@ -73,13 +81,6 @@ export const WBTC_POLYGON = new Token(
'WBTC',
'Wrapped BTC'
)
export const USDC_OPTIMISM = new Token(
SupportedChainId.OPTIMISM,
'0x7F5c764cBc14f9669B88837ca1490cCa17c31607',
6,
'USDC',
'USD//C'
)
export const USDT = new Token(
SupportedChainId.MAINNET,
'0xdAC17F958D2ee523a2206206994597C13D831ec7',
@@ -208,8 +209,8 @@ export const UNI: { [chainId: number]: Token } = {
[SupportedChainId.KOVAN]: new Token(SupportedChainId.KOVAN, UNI_ADDRESS[42], 18, 'UNI', 'Uniswap'),
}
export const WRAPPED_NATIVE_CURRENCY: { [chainId: number]: Token } = {
...WETH9,
export const WRAPPED_NATIVE_CURRENCY: { [chainId: number]: Token | undefined } = {
...(WETH9 as Record<SupportedChainId, Token>),
[SupportedChainId.OPTIMISM]: new Token(
SupportedChainId.OPTIMISM,
'0x4200000000000000000000000000000000000006',
@@ -265,7 +266,9 @@ class MaticNativeCurrency extends NativeCurrency {
get wrapped(): Token {
if (!isMatic(this.chainId)) throw new Error('Not matic')
return WRAPPED_NATIVE_CURRENCY[this.chainId]
const wrapped = WRAPPED_NATIVE_CURRENCY[this.chainId]
invariant(wrapped instanceof Token)
return wrapped
}
public constructor(chainId: number) {
@@ -276,7 +279,8 @@ class MaticNativeCurrency extends NativeCurrency {
export class ExtendedEther extends Ether {
public get wrapped(): Token {
if (this.chainId in WRAPPED_NATIVE_CURRENCY) return WRAPPED_NATIVE_CURRENCY[this.chainId]
const wrapped = WRAPPED_NATIVE_CURRENCY[this.chainId]
if (wrapped) return wrapped
throw new Error('Unsupported chain ID')
}
@@ -296,3 +300,19 @@ export function nativeOnChain(chainId: number): NativeCurrency {
: ExtendedEther.onChain(chainId))
)
}
export const TOKEN_SHORTHANDS: { [shorthand: string]: { [chainId in SupportedChainId]?: string } } = {
USDC: {
[SupportedChainId.MAINNET]: USDC_MAINNET.address,
[SupportedChainId.ARBITRUM_ONE]: USDC_ARBITRUM.address,
[SupportedChainId.OPTIMISM]: USDC_OPTIMISM.address,
[SupportedChainId.ARBITRUM_RINKEBY]: USDC_ARBITRUM_RINKEBY.address,
[SupportedChainId.OPTIMISTIC_KOVAN]: USDC_OPTIMISTIC_KOVAN.address,
[SupportedChainId.POLYGON]: USDC_POLYGON.address,
[SupportedChainId.POLYGON_MUMBAI]: USDC_POLYGON_MUMBAI.address,
[SupportedChainId.GOERLI]: USDC_GÖRLI.address,
[SupportedChainId.RINKEBY]: USDC_RINKEBY.address,
[SupportedChainId.KOVAN]: USDC_KOVAN.address,
[SupportedChainId.ROPSTEN]: USDC_ROPSTEN.address,
},
}

View File

@@ -1,4 +1,4 @@
import { AbstractConnector } from '@web3-react/abstract-connector'
import { AbstractConnector } from 'web3-react-abstract-connector'
import INJECTED_ICON_URL from '../assets/images/arrow-right.svg'
import COINBASE_ICON_URL from '../assets/images/coinbaseWalletIcon.svg'

View File

@@ -1,18 +1,15 @@
import { Currency, Token } from '@uniswap/sdk-core'
import { CHAIN_INFO, L2_CHAIN_IDS, SupportedChainId, SupportedL2ChainId } from 'constants/chains'
import { arrayify, parseBytes32String } from 'ethers/lib/utils'
import { CHAIN_INFO } from 'constants/chainInfo'
import { L2_CHAIN_IDS, SupportedChainId, SupportedL2ChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useCurrencyFromMap, useTokenFromMapOrNetwork } from 'lib/hooks/useCurrency'
import { getTokenFilter } from 'lib/hooks/useTokenList/filtering'
import { useMemo } from 'react'
import { createTokenFilterFunction } from '../components/SearchModal/filtering'
import { nativeOnChain } from '../constants/tokens'
import { useAllLists, useCombinedActiveList, useInactiveListUrls } from '../state/lists/hooks'
import { WrappedTokenInfo } from '../state/lists/wrappedTokenInfo'
import { NEVER_RELOAD, useSingleCallResult } from '../state/multicall/hooks'
import { useUserAddedTokens } from '../state/user/hooks'
import { isAddress } from '../utils'
import { TokenAddressMap, useUnsupportedTokenList } from './../state/lists/hooks'
import { useBytes32TokenContract, useTokenContract } from './useContract'
import { useActiveWeb3React } from './web3'
// reduce token map into standard address <-> Token mapping, optionally include user added tokens
function useTokensFromMap(tokenMap: TokenAddressMap, includeUserAdded: boolean): { [address: string]: Token } {
@@ -115,7 +112,7 @@ export function useSearchInactiveTokenLists(search: string | undefined, minResul
const activeTokens = useAllTokens()
return useMemo(() => {
if (!search || search.trim().length === 0) return []
const tokenFilter = createTokenFilterFunction(search)
const tokenFilter = getTokenFilter(search)
const result: WrappedTokenInfo[] = []
const addressSet: { [address: string]: true } = {}
for (const url of inactiveUrls) {
@@ -157,95 +154,15 @@ export function useIsUserAddedToken(currency: Currency | undefined | null): bool
return !!userAddedTokens.find((token) => currency.equals(token))
}
// parse a name or symbol from a token response
const BYTES32_REGEX = /^0x[a-fA-F0-9]{64}$/
function parseStringOrBytes32(str: string | undefined, bytes32: string | undefined, defaultValue: string): string {
return str && str.length > 0
? str
: // need to check for proper bytes string and valid terminator
bytes32 && BYTES32_REGEX.test(bytes32) && arrayify(bytes32)[31] === 0
? parseBytes32String(bytes32)
: defaultValue
}
// undefined if invalid or does not exist
// null if loading or null was passed
// otherwise returns the token
export function useToken(tokenAddress?: string | null): Token | undefined | null {
const { chainId } = useActiveWeb3React()
export function useToken(tokenAddress?: string | null): Token | null | undefined {
const tokens = useAllTokens()
const address = isAddress(tokenAddress)
const tokenContract = useTokenContract(address ? address : undefined, false)
const tokenContractBytes32 = useBytes32TokenContract(address ? address : undefined, false)
const token: Token | undefined = address ? tokens[address] : undefined
const tokenName = useSingleCallResult(token ? undefined : tokenContract, 'name', undefined, NEVER_RELOAD)
const tokenNameBytes32 = useSingleCallResult(
token ? undefined : tokenContractBytes32,
'name',
undefined,
NEVER_RELOAD
)
const symbol = useSingleCallResult(token ? undefined : tokenContract, 'symbol', undefined, NEVER_RELOAD)
const symbolBytes32 = useSingleCallResult(token ? undefined : tokenContractBytes32, 'symbol', undefined, NEVER_RELOAD)
const decimals = useSingleCallResult(token ? undefined : tokenContract, 'decimals', undefined, NEVER_RELOAD)
return useMemo(() => {
if (token) return token
if (tokenAddress === null) return null
if (!chainId || !address) return undefined
if (decimals.loading || symbol.loading || tokenName.loading) return null
if (decimals.result) {
return new Token(
chainId,
address,
decimals.result[0],
parseStringOrBytes32(symbol.result?.[0], symbolBytes32.result?.[0], 'UNKNOWN'),
parseStringOrBytes32(tokenName.result?.[0], tokenNameBytes32.result?.[0], 'Unknown Token')
)
}
return undefined
}, [
address,
chainId,
decimals.loading,
decimals.result,
symbol.loading,
symbol.result,
symbolBytes32.result,
token,
tokenAddress,
tokenName.loading,
tokenName.result,
tokenNameBytes32.result,
])
return useTokenFromMapOrNetwork(tokens, tokenAddress)
}
export function useNativeCurrency(): Currency {
const { chainId } = useActiveWeb3React()
return useMemo(
() =>
chainId
? nativeOnChain(chainId)
: // display mainnet when not connected
nativeOnChain(SupportedChainId.MAINNET),
[chainId]
)
}
export function useCurrency(currencyId: string | null | undefined): Currency | null | undefined {
const nativeCurrency = useNativeCurrency()
const isNative = Boolean(nativeCurrency && currencyId?.toUpperCase() === 'ETH')
const token = useToken(isNative ? undefined : currencyId)
if (currencyId === null || currencyId === undefined) return currencyId
// this case so we use our builtin wrapped token instead of wrapped tokens on token lists
const wrappedNative = nativeCurrency?.wrapped
if (wrappedNative?.address?.toUpperCase() === currencyId?.toUpperCase()) return wrappedNative
return isNative ? nativeCurrency : token
export function useCurrency(currencyId?: string | null): Currency | null | undefined {
const tokens = useAllTokens()
return useCurrencyFromMap(tokens, currencyId)
}

View File

@@ -1,19 +1,20 @@
import { useWeb3React } from '@web3-react/core'
import { providers } from 'ethers'
/* eslint-disable react-hooks/rules-of-hooks */
import { Web3Provider } from '@ethersproject/providers'
import { default as useWidgetsWeb3React } from 'lib/hooks/useActiveWeb3React'
import { useWeb3React } from 'web3-react-core'
import { NetworkContextName } from '../constants/misc'
export default function useActiveWeb3React() {
const widgetsContext = useWidgetsWeb3React()
const interfaceContext = useWeb3React<providers.Web3Provider>()
const interfaceNetworkContext = useWeb3React<providers.Web3Provider>(
if (process.env.REACT_APP_IS_WIDGET) {
return useWidgetsWeb3React()
}
const interfaceContext = useWeb3React<Web3Provider>()
const interfaceNetworkContext = useWeb3React<Web3Provider>(
process.env.REACT_APP_IS_WIDGET ? undefined : NetworkContextName
)
if (process.env.REACT_APP_IS_WIDGET) {
return widgetsContext
}
if (interfaceContext.active) {
return interfaceContext
}

View File

@@ -1,9 +1,8 @@
import { Currency, Token } from '@uniswap/sdk-core'
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs'
import { useCallback, useState } from 'react'
import { getTokenLogoURL } from './../components/CurrencyLogo/index'
export default function useAddTokenToMetamask(currencyToAdd: Currency | undefined): {
addToken: () => void
success: boolean | undefined
@@ -13,6 +12,7 @@ export default function useAddTokenToMetamask(currencyToAdd: Currency | undefine
const token: Token | undefined = currencyToAdd?.wrapped
const [success, setSuccess] = useState<boolean | undefined>()
const logoURL = useCurrencyLogoURIs(token)[0]
const addToken = useCallback(() => {
if (library && library.provider.isMetaMask && library.provider.request && token) {
@@ -26,7 +26,7 @@ export default function useAddTokenToMetamask(currencyToAdd: Currency | undefine
address: token.address,
symbol: token.symbol,
decimals: token.decimals,
image: getTokenLogoURL(token.address),
image: logoURL,
},
},
})
@@ -37,7 +37,7 @@ export default function useAddTokenToMetamask(currencyToAdd: Currency | undefine
} else {
setSuccess(false)
}
}, [library, token])
}, [library, logoURL, token])
return { addToken, success }
}

View File

@@ -1,9 +1,9 @@
import { Currency } from '@uniswap/sdk-core'
import { Pool, Route } from '@uniswap/v3-sdk'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useMemo } from 'react'
import { useV3SwapPools } from './useV3SwapPools'
import { useActiveWeb3React } from './web3'
/**
* Returns true if poolA is equivalent to poolB

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