Compare commits

..

178 Commits

Author SHA1 Message Date
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
Jordan Frankfurt
5a90f13a03 chore(deps): bump walletconnect (#3097) 2022-01-11 14:16:35 -06:00
Will Hennessy
8c213f9001 Update wrong network message (#3089)
fixes https://github.com/Uniswap/interface/issues/2740
2022-01-11 14:16:19 -06:00
Jordan Frankfurt
5722902f96 add polygon to supported walletlink chainIds (#3096) 2022-01-11 14:15:09 -06:00
Zach Pomerantz
27412e49d5 chore: import from ethers (#3094)
* chore: rm lodash

* chore: improve styled-components lint

* chore: import from ethers

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

* refactor: mv token list utils to lib

* feat: expand fetchTokenList to include inlined

* feat: simple widget token list

* fix: token img props

* feat: use token list in selector

* fix: update useColor for optional logoURI

* fix: avoid leaking deps

* chore: add state to lib build

* chore: mv devDeps to deps for lib

* fix: microbundle css import

* fix: match ethers versions

* fix: use color callback

* chore: clean up token info type

* chore: widget type simplification

* refactor: share token map code

* test: include list in token select fixture

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

* update reverse button css and remove popover logic

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

For issue #3010

* Update useENSAvatar.ts

Add leading zero pad to 64 hex chars

* Update useENSAvatar.ts

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

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

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

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

add url connector

* naming

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

3
.env
View File

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

View File

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

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

9
.gitignore vendored
View File

@@ -11,21 +11,16 @@
/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
/dist
/dts
# misc
.DS_Store

View File

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

View File

@@ -1,14 +1,26 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
/* 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) =>
plugin instanceof HtmlWebpackPlugin
? new HtmlWebpackPlugin({
templateContent: '<body></body>',
})
: plugin
),
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,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,17 +1,20 @@
{
"name": "@uniswap/interface",
"name": "@uniswap/widgets",
"version": "0.0.13-beta",
"description": "Uniswap Interface",
"homepage": ".",
"main": "dist/interface.js",
"module": "dist/interface.esm.js",
"types": "dist/index.d.ts",
"main": "dist/widgets.js",
"module": "dist/widgets.esm.js",
"types": "dist/widgets.d.ts",
"files": [
"lib",
"dist"
],
"private": true,
"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",
@@ -22,8 +25,16 @@
"@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,30 +63,24 @@
"@types/wcag-contrast": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
"@uniswap/default-token-list": "^2.1.0",
"@uniswap/default-token-list": "^3.0.0",
"@uniswap/governance": "^1.0.2",
"@uniswap/liquidity-staker": "^1.0.2",
"@uniswap/merkle-distributor": "1.0.1",
"@uniswap/router-sdk": "^1.0.3",
"@uniswap/sdk-core": "^3.0.1",
"@uniswap/smart-order-router": "^2.5.4",
"@uniswap/token-lists": "^1.0.0-beta.27",
"@uniswap/v2-core": "1.0.0",
"@uniswap/v2-periphery": "^1.1.0-beta.0",
"@uniswap/v2-sdk": "^3.0.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",
"ajv": "^6.12.3",
"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.11",
"array.prototype.flat": "^1.2.4",
"array.prototype.flatmap": "^1.2.4",
"cids": "^1.0.0",
"babel-plugin-macros": "^3.1.0",
"copy-to-clipboard": "^3.2.0",
"cross-env": "^7.0.3",
"cypress": "^7.7.0",
@@ -88,35 +93,38 @@
"eslint-plugin-react-hooks": "^4.0.0",
"eslint-plugin-simple-import-sort": "^7.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"ethers": "^5.4.6",
"firebase": "^9.1.3",
"graphql": "^15.5.0",
"graphql-request": "^3.4.0",
"inter-ui": "^3.13.1",
"jest-styled-components": "^7.0.5",
"microbundle": "^0.13.3",
"ms.macro": "^2.0.0",
"multicodec": "^3.0.1",
"multihashes": "^4.0.2",
"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",
"react-redux": "^7.2.2",
"react-router-dom": "^5.0.0",
"react-scripts": "^4.0.3",
"react-spring": "^8.0.27",
"react-use-gesture": "^6.0.14",
"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-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",
@@ -127,7 +135,7 @@
"workbox-routing": "^6.1.0"
},
"resolutions": {
"@walletconnect/ethereum-provider": "1.6.5"
"@walletconnect/ethereum-provider": "1.7.1"
},
"scripts": {
"contracts:compile:abi": "typechain --target ethers-v5 --out-dir src/abis/types \"./src/abis/**/*.json\"",
@@ -138,17 +146,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 --record'",
"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"
"widgets:start": "cosmos",
"widgets:build": "rollup --config --failAfterWarnings --configPlugin typescript2"
},
"browserslist": {
"production": [
@@ -164,24 +169,52 @@
},
"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.10",
"@uniswap/token-lists": "^1.0.0-beta.27",
"@uniswap/v2-sdk": "^3.0.1",
"@uniswap/v3-sdk": "^3.8.2",
"web3-react-core": "npm:@web3-react/core@^6.0.9",
"ajv": "^6.12.3",
"cids": "^1.0.0",
"immer": "^9.0.6",
"jotai": "^1.3.7",
"lodash": "^4.17.21",
"jsbi": "^3.1.4",
"make-plural": "^7.0.0",
"ms.macro": "^2.0.0",
"multicodec": "^3.0.1",
"multihashes": "^4.0.2",
"node-vibrant": "^3.2.1-alpha.1",
"polished": "^3.3.2",
"popper-max-size-modifier": "^0.2.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-feather": "^2.0.8",
"react-popper": "^2.2.3",
"react-redux": "^7.2.2",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.5",
"rebass": "^4.0.7",
@@ -189,11 +222,17 @@
"styled-components": "^5.3.0",
"tiny-invariant": "^1.2.0",
"wcag-contrast": "^3.0.0",
"wicg-inert": "^3.1.1",
"widgets-web3-react/core": "npm:@web3-react/core@8.0.15-alpha.0",
"widgets-web3-react/eip1193": "npm:@web3-react/eip1193@8.0.15-alpha.0",
"widgets-web3-react/metamask": "npm:@web3-react/metamask@8.0.15-alpha.0",
"widgets-web3-react/network": "npm:@web3-react/network@8.0.15-alpha.0",
"widgets-web3-react/types": "npm:@web3-react/types@8.0.15-alpha.0"
"@web3-react/core": "8.0.16-alpha.0",
"@web3-react/eip1193": "8.0.16-alpha.0",
"@web3-react/empty": "8.0.17-alpha.0",
"@web3-react/metamask": "8.0.16-alpha.0",
"@web3-react/types": "8.0.16-alpha.0",
"@web3-react/url": "8.0.17-alpha.0",
"wicg-inert": "^3.1.1"
},
"peerDependencies": {
"@babel/runtime": "^7.17.0",
"react": "^17.0.1",
"react-dom": "^17.0.1"
}
}

127
rollup.config.ts Normal file
View File

@@ -0,0 +1,127 @@
/**
* 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'
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"',
}
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
externals({ exclude: ['constants'], deps: true, peerDeps: true }), // marks builtins, dependencies, and peerDependencies external
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; doing so type-checking allows the json to be type-checked
]
const check = {
input: 'src/lib/index.tsx',
output: { file: 'dist/widgets.tsc' },
external: isAsset,
plugins: [...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/widgets.d.ts' },
external: isAsset,
plugins: [
dts({ compilerOptions: { baseUrl: 'dist/dts' } }),
process.env.ROLLUP_WATCH ? undefined : del({ hook: 'buildEnd', targets: ['dist/widgets.tsc', 'dist/dts'] }),
],
}
const transpile = {
input: 'src/lib/index.tsx',
output: [
{
file: 'dist/widgets.js',
format: 'cjs',
sourcemap: false,
},
{
file: 'dist/widgets.esm.js',
format: 'esm',
sourcemap: false,
},
],
plugins: [
...plugins,
// Source code transformation
url({ include: ASSET_EXTENSIONS.map((extname) => '**/*' + extname) }), // imports assets as data URIs
svgr({ exportType: 'named', svgo: false }), // imports svgs as React components
sass({ insert: true }), // imports inlined sass styles
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
],
}),
copy({
copyOnce: true,
targets: [{ src: 'src/locales/*.js', dest: 'dist/locales' }],
}),
],
onwarn: squelchTypeWarnings, // this pipeline is only for transpilation
}
const config = [check, type, transpile]
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

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',
@@ -20,6 +19,20 @@ const BLOCKED_ADDRESSES: string[] = [
'0x8576aCC5C05D6Ce88f4e49bf65BdF0C62F91353C',
'0xC8a65Fadf0e0dDAf421F28FEAb69Bf6E2E589963',
'0x308eD4B7b49797e1A98D3818bFF6fe5385410370',
'0x67d40EE1A85bf4a4Bb7Ffae16De985e8427B',
'0x6f1ca141a28907f78ebaa64fb83a9088b02a83',
'0x6acdfba02d390b97ac2b2d42a63e85293bcc1',
'0x48549a34ae37b12f6a30566245176994e17c6',
'0x5512d943ed1f7c8a43f3435c85f7ab68b30121',
'0xc455f7fd3e0e12afd51fba5c106909934d8a0e',
'0x3cbded43efdaf0fc77b9c55f6fc9988fcc9b757d',
'0x67d40EE1A85bf4a4Bb7Ffae16De985e8427B6b45',
'0x6f1ca141a28907f78ebaa64fb83a9088b02a8352',
'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'
@@ -210,31 +216,90 @@ 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
}
@@ -251,10 +316,10 @@ export default function NetworkSelector() {
<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} />
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.MAINNET} />
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.POLYGON} />
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.OPTIMISM} />
<Row onSelectChain={handleChainSwitch} targetChain={SupportedChainId.ARBITRUM_ONE} />
</FlyoutMenu>
)}
</SelectorWrapper>

View File

@@ -1,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

@@ -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,5 +1,5 @@
import { SupportedChainId } from 'constants/chains'
import { useActiveWeb3React } from 'hooks/web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import styled from 'styled-components/macro'
import { MEDIA_WIDTHS } from 'theme'

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

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

@@ -3,8 +3,10 @@ import { t, Trans } from '@lingui/macro'
import { TokenList } from '@uniswap/token-lists'
import Card from 'components/Card'
import { UNSUPPORTED_LIST_URLS } from 'constants/lists'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useListColor } from 'hooks/useColor'
import { useActiveWeb3React } from 'hooks/web3'
import parseENSAddress from 'lib/utils/parseENSAddress'
import uriToHttp from 'lib/utils/uriToHttp'
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { CheckCircle, Settings } from 'react-feather'
import ReactGA from 'react-ga'
@@ -20,8 +22,6 @@ import { acceptListUpdate, disableList, enableList, removeList } from '../../sta
import { useActiveListUrls, useAllLists, useIsListActive } from '../../state/lists/hooks'
import { ExternalLink, IconWrapper, LinkStyledButton, ThemedText } from '../../theme'
import listVersionLabel from '../../utils/listVersionLabel'
import { parseENSAddress } from '../../utils/parseENSAddress'
import uriToHttp from '../../utils/uriToHttp'
import { ButtonEmpty, ButtonPrimary } from '../Button'
import Column, { AutoColumn } from '../Column'
import ListLogo from '../ListLogo'

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'
@@ -320,7 +320,7 @@ export default function WalletModal({
<ContentWrapper>
{error instanceof UnsupportedChainIdError ? (
<h5>
<Trans>Please connect to the appropriate Ethereum network.</Trans>
<Trans>Please connect to a supported network in the dropdown menu or in your wallet.</Trans>
</h5>
) : (
<Trans>Error connecting. Try refreshing the page.</Trans>

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 useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useState } from 'react'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
@@ -8,7 +9,6 @@ import styled from 'styled-components/macro'
import Circle from '../../assets/images/blue-loader.svg'
import tokenLogo from '../../assets/images/token-logo.png'
import useENS from '../../hooks/useENS'
import { useActiveWeb3React } from '../../hooks/web3'
import { useClaimCallback, useUserHasAvailableClaim, useUserUnclaimedAmount } from '../../state/claim/hooks'
import { useIsTransactionPending } from '../../state/transactions/hooks'
import { CloseIcon, CustomLightSpinner, ExternalLink, ThemedText, UniTokenAnimated } from '../../theme'

View File

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

View File

@@ -1,10 +1,11 @@
import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
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;

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 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;

View File

@@ -1,10 +1,11 @@
import { TransactionResponse } from '@ethersproject/providers'
import { Trans } from '@lingui/macro'
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;

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

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

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

@@ -7,8 +7,9 @@ import { AutoColumn } from 'components/Column'
import { LoadingRows } from 'components/Loader/styled'
import RoutingDiagram, { RoutingDiagramEntry } from 'components/RoutingDiagram/RoutingDiagram'
import { AutoRow, RowBetween } from 'components/Row'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import useAutoRouterSupported from 'hooks/useAutoRouterSupported'
import { useActiveWeb3React } from 'hooks/web3'
import { memo, useState } from 'react'
import { Plus } from 'react-feather'
import { InterfaceTrade } from 'state/routing/types'
@@ -16,7 +17,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 }>`

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 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 { 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'
@@ -48,10 +49,9 @@ export const portis = new PortisConnector({
networks: [1],
})
// mainnet only
export const walletlink = new WalletLinkConnector({
url: INFURA_NETWORK_URLS[SupportedChainId.MAINNET],
appName: 'Uniswap',
appLogoUrl: UNISWAP_LOGO_URL,
supportedChainIds: [SupportedChainId.MAINNET],
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,8 @@ 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]
/**
* All the chain IDs that are running the Ethereum protocol.
*/
@@ -65,223 +68,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',
},
},
}

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

@@ -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,19 +1,15 @@
import { arrayify } from '@ethersproject/bytes'
import { parseBytes32String } from '@ethersproject/strings'
import { Currency, Token } from '@uniswap/sdk-core'
import { CHAIN_INFO, L2_CHAIN_IDS, SupportedChainId, SupportedL2ChainId } from 'constants/chains'
import { CHAIN_INFO } from 'constants/chainInfo'
import { L2_CHAIN_IDS, SupportedChainId, SupportedL2ChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useCurrencyFromMap, useTokenFromMap } 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 } {
@@ -116,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) {
@@ -158,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 useTokenFromMap(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 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Web3Provider } from '@ethersproject/providers'
import { useWeb3React } from '@web3-react/core'
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()
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

View File

@@ -1,69 +1,25 @@
import { MaxUint256 } from '@ethersproject/constants'
import { TransactionResponse } from '@ethersproject/providers'
import { Protocol, Trade } from '@uniswap/router-sdk'
import { Trade } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
import { Pair, Route as V2Route, Trade as V2Trade } from '@uniswap/v2-sdk'
import { Pool, Route as V3Route, Trade as V3Trade } from '@uniswap/v3-sdk'
import { useCallback, useMemo } from 'react'
import { getTxOptimizedSwapRouter, SwapRouterVersion } from 'utils/getTxOptimizedSwapRouter'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import useSwapApproval, { useSwapApprovalOptimizedTrade } from 'lib/hooks/swap/useSwapApproval'
import { ApprovalState, useApproval } from 'lib/hooks/useApproval'
import { useCallback } from 'react'
import { SWAP_ROUTER_ADDRESSES, V2_ROUTER_ADDRESS, V3_ROUTER_ADDRESS } from '../constants/addresses'
import { TransactionType } from '../state/transactions/actions'
import { useHasPendingApproval, useTransactionAdder } from '../state/transactions/hooks'
import { calculateGasMargin } from '../utils/calculateGasMargin'
import { useTokenContract } from './useContract'
import { useTokenAllowance } from './useTokenAllowance'
import { useActiveWeb3React } from './web3'
export { ApprovalState } from 'lib/hooks/useApproval'
export enum ApprovalState {
UNKNOWN = 'UNKNOWN',
NOT_APPROVED = 'NOT_APPROVED',
PENDING = 'PENDING',
APPROVED = 'APPROVED',
}
export function useApprovalState(amountToApprove?: CurrencyAmount<Currency>, spender?: string) {
const { account } = useActiveWeb3React()
const token = amountToApprove?.currency?.isToken ? amountToApprove.currency : undefined
const currentAllowance = useTokenAllowance(token, account ?? undefined, spender)
const pendingApproval = useHasPendingApproval(token?.address, spender)
return useMemo(() => {
if (!amountToApprove || !spender) return ApprovalState.UNKNOWN
if (amountToApprove.currency.isNative) return ApprovalState.APPROVED
// we might not have enough data to know whether or not we need to approve
if (!currentAllowance) return ApprovalState.UNKNOWN
// amountToApprove will be defined if currentAllowance is
return currentAllowance.lessThan(amountToApprove)
? pendingApproval
? ApprovalState.PENDING
: ApprovalState.NOT_APPROVED
: ApprovalState.APPROVED
}, [amountToApprove, currentAllowance, pendingApproval, spender])
}
/** Returns approval state for all known swap routers */
export function useAllApprovalStates(
trade: Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent
) {
const { chainId } = useActiveWeb3React()
const amountToApprove = useMemo(
() => (trade && trade.inputAmount.currency.isToken ? trade.maximumAmountIn(allowedSlippage) : undefined),
[trade, allowedSlippage]
)
const v2ApprovalState = useApprovalState(amountToApprove, chainId ? V2_ROUTER_ADDRESS[chainId] : undefined)
const v3ApprovalState = useApprovalState(amountToApprove, chainId ? V3_ROUTER_ADDRESS[chainId] : undefined)
const v2V3ApprovalState = useApprovalState(amountToApprove, chainId ? SWAP_ROUTER_ADDRESSES[chainId] : undefined)
return useMemo(
() => ({ v2: v2ApprovalState, v3: v3ApprovalState, v2V3: v2V3ApprovalState }),
[v2ApprovalState, v2V3ApprovalState, v3ApprovalState]
)
function useGetAndTrackApproval(getApproval: ReturnType<typeof useApproval>[1]) {
const addTransaction = useTransactionAdder()
return useCallback(() => {
return getApproval().then((pending) => {
if (pending) {
const { response, tokenAddress, spenderAddress: spender } = pending
addTransaction(response, { type: TransactionType.APPROVAL, tokenAddress, spender })
}
})
}, [addTransaction, getApproval])
}
// returns a variable indicating the state of the approval and a function which approves if necessary or early returns
@@ -71,69 +27,17 @@ export function useApproveCallback(
amountToApprove?: CurrencyAmount<Currency>,
spender?: string
): [ApprovalState, () => Promise<void>] {
const { chainId } = useActiveWeb3React()
const token = amountToApprove?.currency?.isToken ? amountToApprove.currency : undefined
// check the current approval status
const approvalState = useApprovalState(amountToApprove, spender)
const tokenContract = useTokenContract(token?.address)
const addTransaction = useTransactionAdder()
const approve = useCallback(async (): Promise<void> => {
if (approvalState !== ApprovalState.NOT_APPROVED) {
console.error('approve was called unnecessarily')
return
}
if (!chainId) {
console.error('no chainId')
return
}
if (!token) {
console.error('no token')
return
}
if (!tokenContract) {
console.error('tokenContract is null')
return
}
if (!amountToApprove) {
console.error('missing amount to approve')
return
}
if (!spender) {
console.error('no spender')
return
}
let useExact = false
const estimatedGas = await tokenContract.estimateGas.approve(spender, MaxUint256).catch(() => {
// general fallback for tokens who restrict approval amounts
useExact = true
return tokenContract.estimateGas.approve(spender, amountToApprove.quotient.toString())
})
return tokenContract
.approve(spender, useExact ? amountToApprove.quotient.toString() : MaxUint256, {
gasLimit: calculateGasMargin(estimatedGas),
})
.then((response: TransactionResponse) => {
addTransaction(response, { type: TransactionType.APPROVAL, tokenAddress: token.address, spender })
})
.catch((error: Error) => {
console.debug('Failed to approve token', error)
throw error
})
}, [approvalState, token, tokenContract, amountToApprove, spender, addTransaction, chainId])
return [approvalState, approve]
const [approval, getApproval] = useApproval(amountToApprove, spender, useHasPendingApproval)
return [approval, useGetAndTrackApproval(getApproval)]
}
export function useApprovalOptimizedTrade(
trade: Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent
) {
return useSwapApprovalOptimizedTrade(trade, allowedSlippage, useHasPendingApproval)
}
// wraps useApproveCallback in the context of a swap
export function useApproveCallbackFromTrade(
trade:
| V2Trade<Currency, Currency, TradeType>
@@ -141,85 +45,7 @@ export function useApproveCallbackFromTrade(
| Trade<Currency, Currency, TradeType>
| undefined,
allowedSlippage: Percent
) {
const { chainId } = useActiveWeb3React()
const amountToApprove = useMemo(
() => (trade && trade.inputAmount.currency.isToken ? trade.maximumAmountIn(allowedSlippage) : undefined),
[trade, allowedSlippage]
)
const approveCallback = useApproveCallback(
amountToApprove,
chainId
? trade instanceof V2Trade
? V2_ROUTER_ADDRESS[chainId]
: trade instanceof V3Trade
? V3_ROUTER_ADDRESS[chainId]
: SWAP_ROUTER_ADDRESSES[chainId]
: undefined
)
// TODO: remove L162-168 after testing is done. This error will help detect mistakes in the logic.
if (
(Trade instanceof V2Trade && approveCallback[0] !== ApprovalState.APPROVED) ||
(trade instanceof V3Trade && approveCallback[0] !== ApprovalState.APPROVED)
) {
throw new Error('Trying to approve legacy router')
}
return approveCallback
}
export function useApprovalOptimizedTrade(
trade: Trade<Currency, Currency, TradeType> | undefined,
allowedSlippage: Percent
):
| V2Trade<Currency, Currency, TradeType>
| V3Trade<Currency, Currency, TradeType>
| Trade<Currency, Currency, TradeType>
| undefined {
const onlyV2Routes = trade?.routes.every((route) => route.protocol === Protocol.V2)
const onlyV3Routes = trade?.routes.every((route) => route.protocol === Protocol.V3)
const tradeHasSplits = (trade?.routes.length ?? 0) > 1
const approvalStates = useAllApprovalStates(trade, allowedSlippage)
const optimizedSwapRouter = useMemo(
() => getTxOptimizedSwapRouter({ onlyV2Routes, onlyV3Routes, tradeHasSplits, approvalStates }),
[approvalStates, tradeHasSplits, onlyV2Routes, onlyV3Routes]
)
return useMemo(() => {
if (!trade) return undefined
try {
switch (optimizedSwapRouter) {
case SwapRouterVersion.V2V3:
return trade
case SwapRouterVersion.V2:
const pairs = trade.swaps[0].route.pools.filter((pool) => pool instanceof Pair) as Pair[]
const v2Route = new V2Route(pairs, trade.inputAmount.currency, trade.outputAmount.currency)
return new V2Trade(v2Route, trade.inputAmount, trade.tradeType)
case SwapRouterVersion.V3:
return V3Trade.createUncheckedTradeWithMultipleRoutes({
routes: trade.swaps.map(({ route, inputAmount, outputAmount }) => ({
route: new V3Route(
route.pools.filter((p) => p instanceof Pool) as Pool[],
inputAmount.currency,
outputAmount.currency
),
inputAmount,
outputAmount,
})),
tradeType: trade.tradeType,
})
default:
return undefined
}
} catch (e) {
// TODO(#2989): remove try-catch
console.debug(e)
return undefined
}
}, [trade, optimizedSwapRouter])
): [ApprovalState, () => Promise<void>] {
const [approval, getApproval] = useSwapApproval(trade, allowedSlippage, useHasPendingApproval)
return [approval, useGetAndTrackApproval(getApproval)]
}

View File

@@ -1,8 +1,9 @@
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import ArgentWalletContractABI from '../abis/argent-wallet-contract.json'
import { ArgentWalletContract } from '../abis/types'
import { useContract } from './useContract'
import useIsArgentWallet from './useIsArgentWallet'
import { useActiveWeb3React } from './web3'
export function useArgentWalletContract(): ArgentWalletContract | null {
const { account } = useActiveWeb3React()

View File

@@ -1,6 +1,5 @@
import { AUTO_ROUTER_SUPPORTED_CHAINS } from 'state/routing/clientSideSmartOrderRouter/constants'
import { useActiveWeb3React } from './web3'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { AUTO_ROUTER_SUPPORTED_CHAINS } from 'lib/hooks/routing/clientSideSmartOrderRouter'
export default function useAutoRouterSupported(): boolean {
const { chainId } = useActiveWeb3React()

View File

@@ -1,16 +1,15 @@
import { Trade } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'components/swap/GasEstimateBadge'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains'
import { L2_CHAIN_IDS } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import JSBI from 'jsbi'
import useNativeCurrency from 'lib/hooks/useNativeCurrency'
import { useMemo } from 'react'
import { InterfaceTrade } from 'state/routing/types'
import { useUserSlippageToleranceWithDefault } from '../state/user/hooks'
import { useNativeCurrency } from './Tokens'
import useGasPrice from './useGasPrice'
import useUSDCPrice, { useUSDCValue } from './useUSDCPrice'
import { useActiveWeb3React } from './web3'
const V3_SWAP_DEFAULT_SLIPPAGE = new Percent(50, 10_000) // .50%
const ONE_TENTHS_PERCENT = new Percent(10, 10_000) // .10%
@@ -29,7 +28,10 @@ function guesstimateGas(trade: Trade<Currency, Currency, TradeType> | undefined)
const MIN_AUTO_SLIPPAGE_TOLERANCE = new Percent(5, 1000) // 0.5%
const MAX_AUTO_SLIPPAGE_TOLERANCE = new Percent(25, 100) // 25%
export default function useSwapSlippageTolerance(
/**
* Returns slippage tolerance based on values from current trade, gas estimates from api, and active network.
*/
export default function useAutoSlippageTolerance(
trade: InterfaceTrade<Currency, Currency, TradeType> | undefined
): Percent {
const { chainId } = useActiveWeb3React()
@@ -41,7 +43,7 @@ export default function useSwapSlippageTolerance(
const nativeCurrency = useNativeCurrency()
const nativeCurrencyPrice = useUSDCPrice(nativeCurrency ?? undefined)
const defaultSlippageTolerance = useMemo(() => {
return useMemo(() => {
if (!trade || onL2) return ONE_TENTHS_PERCENT
const nativeGasCost =
@@ -73,6 +75,4 @@ export default function useSwapSlippageTolerance(
return V3_SWAP_DEFAULT_SLIPPAGE
}, [trade, onL2, nativeGasPrice, gasEstimate, nativeCurrency, nativeCurrencyPrice, chainId, outputDollarValue])
return useUserSlippageToleranceWithDefault(defaultSlippageTolerance)
}

View File

@@ -1,4 +1,5 @@
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import { useMemo } from 'react'
import { InterfaceTrade, TradeState } from 'state/routing/types'
import { useRoutingAPITrade } from 'state/routing/useRoutingAPITrade'
@@ -24,7 +25,10 @@ export function useBestTrade(
const autoRouterSupported = useAutoRouterSupported()
const isWindowVisible = useIsWindowVisible()
const [debouncedAmount, debouncedOtherCurrency] = useDebounce([amountSpecified, otherCurrency], 200)
const [debouncedAmount, debouncedOtherCurrency] = useDebounce(
useMemo(() => [amountSpecified, otherCurrency], [amountSpecified, otherCurrency]),
200
)
const routingAPITrade = useRoutingAPITrade(
tradeType,
@@ -56,9 +60,12 @@ export function useBestTrade(
)
// only return gas estimate from api if routing api trade is used
return {
...(useFallback ? bestV3Trade : routingAPITrade),
...(debouncing ? { state: TradeState.SYNCING } : {}),
...(isLoading ? { state: TradeState.LOADING } : {}),
}
return useMemo(
() => ({
...(useFallback ? bestV3Trade : routingAPITrade),
...(debouncing ? { state: TradeState.SYNCING } : {}),
...(isLoading ? { state: TradeState.LOADING } : {}),
}),
[bestV3Trade, debouncing, isLoading, routingAPITrade, useFallback]
)
}

View File

@@ -1,14 +1,14 @@
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
import { Route, SwapQuoter } from '@uniswap/v3-sdk'
import { SupportedChainId } from 'constants/chains'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import JSBI from 'jsbi'
import { useSingleContractWithCallData } from 'lib/hooks/multicall'
import { useMemo } from 'react'
import { InterfaceTrade, TradeState } from 'state/routing/types'
import { useSingleContractWithCallData } from '../state/multicall/hooks'
import { useAllV3Routes } from './useAllV3Routes'
import { useV3Quoter } from './useContract'
import { useActiveWeb3React } from './web3'
const QUOTE_GAS_OVERRIDES: { [chainId: number]: number } = {
[SupportedChainId.ARBITRUM_ONE]: 25_000_000,

View File

@@ -1,10 +1,10 @@
import { Token } from '@uniswap/sdk-core'
import { SupportedChainId } from 'constants/chains'
import uriToHttp from 'lib/utils/uriToHttp'
import Vibrant from 'node-vibrant/lib/bundle'
import { shade } from 'polished'
import { useLayoutEffect, useState } from 'react'
import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo'
import uriToHttp from 'utils/uriToHttp'
import { hex } from 'wcag-contrast'
function URIForEthToken(address: string) {

View File

@@ -1,14 +1,11 @@
import { Contract } from '@ethersproject/contracts'
import { abi as GOVERNANCE_ABI } from '@uniswap/governance/build/GovernorAlpha.json'
import { abi as UNI_ABI } from '@uniswap/governance/build/Uni.json'
import { abi as STAKING_REWARDS_ABI } from '@uniswap/liquidity-staker/build/StakingRewards.json'
import { abi as MERKLE_DISTRIBUTOR_ABI } from '@uniswap/merkle-distributor/build/MerkleDistributor.json'
import { abi as IUniswapV2PairABI } from '@uniswap/v2-core/build/IUniswapV2Pair.json'
import { abi as IUniswapV2Router02ABI } from '@uniswap/v2-periphery/build/IUniswapV2Router02.json'
import { abi as QuoterABI } from '@uniswap/v3-periphery/artifacts/contracts/lens/Quoter.sol/Quoter.json'
import { abi as MulticallABI } from '@uniswap/v3-periphery/artifacts/contracts/lens/UniswapInterfaceMulticall.sol/UniswapInterfaceMulticall.json'
import { abi as NFTPositionManagerABI } from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
import { abi as V2MigratorABI } from '@uniswap/v3-periphery/artifacts/contracts/V3Migrator.sol/V3Migrator.json'
import IUniswapV2PairJson from '@uniswap/v2-core/build/IUniswapV2Pair.json'
import IUniswapV2Router02Json from '@uniswap/v2-periphery/build/IUniswapV2Router02.json'
import QuoterJson from '@uniswap/v3-periphery/artifacts/contracts/lens/Quoter.sol/Quoter.json'
import TickLensJson from '@uniswap/v3-periphery/artifacts/contracts/lens/TickLens.sol/TickLens.json'
import UniswapInterfaceMulticallJson from '@uniswap/v3-periphery/artifacts/contracts/lens/UniswapInterfaceMulticall.sol/UniswapInterfaceMulticall.json'
import NonfungiblePositionManagerJson from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
import V3MigratorJson from '@uniswap/v3-periphery/artifacts/contracts/V3Migrator.sol/V3Migrator.json'
import ARGENT_WALLET_DETECTOR_ABI from 'abis/argent-wallet-detector.json'
import EIP_2612 from 'abis/eip_2612.json'
import ENS_PUBLIC_RESOLVER_ABI from 'abis/ens-public-resolver.json'
@@ -17,29 +14,33 @@ import ERC20_ABI from 'abis/erc20.json'
import ERC20_BYTES32_ABI from 'abis/erc20_bytes32.json'
import ERC721_ABI from 'abis/erc721.json'
import ERC1155_ABI from 'abis/erc1155.json'
import GOVERNOR_BRAVO_ABI from 'abis/governor-bravo.json'
import { ArgentWalletDetector, EnsPublicResolver, EnsRegistrar, Erc20, Erc721, Erc1155, Weth } from 'abis/types'
import WETH_ABI from 'abis/weth.json'
import {
ARGENT_WALLET_DETECTOR_ADDRESS,
ENS_REGISTRAR_ADDRESSES,
GOVERNANCE_ALPHA_V0_ADDRESSES,
GOVERNANCE_ALPHA_V1_ADDRESSES,
GOVERNANCE_BRAVO_ADDRESSES,
MERKLE_DISTRIBUTOR_ADDRESS,
MULTICALL_ADDRESS,
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
QUOTER_ADDRESSES,
TICK_LENS_ADDRESSES,
V2_ROUTER_ADDRESS,
V3_MIGRATOR_ADDRESSES,
} from 'constants/addresses'
import { WRAPPED_NATIVE_CURRENCY } from 'constants/tokens'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useMemo } from 'react'
import { NonfungiblePositionManager, Quoter, UniswapInterfaceMulticall } from 'types/v3'
import { NonfungiblePositionManager, Quoter, TickLens, UniswapInterfaceMulticall } from 'types/v3'
import { V3Migrator } from 'types/v3/V3Migrator'
import { getContract } from 'utils'
import { ArgentWalletDetector, EnsPublicResolver, EnsRegistrar, Erc20, Erc721, Erc1155, Weth } from '../abis/types'
import { UNI, WRAPPED_NATIVE_CURRENCY } from '../constants/tokens'
import { useActiveWeb3React } from './web3'
import { getContract } from '../utils'
const { abi: IUniswapV2PairABI } = IUniswapV2PairJson
const { abi: IUniswapV2Router02ABI } = IUniswapV2Router02Json
const { abi: QuoterABI } = QuoterJson
const { abi: TickLensABI } = TickLensJson
const { abi: MulticallABI } = UniswapInterfaceMulticallJson
const { abi: NFTPositionManagerABI } = NonfungiblePositionManagerJson
const { abi: V2MigratorABI } = V3MigratorJson
// returns null on errors
export function useContract<T extends Contract = Contract>(
@@ -121,33 +122,6 @@ export function useInterfaceMulticall() {
return useContract<UniswapInterfaceMulticall>(MULTICALL_ADDRESS, MulticallABI, false) as UniswapInterfaceMulticall
}
export function useMerkleDistributorContract() {
return useContract(MERKLE_DISTRIBUTOR_ADDRESS, MERKLE_DISTRIBUTOR_ABI, true)
}
export function useGovernanceV0Contract(): Contract | null {
return useContract(GOVERNANCE_ALPHA_V0_ADDRESSES, GOVERNANCE_ABI, false)
}
export function useGovernanceV1Contract(): Contract | null {
return useContract(GOVERNANCE_ALPHA_V1_ADDRESSES, GOVERNANCE_ABI, false)
}
export function useGovernanceBravoContract(): Contract | null {
return useContract(GOVERNANCE_BRAVO_ADDRESSES, GOVERNOR_BRAVO_ABI, true)
}
export const useLatestGovernanceContract = useGovernanceBravoContract
export function useUniContract() {
const { chainId } = useActiveWeb3React()
return useContract(chainId ? UNI[chainId]?.address : undefined, UNI_ABI, true)
}
export function useStakingContract(stakingAddress?: string, withSignerIfPossible?: boolean) {
return useContract(stakingAddress, STAKING_REWARDS_ABI, withSignerIfPossible)
}
export function useV3NFTPositionManagerContract(withSignerIfPossible?: boolean): NonfungiblePositionManager | null {
return useContract<NonfungiblePositionManager>(
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES,
@@ -159,3 +133,9 @@ export function useV3NFTPositionManagerContract(withSignerIfPossible?: boolean):
export function useV3Quoter() {
return useContract<Quoter>(QUOTER_ADDRESSES, QuoterABI)
}
export function useTickLens(): TickLens | null {
const { chainId } = useActiveWeb3React()
const address = chainId ? TICK_LENS_ADDRESSES[chainId] : undefined
return useContract(address, TickLensABI) as TickLens | null
}

View File

@@ -1,6 +1,6 @@
import { BigNumber } from '@ethersproject/bignumber'
import { useSingleCallResult } from 'lib/hooks/multicall'
import { useSingleCallResult } from '../state/multicall/hooks'
import { useInterfaceMulticall } from './useContract'
// gets the current timestamp from the blockchain

View File

@@ -1,5 +1,9 @@
import { useEffect, useState } from 'react'
/**
* Debounces updates to a value.
* Non-primitives *must* wrap the value in useMemo, or the value will be updated due to referential inequality.
*/
// modified from https://usehooks.com/useDebounce/
export default function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value)

View File

@@ -1,7 +1,7 @@
import { useSingleCallResult } from 'lib/hooks/multicall'
import { useMemo } from 'react'
import { safeNamehash } from 'utils/safeNamehash'
import { useSingleCallResult } from '../state/multicall/hooks'
import isZero from '../utils/isZero'
import { useENSRegistrarContract, useENSResolverContract } from './useContract'
import useDebounce from './useDebounce'

View File

@@ -1,15 +1,17 @@
import { BigNumber } from '@ethersproject/bignumber'
import { hexZeroPad } from '@ethersproject/bytes'
import { namehash } from '@ethersproject/hash'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { useSingleCallResult } from 'lib/hooks/multicall'
import uriToHttp from 'lib/utils/uriToHttp'
import { useEffect, useMemo, useState } from 'react'
import { safeNamehash } from 'utils/safeNamehash'
import uriToHttp from 'utils/uriToHttp'
import { useSingleCallResult } from '../state/multicall/hooks'
import { isAddress } from '../utils'
import isZero from '../utils/isZero'
import { useENSRegistrarContract, useENSResolverContract, useERC721Contract, useERC1155Contract } from './useContract'
import useDebounce from './useDebounce'
import useENSName from './useENSName'
import { useActiveWeb3React } from './web3'
/**
* Returns the ENS avatar URI, if available.
@@ -134,11 +136,14 @@ function useERC1155Uri(
const contract = useERC1155Contract(contractAddress)
const balance = useSingleCallResult(contract, 'balanceOf', accountArgument)
const uri = useSingleCallResult(contract, 'uri', idArgument)
// ERC-1155 allows a generic {id} in the URL, so prepare to replace if relevant,
// in lowercase hexadecimal (with no 0x prefix) and leading zero padded to 64 hex characters.
const idHex = id ? hexZeroPad(BigNumber.from(id).toHexString(), 32).substring(2) : id
return useMemo(
() => ({
uri: !enforceOwnership || balance.result?.[0] > 0 ? uri.result?.[0] : undefined,
uri: !enforceOwnership || balance.result?.[0] > 0 ? uri.result?.[0]?.replaceAll('{id}', idHex) : undefined,
loading: balance.loading || uri.loading,
}),
[balance.loading, balance.result, enforceOwnership, uri.loading, uri.result]
[balance.loading, balance.result, enforceOwnership, uri.loading, uri.result, idHex]
)
}

View File

@@ -1,7 +1,7 @@
import { useSingleCallResult } from 'lib/hooks/multicall'
import { useMemo } from 'react'
import { safeNamehash } from 'utils/safeNamehash'
import { useSingleCallResult } from '../state/multicall/hooks'
import isZero from '../utils/isZero'
import { useENSRegistrarContract, useENSResolverContract } from './useContract'

View File

@@ -1,7 +1,7 @@
import { namehash } from '@ethersproject/hash'
import { useSingleCallResult } from 'lib/hooks/multicall'
import { useMemo } from 'react'
import { useSingleCallResult } from '../state/multicall/hooks'
import { isAddress } from '../utils'
import isZero from '../utils/isZero'
import { useENSRegistrarContract, useENSResolverContract } from './useContract'

View File

@@ -1,20 +1,20 @@
import { BigNumber } from '@ethersproject/bignumber'
import { splitSignature } from '@ethersproject/bytes'
import { Trade } from '@uniswap/router-sdk'
import { Currency, CurrencyAmount, Percent, Token, TradeType } from '@uniswap/sdk-core'
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import JSBI from 'jsbi'
import { useSingleCallResult } from 'lib/hooks/multicall'
import { useMemo, useState } from 'react'
import { SWAP_ROUTER_ADDRESSES, V3_ROUTER_ADDRESS } from '../constants/addresses'
import { DAI, UNI, USDC } from '../constants/tokens'
import { useSingleCallResult } from '../state/multicall/hooks'
import { useEIP2612Contract } from './useContract'
import useIsArgentWallet from './useIsArgentWallet'
import useTransactionDeadline from './useTransactionDeadline'
import { useActiveWeb3React } from './web3'
enum PermitType {
export enum PermitType {
AMOUNT = 1,
ALLOWED = 2,
}
@@ -22,7 +22,7 @@ enum PermitType {
// 20 minutes to submit after signing
const PERMIT_VALIDITY_BUFFER = 20 * 60
interface PermitInfo {
export interface PermitInfo {
type: PermitType
name: string
// version is optional, and if omitted, will not be included in the domain
@@ -116,9 +116,10 @@ const PERMIT_ALLOWED_TYPE = [
{ name: 'allowed', type: 'bool' },
]
function useERC20Permit(
export function useERC20Permit(
currencyAmount: CurrencyAmount<Currency> | null | undefined,
spender: string | null | undefined,
transactionDeadline: BigNumber | undefined,
overridePermitInfo: PermitInfo | undefined | null
): {
signatureData: SignatureData | null
@@ -126,7 +127,6 @@ function useERC20Permit(
gatherPermitSignature: null | (() => Promise<void>)
} {
const { account, chainId, library } = useActiveWeb3React()
const transactionDeadline = useTransactionDeadline()
const tokenAddress = currencyAmount?.currency?.isToken ? currencyAmount.currency.address : undefined
const eip2612Contract = useEIP2612Contract(tokenAddress)
const isArgentWallet = useIsArgentWallet()
@@ -259,26 +259,14 @@ function useERC20Permit(
])
}
const REMOVE_V2_LIQUIDITY_PERMIT_INFO: PermitInfo = {
version: '1',
name: 'Uniswap V2',
type: PermitType.AMOUNT,
}
export function useV2LiquidityTokenPermit(
liquidityAmount: CurrencyAmount<Token> | null | undefined,
spender: string | null | undefined
) {
return useERC20Permit(liquidityAmount, spender, REMOVE_V2_LIQUIDITY_PERMIT_INFO)
}
export function useERC20PermitFromTrade(
trade:
| V2Trade<Currency, Currency, TradeType>
| V3Trade<Currency, Currency, TradeType>
| Trade<Currency, Currency, TradeType>
| undefined,
allowedSlippage: Percent
allowedSlippage: Percent,
transactionDeadline: BigNumber | undefined
) {
const { chainId } = useActiveWeb3React()
const swapRouterAddress = chainId
@@ -294,5 +282,5 @@ export function useERC20PermitFromTrade(
[trade, allowedSlippage]
)
return useERC20Permit(amountToApprove, swapRouterAddress, null)
return useERC20Permit(amountToApprove, swapRouterAddress, transactionDeadline, null)
}

View File

@@ -1,10 +1,10 @@
import { skipToken } from '@reduxjs/toolkit/query/react'
import { Currency, Token } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk'
import useBlockNumber from 'lib/hooks/useBlockNumber'
import ms from 'ms.macro'
import { useMemo } from 'react'
import ReactGA from 'react-ga'
import { useBlockNumber } from 'state/application/hooks'
import { useFeeTierDistributionQuery } from 'state/data/enhanced'
import { FeeTierDistributionQuery } from 'state/data/generated'

View File

@@ -1,13 +1,13 @@
import { nanoid } from '@reduxjs/toolkit'
import { TokenList } from '@uniswap/token-lists'
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import getTokenList from 'lib/hooks/useTokenList/fetchTokenList'
import resolveENSContentHash from 'lib/utils/resolveENSContentHash'
import { useCallback } from 'react'
import { useAppDispatch } from 'state/hooks'
import { getNetworkLibrary } from '../connectors'
import { fetchTokenList } from '../state/lists/actions'
import getTokenList from '../utils/getTokenList'
import resolveENSContentHash from '../utils/resolveENSContentHash'
import { useActiveWeb3React } from './web3'
export function useFetchListCallback(): (listUrl: string, sendDispatch?: boolean) => Promise<TokenList> {
const { chainId, library } = useActiveWeb3React()

View File

@@ -1,6 +1,6 @@
import JSBI from 'jsbi'
import { useSingleCallResult } from 'lib/hooks/multicall'
import { useSingleCallResult } from '../state/multicall/hooks'
import { useContract } from './useContract'
import useENSAddress from './useENSAddress'

View File

@@ -1,8 +1,8 @@
import contenthashToUri from 'lib/utils/contenthashToUri'
import parseENSAddress from 'lib/utils/parseENSAddress'
import uriToHttp from 'lib/utils/uriToHttp'
import { useMemo } from 'react'
import contenthashToUri from '../utils/contenthashToUri'
import { parseENSAddress } from '../utils/parseENSAddress'
import uriToHttp from '../utils/uriToHttp'
import useENSContentHash from './useENSContentHash'
export default function useHttpLocations(uri: string | undefined): string[] {

View File

@@ -1,8 +1,8 @@
import useActiveWeb3React from 'hooks/useActiveWeb3React'
import { NEVER_RELOAD, useSingleCallResult } from 'lib/hooks/multicall'
import { useMemo } from 'react'
import { NEVER_RELOAD, useSingleCallResult } from '../state/multicall/hooks'
import { useArgentWalletDetectorContract } from './useContract'
import { useActiveWeb3React } from './web3'
export default function useIsArgentWallet(): boolean {
const { account } = useActiveWeb3React()

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