Compare commits
405 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20dbb2a9f7 | ||
|
|
fd4430fe69 | ||
|
|
167cc695c9 | ||
|
|
e175bff7f4 | ||
|
|
4442933eac | ||
|
|
8447b30327 | ||
|
|
22ce55ec46 | ||
|
|
b25da9de2d | ||
|
|
ae1fb4367f | ||
|
|
1410edda32 | ||
|
|
3bc7f015ee | ||
|
|
802714377c | ||
|
|
352daf959e | ||
|
|
92c21c2811 | ||
|
|
e70723aaf3 | ||
|
|
1802f50163 | ||
|
|
2aa1b18d14 | ||
|
|
a286e5b114 | ||
|
|
62361647e0 | ||
|
|
deee278439 | ||
|
|
6340deb201 | ||
|
|
28b154ebe8 | ||
|
|
3bde2165f4 | ||
|
|
78c8fd2359 | ||
|
|
c378752910 | ||
|
|
0bf7b92013 | ||
|
|
283479f76e | ||
|
|
d3c30e2f6b | ||
|
|
32d226f78e | ||
|
|
96744505c0 | ||
|
|
97236033d4 | ||
|
|
86e62dc4b9 | ||
|
|
e584a5fa36 | ||
|
|
332ef6e6c8 | ||
|
|
8cbd111e65 | ||
|
|
55ffcbd465 | ||
|
|
404775e86d | ||
|
|
0ae9fe28a2 | ||
|
|
89c0caae43 | ||
|
|
c8086e3c76 | ||
|
|
1c2842e5a0 | ||
|
|
a2c6d3f475 | ||
|
|
841ea7f8a1 | ||
|
|
804692b114 | ||
|
|
6282298d13 | ||
|
|
7a5b855097 | ||
|
|
c9908748cf | ||
|
|
79b77deee1 | ||
|
|
a554af6670 | ||
|
|
1843f214b1 | ||
|
|
3e0788092e | ||
|
|
d14c49df0d | ||
|
|
c098ad1ffe | ||
|
|
48114ef51d | ||
|
|
4529e3cc88 | ||
|
|
cb7132ee17 | ||
|
|
4d47470f33 | ||
|
|
aedc020646 | ||
|
|
0fa4859a09 | ||
|
|
f8bb5046f0 | ||
|
|
7d1589d1df | ||
|
|
26b603cc2e | ||
|
|
ece68a0ec7 | ||
|
|
fd212477ce | ||
|
|
a16d2387cc | ||
|
|
cae56ec385 | ||
|
|
d16b3473e0 | ||
|
|
f66f249dba | ||
|
|
08afd888d0 | ||
|
|
b427be2673 | ||
|
|
f753a5e325 | ||
|
|
46d9d8e3df | ||
|
|
680d3a3f26 | ||
|
|
e4c625ee71 | ||
|
|
fd8085722e | ||
|
|
a60a85db54 | ||
|
|
ad2472eac6 | ||
|
|
f4d4acacae | ||
|
|
a5d7af192c | ||
|
|
21a2863ae3 | ||
|
|
1f871d4e73 | ||
|
|
3690936aff | ||
|
|
e95e2321b4 | ||
|
|
8b1bf09ff1 | ||
|
|
6383e9e4bf | ||
|
|
515ce9253d | ||
|
|
23ed384802 | ||
|
|
9ae31aa26e | ||
|
|
642c489240 | ||
|
|
778ea8ee42 | ||
|
|
36900fe6c6 | ||
|
|
40eb28f1e1 | ||
|
|
7c3ee78715 | ||
|
|
ccac51ec1f | ||
|
|
77747f9f6f | ||
|
|
0622ff30f6 | ||
|
|
982c99b07f | ||
|
|
484a7d49f6 | ||
|
|
082591d5dd | ||
|
|
aa03f97890 | ||
|
|
fd12a0d6e7 | ||
|
|
0176c74430 | ||
|
|
35613cc979 | ||
|
|
b0d71f10e9 | ||
|
|
1cfb3d8034 | ||
|
|
a650807c96 | ||
|
|
6efd7ca779 | ||
|
|
d658720505 | ||
|
|
bba40846e1 | ||
|
|
8fa6c87015 | ||
|
|
933d02b275 | ||
|
|
7738a6b9e0 | ||
|
|
2db4b1da3d | ||
|
|
06c85b744f | ||
|
|
aa29ea80a9 | ||
|
|
3613dc2d4a | ||
|
|
e22554b4c4 | ||
|
|
5f1625f5dc | ||
|
|
c1e6dd7335 | ||
|
|
45419c2739 | ||
|
|
c2342a86d6 | ||
|
|
504cd5b848 | ||
|
|
1faf13639c | ||
|
|
69c084ebe7 | ||
|
|
e5ac7e77da | ||
|
|
0614358a5e | ||
|
|
42784e6121 | ||
|
|
830500dc3b | ||
|
|
5af32592aa | ||
|
|
0f36a99e98 | ||
|
|
5fe9f3f6e8 | ||
|
|
167fff16a0 | ||
|
|
a6eff7823a | ||
|
|
1aba4fbcd7 | ||
|
|
714d215cda | ||
|
|
0f32ed34f7 | ||
|
|
3703e843f8 | ||
|
|
3c3158f443 | ||
|
|
f933e538e6 | ||
|
|
02b678b4a9 | ||
|
|
c25a2cfc00 | ||
|
|
a5d75cad5b | ||
|
|
40784963a5 | ||
|
|
6ca8e4f664 | ||
|
|
91c0580825 | ||
|
|
c518501e7b | ||
|
|
d59e4f334e | ||
|
|
4c3528a03d | ||
|
|
ed82f9ff8a | ||
|
|
dd5a22ce83 | ||
|
|
185c1f6772 | ||
|
|
93e6b65cb3 | ||
|
|
965a745d5e | ||
|
|
6d97590c0f | ||
|
|
8e7ab6f8c3 | ||
|
|
61729610c2 | ||
|
|
53860dd8e4 | ||
|
|
19028c1d82 | ||
|
|
6676d80707 | ||
|
|
f9f804c381 | ||
|
|
0a0b56b13d | ||
|
|
480f3f29f3 | ||
|
|
5f2072f449 | ||
|
|
4e144c7fb5 | ||
|
|
cfbb6a7129 | ||
|
|
61f03af20a | ||
|
|
5eb1274f97 | ||
|
|
9eb7d45aea | ||
|
|
2e1d4fdda1 | ||
|
|
e85b6e4cc6 | ||
|
|
9c334bc865 | ||
|
|
6a833fc740 | ||
|
|
80ed8eb6c2 | ||
|
|
a14d2df8e6 | ||
|
|
09511b06f2 | ||
|
|
9def686344 | ||
|
|
a88c083758 | ||
|
|
1a6cad4a8f | ||
|
|
505b3f2a20 | ||
|
|
1b5a145738 | ||
|
|
dbdd3a8e16 | ||
|
|
78e438294f | ||
|
|
2c014c6f38 | ||
|
|
7b3b7864ad | ||
|
|
e35eefbeb3 | ||
|
|
049a7d1d6a | ||
|
|
28d6c6454e | ||
|
|
f96ecb59eb | ||
|
|
a4c54ff953 | ||
|
|
d4cb32c4c3 | ||
|
|
efb76200ce | ||
|
|
a96bdaad04 | ||
|
|
b89860dc53 | ||
|
|
e640dccebd | ||
|
|
4710b832fa | ||
|
|
fb07666e23 | ||
|
|
22f64a98a1 | ||
|
|
50f6401a8a | ||
|
|
6480b947ef | ||
|
|
f41cbbb58f | ||
|
|
0cb098b9d4 | ||
|
|
76f5638583 | ||
|
|
c840de73db | ||
|
|
ab4271b2ff | ||
|
|
6f0586c596 | ||
|
|
9f33ed06dd | ||
|
|
85f4cec829 | ||
|
|
5e23501d58 | ||
|
|
6bc98363cc | ||
|
|
e15ccc3c79 | ||
|
|
e8880be1d9 | ||
|
|
0e9b05405d | ||
|
|
55d85d2623 | ||
|
|
7fb7517a1a | ||
|
|
1a6fe3c1a8 | ||
|
|
a49ff49185 | ||
|
|
ca1dc593d9 | ||
|
|
afacc4a348 | ||
|
|
91157b7a43 | ||
|
|
d5e676efb5 | ||
|
|
9ac83bea7e | ||
|
|
53b9a847ca | ||
|
|
04f9127961 | ||
|
|
5364eb5715 | ||
|
|
5126e24d19 | ||
|
|
a06bb79039 | ||
|
|
a446dc7f10 | ||
|
|
e903a335d6 | ||
|
|
3be5e9b5fe | ||
|
|
818e98328e | ||
|
|
aa3225c21c | ||
|
|
35d66f1e09 | ||
|
|
e156635f77 | ||
|
|
d2a97c62ed | ||
|
|
6aa999f713 | ||
|
|
0a3f8636e7 | ||
|
|
f5de7178d9 | ||
|
|
6c203cc990 | ||
|
|
3a40159147 | ||
|
|
c6f6bd446b | ||
|
|
416212be3b | ||
|
|
ce9f4525a3 | ||
|
|
23a250aae0 | ||
|
|
5d5e0f4596 | ||
|
|
d6199e0f61 | ||
|
|
a611cd03d8 | ||
|
|
bacc9667e8 | ||
|
|
41776655dc | ||
|
|
a350f59811 | ||
|
|
bdc336e188 | ||
|
|
8f44adb038 | ||
|
|
e4ae705eb1 | ||
|
|
1afc36454d | ||
|
|
1b65d6a1ce | ||
|
|
677fabf71a | ||
|
|
e138e0ecf2 | ||
|
|
60bd2db4c1 | ||
|
|
c7dd0f06e7 | ||
|
|
76dc71e442 | ||
|
|
88bb048920 | ||
|
|
1344e57c4d | ||
|
|
0b18bf0813 | ||
|
|
1195be5747 | ||
|
|
3aa98d626b | ||
|
|
362873d968 | ||
|
|
2fe5e487f4 | ||
|
|
5b418c68af | ||
|
|
18f64d6dac | ||
|
|
af2725ec25 | ||
|
|
6fd5dc0cfc | ||
|
|
ce5c0ff453 | ||
|
|
b419b85694 | ||
|
|
9d37b1bb55 | ||
|
|
57371fb47e | ||
|
|
e9dd0c90e0 | ||
|
|
f373a52da4 | ||
|
|
e4473e3007 | ||
|
|
da2f168eeb | ||
|
|
76e3caa659 | ||
|
|
7fa91d1442 | ||
|
|
d999388876 | ||
|
|
82c7657402 | ||
|
|
cb4101e606 | ||
|
|
92b0433184 | ||
|
|
21e5208d5c | ||
|
|
6b09aa9457 | ||
|
|
21594343b5 | ||
|
|
f29c9f8440 | ||
|
|
a6549dd340 | ||
|
|
9dabacef9b | ||
|
|
80921e782f | ||
|
|
183beddc72 | ||
|
|
7ce718df22 | ||
|
|
82fd79f0e2 | ||
|
|
d24c62ec4b | ||
|
|
2ea70d1894 | ||
|
|
448090b534 | ||
|
|
b1fd484894 | ||
|
|
aeb636cf8a | ||
|
|
4240908c4c | ||
|
|
d53ba64218 | ||
|
|
89ce5a9805 | ||
|
|
1790492f17 | ||
|
|
304cd72eed | ||
|
|
9dba68b34c | ||
|
|
588567b900 | ||
|
|
ef964ab120 | ||
|
|
f3d64b65da | ||
|
|
a9200b2c39 | ||
|
|
209fd33780 | ||
|
|
940c1dbb8e | ||
|
|
5dce68a62f | ||
|
|
9dd8ad1db6 | ||
|
|
0b40f72f0c | ||
|
|
875171e36a | ||
|
|
8e9a20a6c8 | ||
|
|
1a31560374 | ||
|
|
d528b28203 | ||
|
|
c1cb712087 | ||
|
|
ceed5e0b4c | ||
|
|
a449338252 | ||
|
|
9662344e24 | ||
|
|
1536e18784 | ||
|
|
c19431eb20 | ||
|
|
634e38529c | ||
|
|
083ec425d0 | ||
|
|
e8c09db146 | ||
|
|
9ab4d952ef | ||
|
|
48883cce8d | ||
|
|
3d820d39b7 | ||
|
|
4fdca48a97 | ||
|
|
7834ab7979 | ||
|
|
dee808cc57 | ||
|
|
4c23f62a24 | ||
|
|
93633a81a7 | ||
|
|
7465a0e999 | ||
|
|
6aac978754 | ||
|
|
62775f6091 | ||
|
|
97b3725c19 | ||
|
|
46563ee565 | ||
|
|
c68624e048 | ||
|
|
0fa1c5e6ea | ||
|
|
a7fd60987e | ||
|
|
51fe44d53a | ||
|
|
edf67e8e45 | ||
|
|
babfebccef | ||
|
|
ea02d9e919 | ||
|
|
bb3b236cd9 | ||
|
|
1d3fd512ae | ||
|
|
5dbd0ae782 | ||
|
|
b95621758c | ||
|
|
ce51ffae75 | ||
|
|
8cd32138ac | ||
|
|
785c2a6712 | ||
|
|
56a9952546 | ||
|
|
7059a12a25 | ||
|
|
da01254247 | ||
|
|
54a7b943ce | ||
|
|
ec6c843db6 | ||
|
|
7a6bb369d4 | ||
|
|
66a38c8e51 | ||
|
|
f79d2f821e | ||
|
|
72c5e64f74 | ||
|
|
01a44d49b0 | ||
|
|
f0412f5d47 | ||
|
|
2887ee9ac8 | ||
|
|
79d5211db4 | ||
|
|
d05e5d028b | ||
|
|
d3a415ee96 | ||
|
|
db9ac38c64 | ||
|
|
f27d119181 | ||
|
|
f2b85621f5 | ||
|
|
d7bc0aaf4c | ||
|
|
f50e0ca9f9 | ||
|
|
84960b0cef | ||
|
|
42646003fe | ||
|
|
321b8df3a2 | ||
|
|
f1990ff001 | ||
|
|
b48af759f1 | ||
|
|
3969f0414d | ||
|
|
9dc6c60a1a | ||
|
|
4b686a0147 | ||
|
|
f9f8eea6f6 | ||
|
|
3f6dc180cf | ||
|
|
7ce58b55a1 | ||
|
|
e8d1067313 | ||
|
|
c12b0a6dab | ||
|
|
effc3d1c4d | ||
|
|
63a9bd4fbf | ||
|
|
ca829a355c | ||
|
|
8464fc70fe | ||
|
|
dd68f89bf9 | ||
|
|
e42991c066 | ||
|
|
6eb699712d | ||
|
|
1d6662dfe3 | ||
|
|
258be9bf65 | ||
|
|
8592703931 | ||
|
|
44ecc9a203 | ||
|
|
b19e7809ea | ||
|
|
43a0bf4c31 | ||
|
|
546423512a | ||
|
|
b13acb33ed | ||
|
|
82c3193d21 | ||
|
|
503fc37a4b | ||
|
|
1788c9f3c0 |
10
.env
@@ -1,10 +1,12 @@
|
||||
# These API keys are intentionally public. Please do not report them - thank you for your concern.
|
||||
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
|
||||
REACT_APP_AMPLITUDE_PROXY_URL="https://api.uniswap.org/v1/amplitude-proxy"
|
||||
REACT_APP_AWS_API_REGION="us-east-2"
|
||||
REACT_APP_AWS_API_ACCESS_KEY="AKIAYJJWW6AQ47ODATHN"
|
||||
REACT_APP_AWS_API_ACCESS_SECRET="V9PoU0FhBP3cX760rPs9jMG/MIuDNLX6hYvVcaYO"
|
||||
REACT_APP_AWS_X_API_KEY="z9dReS5UtHu7iTrUsTuWRozLthi3AxOZlvobrIdr14"
|
||||
REACT_APP_AWS_API_ENDPOINT="https://beta.api.uniswap.org/v1/graphql"
|
||||
REACT_APP_TEMP_API_URL="https://temp.api.uniswap.org/v1"
|
||||
REACT_APP_SENTRY_DSN="https://a3c62e400b8748b5a8d007150e2f38b7@o1037921.ingest.sentry.io/4504255148851200"
|
||||
REACT_APP_SENTRY_ENABLED=false
|
||||
ESLINT_NO_DEV_ERRORS=true
|
||||
REACT_APP_INFURA_KEY="4bf032f2d38a4ed6bb975b80d6340847"
|
||||
REACT_APP_MOONPAY_API="https://api.moonpay.com"
|
||||
REACT_APP_MOONPAY_LINK="https://us-central1-uniswap-mobile.cloudfunctions.net/signMoonpayLinkStaging?platform=web"
|
||||
REACT_APP_MOONPAY_PUBLISHABLE_KEY="pk_test_DycfESRid31UaSxhI5yWKe1r5E5kKSz"
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
REACT_APP_AMPLITUDE_PROXY_URL="https://api.uniswap.org/v1/amplitude-proxy"
|
||||
REACT_APP_INFURA_KEY="099fc58e0de9451d80b18d7c74caa7c1"
|
||||
REACT_APP_AWS_API_ENDPOINT="https://api.uniswap.org/v1/graphql"
|
||||
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
|
||||
REACT_APP_GOOGLE_ANALYTICS_ID="G-KDP9B6W4H8"
|
||||
REACT_APP_INFURA_KEY="099fc58e0de9451d80b18d7c74caa7c1"
|
||||
REACT_APP_MOONPAY_API="https://api.moonpay.com"
|
||||
REACT_APP_MOONPAY_LINK="https://us-central1-uniswap-mobile.cloudfunctions.net/signMoonpayLink?platform=web"
|
||||
REACT_APP_MOONPAY_PUBLISHABLE_KEY="pk_live_uQG4BJC4w3cxnqpcSqAfohdBFDTsY6E"
|
||||
REACT_APP_FIREBASE_KEY="AIzaSyBcZWwTcTJHj_R6ipZcrJkXdq05PuX0Rs0"
|
||||
REACT_APP_AWS_API_ENDPOINT="https://api.uniswap.org/v1/graphql"
|
||||
THE_GRAPH_SCHEMA_ENDPOINT="https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3"
|
||||
REACT_APP_SENTRY_ENABLED=true
|
||||
|
||||
5
.eslintignore
Normal file
@@ -0,0 +1,5 @@
|
||||
*.config.ts
|
||||
*.d.ts
|
||||
/src/graphql/data/__generated__/types-and-hooks.ts
|
||||
/src/graphql/thegraph/__generated__/types-and-hooks.ts
|
||||
/src/schema/schema.graphql
|
||||
7
.eslintrc.js
Normal file
@@ -0,0 +1,7 @@
|
||||
/* eslint-env node */
|
||||
|
||||
require('@uniswap/eslint-config/load')
|
||||
|
||||
module.exports = {
|
||||
extends: '@uniswap/eslint-config/react',
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
// Allows for the parsing of JSX
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
}
|
||||
},
|
||||
"ignorePatterns": [
|
||||
"src/types/v3",
|
||||
"src/abis/types",
|
||||
"src/locales/**/*.js",
|
||||
"src/locales/**/en-US.po",
|
||||
"node_modules",
|
||||
"coverage",
|
||||
"build",
|
||||
"dist",
|
||||
".DS_Store",
|
||||
".env.local",
|
||||
".env.development.local",
|
||||
".env.test.local",
|
||||
".env.production.local",
|
||||
".idea/",
|
||||
".vscode/",
|
||||
"package-lock.json",
|
||||
"yarn.lock"
|
||||
],
|
||||
"extends": [
|
||||
"react-app",
|
||||
"plugin:react/recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"prettier/@typescript-eslint",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"plugins": ["simple-import-sort", "unused-imports"],
|
||||
"rules": {
|
||||
"unused-imports/no-unused-imports": "error",
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"prettier/prettier": "error",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/ban-ts-ignore": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"react/jsx-curly-brace-presence": ["error", {"props": "never", "children": "never" }],
|
||||
"object-shorthand": ["error", "always"],
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
{
|
||||
"name": "ethers",
|
||||
"message": "Please import from '@ethersproject/module' directly to support tree-shaking."
|
||||
},
|
||||
{
|
||||
"name": "styled-components",
|
||||
"message": "Please import from styled-components/macro."
|
||||
},
|
||||
{
|
||||
"name": "@lingui/macro",
|
||||
"importNames": ["t"],
|
||||
"message": "Please use <Trans> instead of t."
|
||||
}
|
||||
],
|
||||
"patterns": [
|
||||
{
|
||||
"group": ["**/dist"],
|
||||
"message": "Do not import from dist/ - this is an implementation detail, and breaks tree-shaking."
|
||||
},
|
||||
{
|
||||
"group": ["!styled-components/macro"]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
{
|
||||
"name": "@ethersproject/providers",
|
||||
"message": "Please only use Providers instantiated in constants/providers to improve traceability.",
|
||||
"allowTypeImports": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
3
.github/dependabot.yml
vendored
@@ -6,5 +6,6 @@ updates:
|
||||
schedule:
|
||||
interval: 'daily'
|
||||
allow:
|
||||
- dependency-name: '@uniswap/token-lists'
|
||||
- dependency-name: '@uniswap/default-token-list'
|
||||
- dependency-name: '@uniswap/token-lists'
|
||||
- dependency-name: '@uniswap/widgets'
|
||||
|
||||
49
.github/workflows/release.yaml
vendored
@@ -71,29 +71,6 @@ jobs:
|
||||
with:
|
||||
cidv0: ${{ steps.pinata.outputs.hash }}
|
||||
|
||||
- uses: actions/cache@v3
|
||||
id: cypress-cache
|
||||
with:
|
||||
path: /home/runner/.cache/Cypress
|
||||
key: ${{ runner.os }}-cypress-${{ hashFiles('node_modules/cypress') }}
|
||||
- if: steps.cypress-cache.outputs.cache-hit != 'true'
|
||||
run: yarn cypress install
|
||||
- uses: cypress-io/github-action@v4
|
||||
with:
|
||||
install: false
|
||||
browser: chrome
|
||||
config-file: cypress.release.config.ts
|
||||
config: baseUrl=https://cloudflare-ipfs.com/ipfs/${{ steps.pinata.outputs.hash }}
|
||||
|
||||
- name: Update DNS with new IPFS hash
|
||||
env:
|
||||
CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_TOKEN }}
|
||||
CLOUDFLARE_ZONE_ID: ${{ secrets.CLOUDFLARE_ZONE_ID }}
|
||||
CLOUDFLARE_GATEWAY_ID: ${{ secrets.CLOUDFLARE_GATEWAY_ID }}
|
||||
uses: Uniswap/cloudflare-update-web3-gateway@b3205288b1c6d0acb63fa3bd8fb686c72a9e3f3e
|
||||
with:
|
||||
cid: ${{ steps.pinata.outputs.hash }}
|
||||
|
||||
- name: Release
|
||||
uses: actions/create-release@v1.1.0
|
||||
env:
|
||||
@@ -119,3 +96,29 @@ jobs:
|
||||
- [ipfs://${{ steps.upload.outputs.hash }}/](ipfs://${{ steps.pinata.outputs.hash }}/)
|
||||
|
||||
${{ needs.tag.outputs.changelog }}
|
||||
|
||||
- name: Setup node@16 (required by Cloudflare Pages)
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Update Cloudflare Pages deployment
|
||||
uses: cloudflare/pages-action@364c7ca09a4b57837c5967871d64a2c31adb8c0d
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
projectName: ${{ secrets.CLOUDFLARE_PROJECT_NAME }}
|
||||
directory: build
|
||||
githubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload source maps to Sentry
|
||||
uses: getsentry/action-release@bd5f874fcda966ba48139b0140fb3ec0cb3aabdd
|
||||
continue-on-error: true
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||
with:
|
||||
environment: production
|
||||
sourcemaps: './build/static/js'
|
||||
url_prefix: '~/static/js'
|
||||
|
||||
27
.github/workflows/revert.yaml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Revert
|
||||
on:
|
||||
# manual trigger
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/setup
|
||||
- run: yarn prepare
|
||||
- run: yarn build
|
||||
|
||||
- name: Setup node@16 (required by Cloudflare Pages)
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Update Cloudflare Pages deployment
|
||||
uses: cloudflare/pages-action@364c7ca09a4b57837c5967871d64a2c31adb8c0d
|
||||
with:
|
||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
projectName: ${{ secrets.CLOUDFLARE_PROJECT_NAME }}
|
||||
directory: build
|
||||
githubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
2
.github/workflows/test.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/setup
|
||||
- run: npx yarn-deduplicate --strategy=highest --list --fail
|
||||
- run: yarn yarn-deduplicate --strategy=highest --list --fail
|
||||
|
||||
unit-tests:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
1
.gitignore
vendored
@@ -9,7 +9,6 @@
|
||||
/src/locales/**/pseudo.po
|
||||
|
||||
# generated graphql types
|
||||
__generated__/
|
||||
schema.graphql
|
||||
|
||||
# dependencies
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/src/schema/schema.graphql
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 120
|
||||
}
|
||||
25
.snyk
Normal file
@@ -0,0 +1,25 @@
|
||||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
||||
version: v1.25.0
|
||||
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
|
||||
ignore:
|
||||
SNYK-JS-OPENZEPPELINCONTRACTS-2964946:
|
||||
- '*':
|
||||
reason: None Given
|
||||
expires: 2099-01-01T00:00:00.000Z
|
||||
created: 2022-12-08T16:25:57.347Z
|
||||
SNYK-JS-OPENZEPPELINCONTRACTS-2958047:
|
||||
- '*':
|
||||
reason: None Given
|
||||
expires: 2099-01-01T00:00:00.000Z
|
||||
created: 2022-12-08T16:26:09.720Z
|
||||
SNYK-JS-OPENZEPPELINCONTRACTS-2958050:
|
||||
- '*':
|
||||
reason: None Given
|
||||
expires: 2099-01-01T00:00:00.000Z
|
||||
created: 2022-12-08T16:26:17.702Z
|
||||
SNYK-JS-OPENZEPPELINCONTRACTS-2965580:
|
||||
- '*':
|
||||
reason: None Given
|
||||
expires: 2099-01-01T00:00:00.000Z
|
||||
created: 2022-12-08T16:26:34.283Z
|
||||
patch: {}
|
||||
6
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint"
|
||||
],
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
9
.vscode/settings.json
vendored
@@ -5,15 +5,12 @@
|
||||
"editor.formatOnSaveMode": "file",
|
||||
"editor.tabCompletion": "on",
|
||||
"editor.tabSize": 2,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnSave": false,
|
||||
"editor.inlineSuggest.enabled": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": true
|
||||
},
|
||||
"files.eol": "\n",
|
||||
"eslint.enable": true,
|
||||
"eslint.debug": true,
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
}
|
||||
"eslint.debug": true
|
||||
}
|
||||
|
||||
25
apollo-codegen.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/* eslint-env node */
|
||||
|
||||
import type { CodegenConfig } from '@graphql-codegen/cli'
|
||||
|
||||
// Generates TS objects from the schemas returned by graphql queries
|
||||
// To learn more: https://www.apollographql.com/docs/react/development-testing/static-typing/#setting-up-your-project
|
||||
const config: CodegenConfig = {
|
||||
overwrite: true,
|
||||
schema: './src/graphql/data/schema.graphql',
|
||||
documents: ['./src/graphql/data/**', '!./src/graphql/data/__generated__/**', '!**/thegraph/**'],
|
||||
generates: {
|
||||
'src/graphql/data/__generated__/types-and-hooks.ts': {
|
||||
plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
|
||||
config: {
|
||||
withHooks: true,
|
||||
// This avoid all generated schemas being wrapped in Maybe https://the-guild.dev/graphql/codegen/plugins/typescript/typescript#maybevalue-string-default-value-t--null
|
||||
maybeValue: 'T',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// This is used in package.json when generating apollo schemas however the linter stills flags this as unused
|
||||
// eslint-disable-next-line import/no-unused-modules
|
||||
export default config
|
||||
25
apollo-codegen_thegraph.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/* eslint-env node */
|
||||
|
||||
import type { CodegenConfig } from '@graphql-codegen/cli'
|
||||
|
||||
// Generates TS objects from the schemas returned by graphql queries
|
||||
// To learn more: https://www.apollographql.com/docs/react/development-testing/static-typing/#setting-up-your-project
|
||||
const config: CodegenConfig = {
|
||||
overwrite: true,
|
||||
schema: './src/graphql/thegraph/schema.graphql',
|
||||
documents: ['!./src/graphql/data/**', '!./src/graphql/thegraph/__generated__/**', './src/graphql/thegraph/**'],
|
||||
generates: {
|
||||
'src/graphql/thegraph/__generated__/types-and-hooks.ts': {
|
||||
plugins: ['typescript', 'typescript-operations', 'typescript-react-apollo'],
|
||||
config: {
|
||||
withHooks: true,
|
||||
// This avoid all generated schemas being wrapped in Maybe https://the-guild.dev/graphql/codegen/plugins/typescript/typescript#maybevalue-string-default-value-t--null
|
||||
maybeValue: 'T',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// This is used in package.json when generating apollo schemas however the linter stills flags this as unused
|
||||
// eslint-disable-next-line import/no-unused-modules
|
||||
export default config
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-env node */
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -21,6 +21,16 @@ module.exports = {
|
||||
(plugin) => plugin instanceof MiniCssExtractPlugin
|
||||
)
|
||||
if (instanceOfMiniCssExtractPlugin !== undefined) instanceOfMiniCssExtractPlugin.options.ignoreOrder = true
|
||||
|
||||
// We're currently on Webpack 4.x that doesn't support the `exports` field in package.json.
|
||||
// See https://github.com/webpack/webpack/issues/9509.
|
||||
//
|
||||
// In case you need to add more modules, make sure to remap them to the correct path.
|
||||
//
|
||||
// Map @uniswap/conedison to its dist folder.
|
||||
// This is required because conedison uses * to redirect all imports to its dist.
|
||||
webpackConfig.resolve.alias['@uniswap/conedison'] = '@uniswap/conedison/dist'
|
||||
|
||||
return webpackConfig
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@ import { defineConfig } from 'cypress'
|
||||
export default defineConfig({
|
||||
projectId: 'yp82ef',
|
||||
videoUploadOnPasses: false,
|
||||
defaultCommandTimeout: 10000,
|
||||
defaultCommandTimeout: 24000, // 2x average block time
|
||||
chromeWebSecurity: false,
|
||||
e2e: {
|
||||
setupNodeEvents(on, config) {
|
||||
|
||||
@@ -1,12 +1,27 @@
|
||||
import { getTestSelector } from '../utils'
|
||||
|
||||
describe('Landing Page', () => {
|
||||
beforeEach(() => cy.visit('/'))
|
||||
it('loads swap page', () => {
|
||||
cy.get('#swap-page')
|
||||
it('shows landing page when no selectedWallet', () => {
|
||||
cy.visit('/', { noWallet: true })
|
||||
cy.get(getTestSelector('landing-page'))
|
||||
cy.screenshot()
|
||||
})
|
||||
|
||||
it('redirects to url /swap', () => {
|
||||
it('redirects to swap page when selectedWallet is INJECTED', () => {
|
||||
cy.visit('/', { selectedWallet: 'INJECTED' })
|
||||
cy.get('#swap-page')
|
||||
cy.url().should('include', '/swap')
|
||||
cy.screenshot()
|
||||
})
|
||||
|
||||
it('shows landing page when selectedWallet is INJECTED and ?intro=true is in query', () => {
|
||||
cy.visit('/?intro=true', { selectedWallet: 'INJECTED' })
|
||||
cy.get(getTestSelector('landing-page'))
|
||||
})
|
||||
|
||||
it('shows landing page when the unicorn icon in nav is selected', () => {
|
||||
cy.get(getTestSelector('uniswap-logo')).click()
|
||||
cy.get(getTestSelector('landing-page'))
|
||||
})
|
||||
|
||||
it('allows navigation to pool', () => {
|
||||
|
||||
63
cypress/e2e/nfts.test.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { getTestSelector } from '../utils'
|
||||
|
||||
const COLLECTION_ADDRESS = '0xbd3531da5cf5857e7cfaa92426877b022e612cf8'
|
||||
|
||||
describe('Testing nfts', () => {
|
||||
before(() => {
|
||||
cy.visit('/')
|
||||
})
|
||||
|
||||
it('should load nft leaderboard', () => {
|
||||
cy.get(getTestSelector('nft-nav')).first().click()
|
||||
cy.get(getTestSelector('nft-nav')).first().should('exist')
|
||||
cy.get(getTestSelector('nft-nav')).first().click()
|
||||
cy.get(getTestSelector('nft-trending-collection')).its('length').should('be.gte', 25)
|
||||
})
|
||||
|
||||
it('should load pudgy penguin collection page', () => {
|
||||
cy.visit(`/#/nfts/collection/${COLLECTION_ADDRESS}`)
|
||||
cy.get(getTestSelector('nft-collection-asset')).should('exist')
|
||||
cy.get(getTestSelector('nft-collection-filter-buy-now')).should('not.exist')
|
||||
cy.get(getTestSelector('nft-filter')).first().click()
|
||||
cy.get(getTestSelector('nft-collection-filter-buy-now')).should('exist')
|
||||
})
|
||||
|
||||
it('should be able to open bag and open sweep', () => {
|
||||
cy.get(getTestSelector('nft-sweep-button')).first().click()
|
||||
cy.get(getTestSelector('nft-empty-bag')).should('exist')
|
||||
cy.get(getTestSelector('nft-sweep-slider')).should('exist')
|
||||
})
|
||||
|
||||
it('should be able to navigate to activity', () => {
|
||||
cy.get(getTestSelector('nft-activity')).first().click()
|
||||
cy.get(getTestSelector('nft-activity-row')).should('exist')
|
||||
})
|
||||
|
||||
it('should go to the details page', () => {
|
||||
cy.visit(`/#/nfts/collection/${COLLECTION_ADDRESS}`)
|
||||
cy.get(getTestSelector('nft-filter')).first().click()
|
||||
cy.get(getTestSelector('nft-collection-filter-buy-now')).click()
|
||||
cy.get(getTestSelector('nft-details-link')).first().click()
|
||||
cy.get(getTestSelector('nft-details-traits')).should('exist')
|
||||
cy.get(getTestSelector('nft-details-activity')).should('exist')
|
||||
cy.get(getTestSelector('nft-details-description')).should('exist')
|
||||
cy.get(getTestSelector('nft-details-asset-details')).should('exist')
|
||||
})
|
||||
|
||||
it('should toggle buy now on details page', () => {
|
||||
cy.get(getTestSelector('nft-details-description-text')).should('exist')
|
||||
cy.get(getTestSelector('nft-details-description')).click()
|
||||
cy.get(getTestSelector('nft-details-description-text')).should('not.exist')
|
||||
cy.get(getTestSelector('nft-details-toggle-bag')).eq(1).click()
|
||||
cy.get(getTestSelector('nft-bag')).should('exist')
|
||||
})
|
||||
|
||||
it('should go view my nfts', () => {
|
||||
cy.get(getTestSelector('web3-status-connected')).click()
|
||||
cy.get(getTestSelector('nft-view-self-nfts')).click()
|
||||
cy.get(getTestSelector('nft-explore-nfts-button')).should('exist')
|
||||
cy.get(getTestSelector('nft-no-nfts-selected')).should('exist')
|
||||
cy.get(getTestSelector('nft-bag-close-icon')).click()
|
||||
cy.get(getTestSelector('nft-explore-nfts-button')).click()
|
||||
})
|
||||
})
|
||||
@@ -3,8 +3,8 @@ describe('Redirect', () => {
|
||||
cy.visit('/create-proposal')
|
||||
cy.url().should('match', /\/vote\/create-proposal/)
|
||||
})
|
||||
it('should redirect to /swap when visiting nonexist url', () => {
|
||||
it('should redirect to /not-found when visiting nonexist url', () => {
|
||||
cy.visit('/none-exist-url')
|
||||
cy.url().should('match', /\/swap/)
|
||||
cy.url().should('match', /\/not-found/)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -22,10 +22,4 @@ describe('Remove Liquidity', () => {
|
||||
cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'WETH')
|
||||
cy.get('#remove-liquidity-tokenb-symbol').should('contain.text', 'WETH')
|
||||
})
|
||||
|
||||
it.skip('token not in storage is loaded', () => {
|
||||
cy.visit('/remove/v2/0xb290b2f9f8f108d03ff2af3ac5c8de6de31cdf6d/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
|
||||
cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'SKL')
|
||||
cy.get('#remove-liquidity-tokenb-symbol').should('contain.text', 'MKR')
|
||||
})
|
||||
})
|
||||
|
||||
34
cypress/e2e/token.test.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { getTestSelector, getTestSelectorStartsWith } from '../utils'
|
||||
|
||||
describe('Testing tokens on uniswap page', () => {
|
||||
before(() => {
|
||||
cy.visit('/')
|
||||
})
|
||||
|
||||
it('should load token leaderboard', () => {
|
||||
cy.visit('/tokens/ethereum')
|
||||
cy.get(getTestSelectorStartsWith('token-table')).its('length').should('be.gte', 25)
|
||||
})
|
||||
|
||||
it('should load go to ethereum token and return to token list page', () => {
|
||||
cy.visit('/tokens/ethereum')
|
||||
cy.get(getTestSelector('token-table-row-Ether')).click()
|
||||
cy.get(getTestSelector('token-details-stats')).should('exist')
|
||||
cy.get(getTestSelector('token-details-return-button')).click()
|
||||
cy.get(getTestSelectorStartsWith('token-table')).its('length').should('be.gte', 25)
|
||||
})
|
||||
|
||||
it('should go to native token on ethereum and render description', () => {
|
||||
cy.visit('/tokens/ethereum/NATIVE')
|
||||
cy.get(getTestSelector('token-details-about-section')).should('exist')
|
||||
cy.contains('Ethereum is a smart contract platform that enables developers').should('exist')
|
||||
cy.contains('Etherscan').should('exist')
|
||||
})
|
||||
|
||||
it('should go to native token on polygon and render description and links', () => {
|
||||
cy.visit('/tokens/polygon/NATIVE')
|
||||
cy.get(getTestSelector('token-details-about-section')).should('exist')
|
||||
cy.contains('Wrapped Matic on Polygon').should('exist')
|
||||
cy.contains('Block Explorer').should('exist')
|
||||
})
|
||||
})
|
||||
@@ -1,9 +1,8 @@
|
||||
import { FeatureFlag } from '../../src/featureFlags/flags/featureFlags'
|
||||
import { getTestSelector } from '../utils'
|
||||
|
||||
describe('Wallet Dropdown', () => {
|
||||
before(() => {
|
||||
cy.visit('/', { featureFlags: [FeatureFlag.navBar, FeatureFlag.tokenSafety] })
|
||||
cy.visit('/pool')
|
||||
})
|
||||
|
||||
it('should change the theme', () => {
|
||||
@@ -31,6 +30,8 @@ describe('Wallet Dropdown', () => {
|
||||
cy.get(getTestSelector('wallet-disconnect')).click()
|
||||
cy.get(getTestSelector('wallet-select-theme')).click()
|
||||
cy.get(getTestSelector('wallet-select-theme')).contains('Dark theme').should('exist')
|
||||
cy.get(getTestSelector('wallet-select-theme')).click()
|
||||
cy.get(getTestSelector('wallet-select-theme')).contains('Light theme').should('exist')
|
||||
})
|
||||
|
||||
it('should select a language when not connected', () => {
|
||||
|
||||
@@ -8,7 +8,8 @@ describe(
|
||||
},
|
||||
() => {
|
||||
it('loads swap page', () => {
|
||||
// We *must* wait in order to space out the retry attempts.
|
||||
// TODO: We *must* wait in order to space out the retry attempts. Find a better way to do this.
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(ONE_MINUTE)
|
||||
.visit('/', {
|
||||
retryOnStatusCodeFailure: true,
|
||||
|
||||
@@ -20,6 +20,8 @@ declare global {
|
||||
interface VisitOptions {
|
||||
serviceWorker?: true
|
||||
featureFlags?: Array<FeatureFlag>
|
||||
selectedWallet?: string
|
||||
noWallet?: boolean
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +40,12 @@ Cypress.Commands.overwrite(
|
||||
onBeforeLoad(win) {
|
||||
options?.onBeforeLoad?.(win)
|
||||
win.localStorage.clear()
|
||||
win.localStorage.setItem('redux_localstorage_simple_user', '{"selectedWallet":"INJECTED"}')
|
||||
|
||||
const userState = {
|
||||
selectedWallet: options?.noWallet !== true ? options?.selectedWallet || 'INJECTED' : undefined,
|
||||
fiatOnrampDismissed: true,
|
||||
}
|
||||
win.localStorage.setItem('redux_localstorage_simple_user', JSON.stringify(userState))
|
||||
|
||||
if (options?.featureFlags) {
|
||||
const featureFlags = options.featureFlags.reduce(
|
||||
@@ -65,10 +72,20 @@ beforeEach(() => {
|
||||
res.headers['origin'] = 'http://localhost:3000'
|
||||
res.continue()
|
||||
})
|
||||
|
||||
// Graphql security policies are based on Origin headers.
|
||||
// These are stripped by cypress because chromeWebSecurity === false; this adds them back in.
|
||||
cy.intercept('https://api.uniswap.org/v1/graphql', (res) => {
|
||||
res.headers['origin'] = 'https://app.uniswap.org'
|
||||
res.continue()
|
||||
})
|
||||
cy.intercept('https://beta.api.uniswap.org/v1/graphql', (res) => {
|
||||
res.headers['origin'] = 'https://app.uniswap.org'
|
||||
res.continue()
|
||||
})
|
||||
})
|
||||
|
||||
Cypress.on('uncaught:exception', (_err, _runnable) => {
|
||||
// returning false here prevents Cypress from
|
||||
// failing the test
|
||||
Cypress.on('uncaught:exception', () => {
|
||||
// returning false here prevents Cypress from failing the test
|
||||
return false
|
||||
})
|
||||
|
||||
@@ -12,12 +12,7 @@ import { Wallet } from '@ethersproject/wallet'
|
||||
const TEST_PRIVATE_KEY = '0xe580410d7c37d26c6ad1a837bbae46bc27f9066a466fb3a66e770523b4666d19'
|
||||
|
||||
// address of the above key
|
||||
export const TEST_ADDRESS_NEVER_USE = new Wallet(TEST_PRIVATE_KEY).address
|
||||
|
||||
export const TEST_ADDRESS_NEVER_USE_SHORTENED = `${TEST_ADDRESS_NEVER_USE.substr(
|
||||
0,
|
||||
6
|
||||
)}...${TEST_ADDRESS_NEVER_USE.substr(-4, 4)}`
|
||||
const TEST_ADDRESS_NEVER_USE = new Wallet(TEST_PRIVATE_KEY).address
|
||||
|
||||
const provider = new JsonRpcProvider('https://goerli.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847', 4)
|
||||
const signer = new Wallet(TEST_PRIVATE_KEY, provider)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Utility to match GraphQL mutation based on the query name
|
||||
export const hasQuery = (req: any, queryName: string) => {
|
||||
const { body } = req
|
||||
return body.hasOwnProperty('query') && body.query.includes(queryName)
|
||||
return Object.prototype.hasOwnProperty.call(body, 'query') && body.query.includes(queryName)
|
||||
}
|
||||
|
||||
// Alias query if queryName matches
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export const getTestSelector = (selectorId: string) => `[data-testid=${selectorId}]`
|
||||
|
||||
export const getTestSelectorStartsWith = (selectorId: string) => `[data-testid^=${selectorId}]`
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
/* eslint-disable */
|
||||
/* eslint-env node */
|
||||
|
||||
require('dotenv').config({ path: '.env.production' })
|
||||
|
||||
const { exec } = require('child_process')
|
||||
const dataConfig = require('./relay.config')
|
||||
const thegraphConfig = require('./relay_thegraph.config')
|
||||
/* eslint-enable */
|
||||
const dataConfig = require('./graphql.config')
|
||||
const thegraphConfig = require('./graphql_thegraph.config')
|
||||
|
||||
const THEGRAPH_API_URL = 'https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v3'
|
||||
exec(`get-graphql-schema ${THEGRAPH_API_URL} > ${thegraphConfig.schema}`)
|
||||
function fetchSchema(url, outputFile) {
|
||||
exec(
|
||||
`get-graphql-schema --h Origin=https://app.uniswap.org ${url} | tee ${outputFile}.temp`,
|
||||
(error, stdout, stderr) => {
|
||||
if (error || stderr) {
|
||||
console.log(`Failed to fetch schema from ${url}`)
|
||||
} else if (stdout) {
|
||||
exec(`mv ${outputFile}.temp ${outputFile}`)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
console.log(process.env.REACT_APP_AWS_API_ENDPOINT)
|
||||
exec(
|
||||
`get-graphql-schema --h Origin=https://app.uniswap.org ${process.env.REACT_APP_AWS_API_ENDPOINT} > ${dataConfig.schema}`
|
||||
)
|
||||
fetchSchema(process.env.THE_GRAPH_SCHEMA_ENDPOINT, thegraphConfig.schema)
|
||||
fetchSchema(process.env.REACT_APP_AWS_API_ENDPOINT, dataConfig.schema)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* eslint-env node */
|
||||
|
||||
module.exports = {
|
||||
src: './src',
|
||||
language: 'typescript',
|
||||
@@ -1,5 +1,6 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const defaultConfig = require('./relay.config')
|
||||
/* eslint-env node */
|
||||
|
||||
const defaultConfig = require('./graphql.config')
|
||||
|
||||
module.exports = {
|
||||
src: defaultConfig.src,
|
||||
67
package.json
@@ -8,10 +8,10 @@
|
||||
"contracts:compile:abi": "typechain --target ethers-v5 --out-dir src/abis/types \"./src/abis/**/*.json\"",
|
||||
"contracts:compile:v3": "typechain --target ethers-v5 --out-dir src/types/v3 \"./node_modules/@uniswap/**/artifacts/contracts/**/*[!dbg].json\"",
|
||||
"contracts:compile": "yarn contracts:compile:abi && yarn contracts:compile:v3",
|
||||
"relay": "relay-compiler relay.config.js",
|
||||
"relay-thegraph": "relay-compiler relay_thegraph.config.js",
|
||||
"graphql:fetch": "node fetch-schema.js",
|
||||
"graphql:generate": "yarn relay && yarn relay-thegraph",
|
||||
"graphql:generate:data": "graphql-codegen --config apollo-codegen.ts",
|
||||
"graphql:generate:thegraph": "graphql-codegen --config apollo-codegen_thegraph.ts",
|
||||
"graphql:generate": "yarn graphql:generate:data && yarn graphql:generate:thegraph",
|
||||
"prei18n:extract": "node prei18n-extract.js",
|
||||
"i18n:extract": "lingui extract --locale en-US",
|
||||
"i18n:compile": "yarn i18n:extract && lingui compile",
|
||||
@@ -20,6 +20,7 @@
|
||||
"start": "craco start",
|
||||
"build": "craco build",
|
||||
"serve": "serve build -l 3000",
|
||||
"deduplicate": "yarn-deduplicate --strategy=highest",
|
||||
"lint": "yarn eslint .",
|
||||
"test": "craco test --coverage",
|
||||
"cypress:open": "cypress open --browser chrome --e2e",
|
||||
@@ -89,40 +90,39 @@
|
||||
"@types/ua-parser-js": "^0.7.35",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@types/wcag-contrast": "^3.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4",
|
||||
"@typescript-eslint/parser": "^4",
|
||||
"@uniswap/eslint-config": "^1.1.1",
|
||||
"@vanilla-extract/babel-plugin": "^1.1.7",
|
||||
"@vanilla-extract/webpack-plugin": "^2.1.11",
|
||||
"babel-plugin-relay": "^14.1.0",
|
||||
"cypress": "^10.3.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"eslint": "^7.11.0",
|
||||
"eslint-config-prettier": "^6.11.0",
|
||||
"eslint-plugin-better-styled-components": "^1.1.2",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-react": "^7.21.5",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"jest-styled-components": "^7.0.8",
|
||||
"ms.macro": "^2.0.0",
|
||||
"patch-package": "^6.4.7",
|
||||
"postinstall-postinstall": "^2.1.0",
|
||||
"prettier": "^2.7.1",
|
||||
"react-scripts": "^4.0.3",
|
||||
"relay-compiler": "^14.1.0",
|
||||
"serve": "^11.3.2",
|
||||
"ts-transform-graphql-tag": "^0.2.1",
|
||||
"typechain": "^5.0.0",
|
||||
"typescript": "^4.4.3"
|
||||
"typescript": "^4.4.3",
|
||||
"yarn-deduplicate": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.7.2",
|
||||
"@coinbase/wallet-sdk": "^3.3.0",
|
||||
"@fontsource/ibm-plex-mono": "^4.5.1",
|
||||
"@fontsource/inter": "^4.5.1",
|
||||
"@graphql-codegen/cli": "^2.15.0",
|
||||
"@graphql-codegen/client-preset": "^1.2.1",
|
||||
"@graphql-codegen/typescript": "^2.8.3",
|
||||
"@graphql-codegen/typescript-operations": "^2.5.8",
|
||||
"@graphql-codegen/typescript-react-apollo": "^3.3.7",
|
||||
"@graphql-codegen/typescript-resolvers": "^2.7.8",
|
||||
"@lingui/core": "^3.14.0",
|
||||
"@lingui/macro": "^3.14.0",
|
||||
"@lingui/react": "^3.14.0",
|
||||
"@looksrare/sdk": "^0.7.1",
|
||||
"@looksrare/sdk": "^0.10.2",
|
||||
"@metamask/jazzicon": "^2.0.0",
|
||||
"@opensea/seaport-js": "^1.0.2",
|
||||
"@popperjs/core": "^2.4.4",
|
||||
@@ -130,24 +130,28 @@
|
||||
"@reach/portal": "^0.10.3",
|
||||
"@react-hook/window-scroll": "^1.3.0",
|
||||
"@reduxjs/toolkit": "^1.6.1",
|
||||
"@types/react-relay": "^13.0.2",
|
||||
"@uniswap/analytics": "1.1.1",
|
||||
"@uniswap/analytics-events": "1.1.0",
|
||||
"@sentry/react": "7.20.1",
|
||||
"@types/react-window-infinite-loader": "^1.0.6",
|
||||
"@uniswap/analytics": "1.2.0",
|
||||
"@uniswap/analytics-events": "^1.5.0",
|
||||
"@uniswap/conedison": "^1.1.1",
|
||||
"@uniswap/governance": "^1.0.2",
|
||||
"@uniswap/liquidity-staker": "^1.0.2",
|
||||
"@uniswap/merkle-distributor": "1.0.1",
|
||||
"@uniswap/permit2-sdk": "1.2.0",
|
||||
"@uniswap/redux-multicall": "^1.1.8",
|
||||
"@uniswap/router-sdk": "^1.3.0",
|
||||
"@uniswap/sdk-core": "^3.0.1",
|
||||
"@uniswap/smart-order-router": "^2.10.0",
|
||||
"@uniswap/token-lists": "^1.0.0-beta.30",
|
||||
"@uniswap/universal-router-sdk": "1.3.0",
|
||||
"@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.9.0",
|
||||
"@uniswap/widgets": "^2.18.0",
|
||||
"@uniswap/widgets": "2.22.11",
|
||||
"@vanilla-extract/css": "^1.7.2",
|
||||
"@vanilla-extract/css-utils": "^0.1.2",
|
||||
"@vanilla-extract/dynamic": "^2.0.2",
|
||||
@@ -160,16 +164,16 @@
|
||||
"@visx/responsive": "^2.10.0",
|
||||
"@visx/shape": "^2.11.1",
|
||||
"@walletconnect/ethereum-provider": "^1.8.0",
|
||||
"@web3-react/coinbase-wallet": "^8.0.34-beta.0",
|
||||
"@web3-react/core": "^8.0.35-beta.0",
|
||||
"@web3-react/eip1193": "^8.0.26-beta.0",
|
||||
"@web3-react/empty": "^8.0.20-beta.0",
|
||||
"@web3-react/gnosis-safe": "^8.0.6-beta.0",
|
||||
"@web3-react/metamask": "^8.0.28-beta.0",
|
||||
"@web3-react/network": "^8.0.27-beta.0",
|
||||
"@web3-react/types": "^8.0.20-beta.0",
|
||||
"@web3-react/url": "^8.0.25-beta.0",
|
||||
"@web3-react/walletconnect": "^8.0.35-beta.0",
|
||||
"@web3-react/coinbase-wallet": "8.0.34-beta.0",
|
||||
"@web3-react/core": "8.0.35-beta.0",
|
||||
"@web3-react/eip1193": "8.0.26-beta.0",
|
||||
"@web3-react/empty": "8.0.20-beta.0",
|
||||
"@web3-react/gnosis-safe": "8.0.7-beta.0",
|
||||
"@web3-react/metamask": "8.0.28-beta.0",
|
||||
"@web3-react/network": "8.0.27-beta.0",
|
||||
"@web3-react/types": "8.0.20-beta.0",
|
||||
"@web3-react/url": "8.0.25-beta.0",
|
||||
"@web3-react/walletconnect": "8.0.36-beta.0",
|
||||
"array.prototype.flat": "^1.2.4",
|
||||
"array.prototype.flatmap": "^1.2.4",
|
||||
"cids": "^1.0.0",
|
||||
@@ -197,7 +201,6 @@
|
||||
"qs": "^6.9.4",
|
||||
"rc-slider": "^10.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-confetti": "^6.0.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-feather": "^2.0.8",
|
||||
"react-ga4": "^1.4.1",
|
||||
@@ -207,13 +210,13 @@
|
||||
"react-popper": "^2.2.3",
|
||||
"react-query": "^3.39.1",
|
||||
"react-redux": "^8.0.2",
|
||||
"react-relay": "^14.1.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-spring": "^9.5.5",
|
||||
"react-table": "^7.8.0",
|
||||
"react-use-gesture": "^6.0.14",
|
||||
"react-virtualized-auto-sizer": "^1.0.2",
|
||||
"react-window": "^1.8.5",
|
||||
"react-window-infinite-loader": "^1.0.8",
|
||||
"rebass": "^4.0.7",
|
||||
"redux": "^4.1.2",
|
||||
"redux-localstorage-simple": "^2.3.1",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
/* eslint-env node */
|
||||
|
||||
const { exec } = require('child_process')
|
||||
const isWindows = process.platform === 'win32' || /^(msys|cygwin)$/.test(process.env.OSTYPE)
|
||||
|
||||
|
||||
@@ -89,7 +89,9 @@
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
html {
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,5 +26,5 @@
|
||||
"iconPath": "./images/256x256_App_Icon_Pink.svg",
|
||||
"short_name": "Uniswap",
|
||||
"start_url": ".",
|
||||
"theme_color": "#FC72FFs"
|
||||
}
|
||||
"theme_color": "#FC72FF"
|
||||
}
|
||||
3
public/nft/svgs/marketplaces/looksrare-grey.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.64864 2L1 7.65256L10.5 17.1487L20 7.65256L14.3514 2H6.64864ZM6.13513 5.59458C8.5352 3.18398 12.4648 3.18396 14.8649 5.59456L16.9189 7.64866L14.8649 9.70272C12.4648 12.1133 8.5352 12.1133 6.13513 9.70274L4.08109 7.64866L6.13513 5.59458ZM7.54702 7.64848C7.54702 9.27987 8.86966 10.6012 10.4997 10.6012C12.1298 10.6012 13.4524 9.27987 13.4524 7.64848C13.4524 6.01708 12.1298 4.69576 10.4997 4.69576C8.86966 4.69576 7.54702 6.01708 7.54702 7.64848ZM10.4997 8.93225C9.791 8.93225 9.21593 8.35778 9.21593 7.64848C9.21593 6.93917 9.791 6.3647 10.4997 6.3647C11.2084 6.3647 11.7835 6.93917 11.7835 7.64848C11.7835 8.35778 11.2084 8.93225 10.4997 8.93225Z" fill="#5D6785"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 820 B |
3
public/nft/svgs/marketplaces/opensea-grey.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 1C5.0302 1 1 5.0302 1 10C1 14.9698 5.0302 19 10 19C14.9698 19 19 14.9698 19 10C19 5.0302 14.9716 1 10 1ZM5.4406 10.3024L5.4784 10.2412L7.8202 6.5782C7.8544 6.526 7.9354 6.5314 7.9606 6.589C8.3512 7.4656 8.6896 8.5564 8.5312 9.235C8.4646 9.514 8.2792 9.892 8.0704 10.2412C8.0434 10.2916 8.0146 10.342 7.9822 10.3906C7.9678 10.4122 7.9426 10.4248 7.9156 10.4248H5.509C5.4442 10.4248 5.4064 10.3546 5.4406 10.3024ZM15.8752 11.5624C15.8752 11.5966 15.8554 11.6254 15.8266 11.638C15.6448 11.7154 15.0238 12.0016 14.7664 12.3598C14.1076 13.276 13.6054 14.5864 12.4804 14.5864H7.7896C6.1264 14.5864 4.78 13.2346 4.78 11.566V11.512C4.78 11.4688 4.816 11.4328 4.861 11.4328H7.4746C7.5268 11.4328 7.5646 11.4796 7.561 11.5318C7.5412 11.701 7.5736 11.8756 7.6546 12.034C7.8094 12.349 8.1316 12.5452 8.479 12.5452H9.7732V11.5354H8.4934C8.4286 11.5354 8.389 11.4598 8.4268 11.4058C8.4412 11.3842 8.4556 11.3626 8.4736 11.3374C8.5942 11.1646 8.767 10.8982 8.9398 10.594C9.0568 10.3888 9.1702 10.1692 9.262 9.9496C9.28 9.91 9.2944 9.8686 9.3106 9.829C9.3358 9.7588 9.361 9.6922 9.379 9.6274C9.397 9.5716 9.4132 9.514 9.4276 9.46C9.4708 9.2728 9.4888 9.0748 9.4888 8.8696C9.4888 8.7886 9.4852 8.704 9.478 8.6248C9.4744 8.5366 9.4636 8.4484 9.4528 8.3602C9.4456 8.2828 9.4312 8.2054 9.4168 8.1262C9.397 8.0092 9.3718 7.8922 9.343 7.7752L9.3322 7.7302C9.3106 7.6492 9.2908 7.5736 9.2656 7.4926C9.1918 7.2406 9.109 6.994 9.019 6.7636C8.9866 6.6718 8.9506 6.5836 8.9128 6.4972C8.8588 6.364 8.803 6.2434 8.7526 6.13C8.7256 6.0778 8.704 6.031 8.6824 5.9824C8.6572 5.9284 8.632 5.8744 8.605 5.8222C8.587 5.7826 8.5654 5.7448 8.551 5.7088L8.3926 5.4172C8.371 5.3776 8.407 5.329 8.4502 5.3416L9.4402 5.6098H9.4438C9.4456 5.6098 9.4456 5.6098 9.4474 5.6098L9.577 5.6476L9.721 5.6872L9.7732 5.7016V5.1148C9.7732 4.8304 10 4.6 10.2826 4.6C10.423 4.6 10.5508 4.6576 10.6408 4.7512C10.7326 4.8448 10.7902 4.9726 10.7902 5.1148V5.9878L10.8964 6.0166C10.9036 6.0202 10.9126 6.0238 10.9198 6.0292C10.945 6.0472 10.9828 6.076 11.0296 6.112C11.0674 6.1408 11.107 6.1768 11.1538 6.2146C11.2492 6.292 11.3644 6.391 11.4886 6.5044C11.521 6.5332 11.5534 6.562 11.584 6.5926C11.7442 6.742 11.9242 6.9166 12.097 7.111C12.1456 7.1668 12.1924 7.2208 12.241 7.2802C12.2878 7.3396 12.34 7.3972 12.3832 7.4548C12.4426 7.5322 12.5038 7.6132 12.5596 7.6978C12.5848 7.7374 12.6154 7.7788 12.6388 7.8184C12.7108 7.9246 12.772 8.0344 12.8314 8.1442C12.8566 8.1946 12.8818 8.2504 12.9034 8.3044C12.97 8.452 13.0222 8.6014 13.0546 8.7526C13.0654 8.785 13.0726 8.8192 13.0762 8.8516V8.8588C13.087 8.902 13.0906 8.9488 13.0942 8.9974C13.1086 9.1504 13.1014 9.3052 13.069 9.46C13.0546 9.5248 13.0366 9.586 13.015 9.6526C12.9916 9.7156 12.97 9.7804 12.9412 9.8434C12.8854 9.9712 12.8206 10.1008 12.7432 10.2196C12.718 10.2646 12.6874 10.3114 12.6586 10.3564C12.6262 10.4032 12.592 10.4482 12.5632 10.4914C12.5218 10.5472 12.4786 10.6048 12.4336 10.657C12.394 10.711 12.3544 10.765 12.3094 10.8136C12.2482 10.8874 12.1888 10.9558 12.1258 11.0224C12.0898 11.0656 12.0502 11.1106 12.0088 11.1502C11.9692 11.1952 11.9278 11.2348 11.8918 11.2708C11.8288 11.3338 11.7784 11.3806 11.7352 11.422L11.6326 11.5138C11.6182 11.5282 11.5984 11.5354 11.5786 11.5354H10.7902V12.5452H11.782C12.0034 12.5452 12.214 12.4678 12.385 12.322C12.4426 12.2716 12.6964 12.052 12.997 11.7208C13.0078 11.7082 13.0204 11.701 13.0348 11.6974L15.7726 10.9054C15.8248 10.891 15.8752 10.9288 15.8752 10.9828V11.5624Z" fill="#5D6785"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
3
public/nft/svgs/marketplaces/uniswap-magenta.svg
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
5
public/nft/svgs/marketplaces/x2y2-grey.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17.146 4.52803C15.767 3.18049 13.8805 2.35 11.8 2.35C7.57502 2.35 4.15 5.77502 4.15 10C4.15 14.225 7.57502 17.65 11.8 17.65C13.8805 17.65 15.767 16.8195 17.146 15.472C15.501 17.617 12.912 19 10 19C5.02944 19 1 14.9706 1 10C1 5.02944 5.02944 1 10 1C12.912 1 15.501 2.38301 17.146 4.52803Z" fill="#5D6785"/>
|
||||
<path d="M6.08317 14.3776C7.18644 15.4556 8.69563 16.12 10.36 16.12C13.74 16.12 16.48 13.38 16.48 10C16.48 6.62002 13.74 3.88 10.36 3.88C8.69563 3.88 7.18644 4.54439 6.08317 5.62243C7.39916 3.90641 9.47037 2.8 11.8 2.8C15.7765 2.8 19 6.02355 19 10C19 13.9764 15.7764 17.2 11.8 17.2C9.47037 17.2 7.39916 16.0936 6.08317 14.3776Z" fill="#5D6785"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.4 10C15.4 12.9823 12.9823 15.4 10 15.4C7.01766 15.4 4.6 12.9823 4.6 10C4.6 7.01766 7.01766 4.6 10 4.6C12.9823 4.6 15.4 7.01766 15.4 10ZM13.6 10C13.6 11.9882 11.9882 13.6 10 13.6C8.01177 13.6 6.4 11.9882 6.4 10C6.4 8.01178 8.01177 6.4 10 6.4C11.9882 6.4 13.6 8.01178 13.6 10Z" fill="#5D6785"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
218
src/abis/uniswap-nft-airdrop-claim.json
Normal file
@@ -0,0 +1,218 @@
|
||||
[
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "token_",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "merkleRoot_",
|
||||
"type": "bytes32"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "endTime_",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "AlreadyClaimed",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "ClaimWindowFinished",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "EndTimeInPast",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "InvalidProof",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "NoWithdrawDuringClaim",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "index",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "Claimed",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "previousOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "index",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "account",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "bytes32[]",
|
||||
"name": "merkleProof",
|
||||
"type": "bytes32[]"
|
||||
}
|
||||
],
|
||||
"name": "claim",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "endTime",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "index",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "isClaimed",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bool",
|
||||
"name": "",
|
||||
"type": "bool"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "merkleRoot",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "bytes32",
|
||||
"name": "",
|
||||
"type": "bytes32"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "token",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
BIN
src/assets/images/404-page-dark.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
src/assets/images/404-page-light.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
src/assets/images/airdopBackground.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 19 KiB |
BIN
src/assets/images/welcomeModal-dark.jpg
Normal file
|
After Width: | Height: | Size: 134 KiB |
BIN
src/assets/images/welcomeModal-dark@2x.jpg
Normal file
|
After Width: | Height: | Size: 449 KiB |
BIN
src/assets/images/welcomeModal-dark@3x.jpg
Normal file
|
After Width: | Height: | Size: 927 KiB |
BIN
src/assets/images/welcomeModal-light.jpg
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
src/assets/images/welcomeModal-light@2x.jpg
Normal file
|
After Width: | Height: | Size: 364 KiB |
BIN
src/assets/images/welcomeModal-light@3x.jpg
Normal file
|
After Width: | Height: | Size: 718 KiB |
4
src/assets/svg/eye.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg width="54" height="40" viewBox="0 0 54 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.3335 19.9997C1.3335 19.9997 10.6668 1.33301 27.0002 1.33301C43.3335 1.33301 52.6668 19.9997 52.6668 19.9997C52.6668 19.9997 43.3335 38.6663 27.0002 38.6663C10.6668 38.6663 1.3335 19.9997 1.3335 19.9997Z" stroke="#98A1C0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M27.0002 26.9997C30.8662 26.9997 34.0002 23.8657 34.0002 19.9997C34.0002 16.1337 30.8662 12.9997 27.0002 12.9997C23.1342 12.9997 20.0002 16.1337 20.0002 19.9997C20.0002 23.8657 23.1342 26.9997 27.0002 26.9997Z" stroke="#98A1C0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 705 B |
21
src/assets/svg/fiat_mask.svg
Normal file
|
After Width: | Height: | Size: 3.5 MiB |
196
src/components/About/AboutFooter.tsx
Normal file
@@ -0,0 +1,196 @@
|
||||
import { TraceEvent } from '@uniswap/analytics'
|
||||
import { BrowserEvent, ElementName, EventName } from '@uniswap/analytics-events'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useIsDarkMode } from 'state/user/hooks'
|
||||
import styled from 'styled-components/macro'
|
||||
import { BREAKPOINTS, ExternalLink } from 'theme'
|
||||
|
||||
import { DiscordIcon, GithubIcon, TwitterIcon } from './Icons'
|
||||
import darkUnicornImgSrc from './images/unicornEmbossDark.png'
|
||||
import lightUnicornImgSrc from './images/unicornEmbossLight.png'
|
||||
|
||||
const Footer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
gap: 48px;
|
||||
max-width: 1440px;
|
||||
|
||||
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
`
|
||||
|
||||
const LogoSection = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`
|
||||
|
||||
const LogoSectionLeft = styled(LogoSection)`
|
||||
display: none;
|
||||
|
||||
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
|
||||
display: flex;
|
||||
}
|
||||
`
|
||||
|
||||
const LogoSectionBottom = styled(LogoSection)`
|
||||
display: flex;
|
||||
|
||||
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
|
||||
display: none;
|
||||
}
|
||||
`
|
||||
|
||||
const StyledLogo = styled.img`
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
display: none;
|
||||
|
||||
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
|
||||
display: block;
|
||||
}
|
||||
`
|
||||
|
||||
const SocialLinks = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
margin: 20px 0 0 0;
|
||||
`
|
||||
|
||||
const SocialLink = styled.a`
|
||||
display: flex;
|
||||
`
|
||||
|
||||
const FooterLinks = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
@media screen and (min-width: ${BREAKPOINTS.xl}px) {
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr;
|
||||
gap: 24px;
|
||||
}
|
||||
`
|
||||
|
||||
const LinkGroup = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
width: 200px;
|
||||
margin: 20px 0 0 0;
|
||||
@media screen and (min-width: ${BREAKPOINTS.xl}px) {
|
||||
margin: 0;
|
||||
}
|
||||
`
|
||||
|
||||
const LinkGroupTitle = styled.span`
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
font-weight: 700;
|
||||
`
|
||||
|
||||
const ExternalTextLink = styled(ExternalLink)`
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
color: ${({ theme }) => theme.textSecondary};
|
||||
`
|
||||
|
||||
const TextLink = styled(Link)`
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
color: ${({ theme }) => theme.textSecondary};
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
`
|
||||
|
||||
const Copyright = styled.span`
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
margin: 1rem 0 0 0;
|
||||
color: ${({ theme }) => theme.textTertiary};
|
||||
`
|
||||
|
||||
const LogoSectionContent = () => {
|
||||
const isDarkMode = useIsDarkMode()
|
||||
return (
|
||||
<>
|
||||
<StyledLogo src={isDarkMode ? darkUnicornImgSrc : lightUnicornImgSrc} alt="Uniswap Logo" />
|
||||
<SocialLinks>
|
||||
<SocialLink href="https://github.com/Uniswap" target="_blank" rel="noopener noreferrer">
|
||||
<DiscordIcon size={32} />
|
||||
</SocialLink>
|
||||
<TraceEvent events={[BrowserEvent.onClick]} name={EventName.ELEMENT_CLICKED} element={ElementName.TWITTER_LINK}>
|
||||
<SocialLink href="https://twitter.com/uniswap" target="_blank" rel="noopener noreferrer">
|
||||
<TwitterIcon size={32} />
|
||||
</SocialLink>
|
||||
</TraceEvent>
|
||||
<SocialLink href="https://discord.gg/FCfyBSbCU5" target="_blank" rel="noopener noreferrer">
|
||||
<GithubIcon size={32} />
|
||||
</SocialLink>
|
||||
</SocialLinks>
|
||||
<Copyright>© {new Date().getFullYear()} Uniswap Labs</Copyright>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const AboutFooter = () => {
|
||||
return (
|
||||
<Footer>
|
||||
<LogoSectionLeft>
|
||||
<LogoSectionContent />
|
||||
</LogoSectionLeft>
|
||||
|
||||
<FooterLinks>
|
||||
<LinkGroup>
|
||||
<LinkGroupTitle>App</LinkGroupTitle>
|
||||
<TextLink to="/swap">Swap</TextLink>
|
||||
<TextLink to="/tokens">Tokens</TextLink>
|
||||
<TextLink to="/nfts">NFTs</TextLink>
|
||||
<TextLink to="/pool">Pools</TextLink>
|
||||
</LinkGroup>
|
||||
<LinkGroup>
|
||||
<LinkGroupTitle>Protocol</LinkGroupTitle>
|
||||
<ExternalTextLink href="https://uniswap.org/community" target="_blank" rel="noopener noreferrer">
|
||||
Community
|
||||
</ExternalTextLink>
|
||||
<ExternalTextLink href="https://uniswap.org/governance" target="_blank" rel="noopener noreferrer">
|
||||
Governance
|
||||
</ExternalTextLink>
|
||||
<ExternalTextLink href="https://uniswap.org/developers" target="_blank" rel="noopener noreferrer">
|
||||
Developers
|
||||
</ExternalTextLink>
|
||||
</LinkGroup>
|
||||
<LinkGroup>
|
||||
<LinkGroupTitle>Company</LinkGroupTitle>
|
||||
<ExternalTextLink href="https://boards.greenhouse.io/uniswaplabs" target="_blank" rel="noopener noreferrer">
|
||||
Careers
|
||||
</ExternalTextLink>
|
||||
<ExternalTextLink href="https://uniswap.org/blog" target="_blank" rel="noopener noreferrer">
|
||||
Blog
|
||||
</ExternalTextLink>
|
||||
</LinkGroup>
|
||||
<LinkGroup>
|
||||
<LinkGroupTitle>Get Help</LinkGroupTitle>
|
||||
<ExternalTextLink
|
||||
href="https://support.uniswap.org/hc/en-us/requests/new"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Contact Us
|
||||
</ExternalTextLink>
|
||||
<ExternalTextLink href="https://support.uniswap.org/hc/en-us" target="_blank" rel="noopener noreferrer">
|
||||
Help Center
|
||||
</ExternalTextLink>
|
||||
</LinkGroup>
|
||||
</FooterLinks>
|
||||
|
||||
<LogoSectionBottom>
|
||||
<LogoSectionContent />
|
||||
</LogoSectionBottom>
|
||||
</Footer>
|
||||
)
|
||||
}
|
||||
150
src/components/About/Card.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
import { TraceEvent } from '@uniswap/analytics'
|
||||
import { BrowserEvent, EventName } from '@uniswap/analytics-events'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useIsDarkMode } from 'state/user/hooks'
|
||||
import styled, { DefaultTheme } from 'styled-components/macro'
|
||||
import { BREAKPOINTS } from 'theme'
|
||||
|
||||
export enum CardType {
|
||||
Primary = 'Primary',
|
||||
Secondary = 'Secondary',
|
||||
}
|
||||
|
||||
const StyledCard = styled.div<{ isDarkMode: boolean; backgroundImgSrc?: string; type: CardType }>`
|
||||
display: flex;
|
||||
background: ${({ isDarkMode, backgroundImgSrc, type, theme }) =>
|
||||
isDarkMode
|
||||
? `${type === CardType.Primary ? theme.backgroundModule : theme.backgroundSurface} ${
|
||||
backgroundImgSrc ? ` url(${backgroundImgSrc})` : ''
|
||||
}`
|
||||
: `${type === CardType.Primary ? 'white' : theme.backgroundModule} url(${backgroundImgSrc})`};
|
||||
background-size: auto 100%;
|
||||
background-position: right;
|
||||
background-repeat: no-repeat;
|
||||
background-origin: border-box;
|
||||
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
text-decoration: none;
|
||||
color: ${({ theme }) => theme.textPrimary};
|
||||
padding: 24px;
|
||||
height: 212px;
|
||||
border-radius: 24px;
|
||||
border: 1px solid ${({ theme, type }) => (type === CardType.Primary ? 'transparent' : theme.backgroundOutline)};
|
||||
box-shadow: 0px 10px 24px 0px rgba(51, 53, 72, 0.04);
|
||||
transition: ${({ theme }) => `${theme.transition.duration.medium} ${theme.transition.timing.ease} border`};
|
||||
|
||||
&:hover {
|
||||
border: 1px solid ${({ theme, isDarkMode }) => (isDarkMode ? theme.backgroundInteractive : theme.textTertiary)};
|
||||
}
|
||||
@media screen and (min-width: ${BREAKPOINTS.sm}px) {
|
||||
height: ${({ backgroundImgSrc }) => (backgroundImgSrc ? 360 : 260)}px;
|
||||
}
|
||||
@media screen and (min-width: ${BREAKPOINTS.xl}px) {
|
||||
padding: 32px;
|
||||
}
|
||||
`
|
||||
|
||||
const TitleRow = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
`
|
||||
|
||||
const CardTitle = styled.div`
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
font-weight: 600;
|
||||
|
||||
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
|
||||
font-size: 28px;
|
||||
line-height: 36px;
|
||||
}
|
||||
`
|
||||
|
||||
const getCardDescriptionColor = (type: CardType, theme: DefaultTheme) => {
|
||||
switch (type) {
|
||||
case CardType.Secondary:
|
||||
return theme.textSecondary
|
||||
default:
|
||||
return theme.textPrimary
|
||||
}
|
||||
}
|
||||
|
||||
const CardDescription = styled.div<{ type: CardType }>`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
color: ${({ theme, type }) => getCardDescriptionColor(type, theme)};
|
||||
padding: 0 40px 0 0;
|
||||
max-width: 480px;
|
||||
|
||||
@media screen and (min-width: ${BREAKPOINTS.xl}px) {
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
max-width: 480px;
|
||||
}
|
||||
`
|
||||
|
||||
const CardCTA = styled(CardDescription)`
|
||||
color: ${({ theme }) => theme.accentAction};
|
||||
font-weight: 500;
|
||||
margin: 24px 0 0;
|
||||
cursor: pointer;
|
||||
|
||||
transition: ${({ theme }) => `${theme.transition.duration.medium} ${theme.transition.timing.ease} opacity`};
|
||||
|
||||
&:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
`
|
||||
|
||||
const Card = ({
|
||||
type = CardType.Primary,
|
||||
title,
|
||||
description,
|
||||
cta,
|
||||
to,
|
||||
external,
|
||||
backgroundImgSrc,
|
||||
icon,
|
||||
elementName,
|
||||
}: {
|
||||
type?: CardType
|
||||
title: string
|
||||
description: string
|
||||
cta?: string
|
||||
to: string
|
||||
external?: boolean
|
||||
backgroundImgSrc?: string
|
||||
icon?: React.ReactNode
|
||||
elementName?: string
|
||||
}) => {
|
||||
const isDarkMode = useIsDarkMode()
|
||||
return (
|
||||
<TraceEvent events={[BrowserEvent.onClick]} name={EventName.ELEMENT_CLICKED} element={elementName}>
|
||||
<StyledCard
|
||||
type={type}
|
||||
as={external ? 'a' : Link}
|
||||
to={external ? undefined : to}
|
||||
href={external ? to : undefined}
|
||||
target={external ? '_blank' : undefined}
|
||||
rel={external ? 'noopenener noreferrer' : undefined}
|
||||
isDarkMode={isDarkMode}
|
||||
backgroundImgSrc={backgroundImgSrc}
|
||||
>
|
||||
<TitleRow>
|
||||
<CardTitle>{title}</CardTitle>
|
||||
{icon}
|
||||
</TitleRow>
|
||||
<CardDescription type={type}>
|
||||
{description}
|
||||
<CardCTA type={type}>{cta}</CardCTA>
|
||||
</CardDescription>
|
||||
</StyledCard>
|
||||
</TraceEvent>
|
||||
)
|
||||
}
|
||||
|
||||
export default Card
|
||||
26
src/components/About/Icons.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import { ReactComponent as DiscordI } from './images/discord.svg'
|
||||
import { ReactComponent as GithubI } from './images/github.svg'
|
||||
import { ReactComponent as TwitterI } from './images/twitter-safe.svg'
|
||||
|
||||
export const DiscordIcon = styled(DiscordI)<{ size?: number; fill?: string }>`
|
||||
height: ${({ size }) => (size ? size + 'px' : '32px')};
|
||||
width: ${({ size }) => (size ? size + 'px' : '32px')};
|
||||
fill: ${({ fill }) => fill ?? '#98A1C0'};
|
||||
opacity: 1;
|
||||
`
|
||||
|
||||
export const TwitterIcon = styled(TwitterI)<{ size?: number; fill?: string }>`
|
||||
height: ${({ size }) => (size ? size + 'px' : '32px')};
|
||||
width: ${({ size }) => (size ? size + 'px' : '32px')};
|
||||
fill: ${({ fill }) => fill ?? '#98A1C0'};
|
||||
opacity: 1;
|
||||
`
|
||||
|
||||
export const GithubIcon = styled(GithubI)<{ size?: number; fill?: string }>`
|
||||
height: ${({ size }) => (size ? size + 'px' : '32px')};
|
||||
width: ${({ size }) => (size ? size + 'px' : '32px')};
|
||||
fill: ${({ fill }) => fill ?? '#98A1C0'};
|
||||
opacity: 1;
|
||||
`
|
||||
106
src/components/About/ProtocolBanner.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import { ButtonEmpty } from 'components/Button'
|
||||
import { useIsDarkMode } from 'state/user/hooks'
|
||||
import styled from 'styled-components/macro'
|
||||
import { BREAKPOINTS } from 'theme'
|
||||
|
||||
import meshSrc from './images/Mesh.png'
|
||||
|
||||
const DARK_MODE_GRADIENT = 'radial-gradient(101.8% 4091.31% at 0% 0%, #4673FA 0%, #9646FA 100%)'
|
||||
|
||||
const Banner = styled.div<{ isDarkMode: boolean }>`
|
||||
height: 340px;
|
||||
width: 100%;
|
||||
border-radius: 32px;
|
||||
max-width: 1440px;
|
||||
margin: 80px 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32px 48px;
|
||||
|
||||
box-shadow: 0px 10px 24px rgba(51, 53, 72, 0.04);
|
||||
|
||||
background: ${({ isDarkMode }) =>
|
||||
isDarkMode
|
||||
? `url(${meshSrc}), ${DARK_MODE_GRADIENT}`
|
||||
: `url(${meshSrc}), linear-gradient(93.06deg, #FF00C7 2.66%, #FF9FFB 98.99%);`};
|
||||
|
||||
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
|
||||
height: 140px;
|
||||
flex-direction: row;
|
||||
}
|
||||
`
|
||||
|
||||
const TextContainer = styled.div`
|
||||
color: white;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
`
|
||||
|
||||
const HeaderText = styled.div`
|
||||
font-weight: 700;
|
||||
font-size: 28px;
|
||||
line-height: 36px;
|
||||
|
||||
@media screen and (min-width: ${BREAKPOINTS.xl}px) {
|
||||
font-size: 28px;
|
||||
line-height: 36px;
|
||||
}
|
||||
`
|
||||
|
||||
const DescriptionText = styled.div`
|
||||
margin: 10px 10px 0 0;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
|
||||
@media screen and (min-width: ${BREAKPOINTS.xl}px) {
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
}
|
||||
`
|
||||
|
||||
const BannerButtonContainer = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
transition: ${({ theme }) => `${theme.transition.duration.medium} ${theme.transition.timing.ease} opacity`};
|
||||
|
||||
&:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
@media screen and (min-width: ${BREAKPOINTS.lg}px) {
|
||||
width: auto;
|
||||
}
|
||||
`
|
||||
|
||||
const BannerButton = styled(ButtonEmpty)`
|
||||
color: white;
|
||||
border: 1px solid white;
|
||||
`
|
||||
|
||||
const ProtocolBanner = () => {
|
||||
const isDarkMode = useIsDarkMode()
|
||||
return (
|
||||
<Banner isDarkMode={isDarkMode}>
|
||||
<TextContainer>
|
||||
<HeaderText>Powered by the Uniswap Protocol</HeaderText>
|
||||
<DescriptionText>
|
||||
The leading decentralized crypto trading protocol, governed by a global community.
|
||||
</DescriptionText>
|
||||
</TextContainer>
|
||||
<BannerButtonContainer>
|
||||
<BannerButton width="200px" as="a" href="https://uniswap.org" rel="noopener noreferrer" target="_blank">
|
||||
Learn more
|
||||
</BannerButton>
|
||||
</BannerButtonContainer>
|
||||
</Banner>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProtocolBanner
|
||||
71
src/components/About/constants.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import { ElementName } from '@uniswap/analytics-events'
|
||||
import { DollarSign, Terminal } from 'react-feather'
|
||||
import styled from 'styled-components/macro'
|
||||
import { lightTheme } from 'theme/colors'
|
||||
|
||||
import darkArrowImgSrc from './images/aboutArrowDark.png'
|
||||
import lightArrowImgSrc from './images/aboutArrowLight.png'
|
||||
import darkDollarImgSrc from './images/aboutDollarDark.png'
|
||||
import darkTerminalImgSrc from './images/aboutTerminalDark.png'
|
||||
import nftCardImgSrc from './images/nftCard.png'
|
||||
import swapCardImgSrc from './images/swapCard.png'
|
||||
|
||||
export const MAIN_CARDS = [
|
||||
{
|
||||
to: '/swap',
|
||||
title: 'Swap tokens',
|
||||
description: 'Buy, sell, and explore tokens on Ethereum, Polygon, Optimism, and more.',
|
||||
cta: 'Trade Tokens',
|
||||
darkBackgroundImgSrc: swapCardImgSrc,
|
||||
lightBackgroundImgSrc: swapCardImgSrc,
|
||||
elementName: ElementName.ABOUT_PAGE_SWAP_CARD,
|
||||
},
|
||||
{
|
||||
to: '/nfts',
|
||||
title: 'Trade NFTs',
|
||||
description: 'Buy and sell NFTs across marketplaces to find more listings at better prices.',
|
||||
cta: 'Explore NFTs',
|
||||
darkBackgroundImgSrc: nftCardImgSrc,
|
||||
lightBackgroundImgSrc: nftCardImgSrc,
|
||||
elementName: ElementName.ABOUT_PAGE_NFTS_CARD,
|
||||
},
|
||||
]
|
||||
|
||||
const StyledCardLogo = styled.img`
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
max-height: 48px;
|
||||
max-width: 48px;
|
||||
`
|
||||
|
||||
export const MORE_CARDS = [
|
||||
{
|
||||
to: 'https://support.uniswap.org/hc/en-us/articles/11306574799117-How-to-use-Moon-Pay-on-the-Uniswap-web-app-',
|
||||
external: true,
|
||||
title: 'Buy crypto',
|
||||
description: 'Buy crypto with your credit card or bank account at the best rates.',
|
||||
lightIcon: <DollarSign color={lightTheme.textTertiary} size={48} />,
|
||||
darkIcon: <StyledCardLogo src={darkDollarImgSrc} alt="Earn" />,
|
||||
cta: 'Buy now',
|
||||
elementName: ElementName.ABOUT_PAGE_BUY_CRYPTO_CARD,
|
||||
},
|
||||
{
|
||||
to: '/pool',
|
||||
title: 'Earn',
|
||||
description: 'Provide liquidity to pools on Uniswap and earn fees on swaps.',
|
||||
lightIcon: <StyledCardLogo src={lightArrowImgSrc} alt="Analytics" />,
|
||||
darkIcon: <StyledCardLogo src={darkArrowImgSrc} alt="Analytics" />,
|
||||
cta: 'Provide liquidity',
|
||||
elementName: ElementName.ABOUT_PAGE_EARN_CARD,
|
||||
},
|
||||
{
|
||||
to: 'https://docs.uniswap.org',
|
||||
external: true,
|
||||
title: 'Build dApps',
|
||||
description: 'Build apps and tools on the largest DeFi protocol on Ethereum.',
|
||||
lightIcon: <Terminal color={lightTheme.textTertiary} size={48} />,
|
||||
darkIcon: <StyledCardLogo src={darkTerminalImgSrc} alt="Developers" />,
|
||||
cta: 'Developer docs',
|
||||
elementName: ElementName.ABOUT_PAGE_DEV_DOCS_CARD,
|
||||
},
|
||||
]
|
||||
BIN
src/components/About/images/About_BG_Dark.jpg
Normal file
|
After Width: | Height: | Size: 327 KiB |
BIN
src/components/About/images/About_BG_Light.jpg
Normal file
|
After Width: | Height: | Size: 379 KiB |
BIN
src/components/About/images/Mesh.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
src/components/About/images/aboutArrowDark.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
src/components/About/images/aboutArrowLight.png
Normal file
|
After Width: | Height: | Size: 532 B |
BIN
src/components/About/images/aboutDollarDark.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src/components/About/images/aboutTerminalDark.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
3
src/components/About/images/discord.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 71 55" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
1
src/components/About/images/github.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>
|
||||
|
After Width: | Height: | Size: 822 B |
BIN
src/components/About/images/nftCard.png
Normal file
|
After Width: | Height: | Size: 178 KiB |
BIN
src/components/About/images/swapCard.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
3
src/components/About/images/twitter-safe.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg viewBox="0 0 32 32" role="img" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M31.2746 5.92398C30.7719 6.14694 30.2551 6.33512 29.727 6.4879C30.3522 5.7808 30.8289 4.9488 31.1199 4.03835C31.1851 3.83427 31.1175 3.61089 30.9498 3.47742C30.7822 3.34385 30.5495 3.32785 30.365 3.43716C29.2434 4.10235 28.0334 4.58039 26.7647 4.85993C25.4866 3.6111 23.7508 2.90039 21.9563 2.90039C18.1684 2.90039 15.0867 5.98199 15.0867 9.76975C15.0867 10.0681 15.1056 10.3647 15.143 10.6573C10.4426 10.2446 6.07276 7.9343 3.07198 4.25337C2.96504 4.12217 2.80029 4.05146 2.63162 4.06498C2.46285 4.0782 2.31121 4.17337 2.22595 4.31964C1.61733 5.36398 1.29557 6.5584 1.29557 7.77368C1.29557 9.4289 1.88654 10.9994 2.93046 12.2265C2.61304 12.1166 2.30502 11.9792 2.01103 11.816C1.8532 11.7282 1.66058 11.7295 1.50378 11.8194C1.34687 11.9093 1.2485 12.0747 1.24437 12.2554C1.24365 12.2859 1.24365 12.3163 1.24365 12.3472C1.24365 14.8179 2.5734 17.0423 4.60644 18.2547C4.43178 18.2373 4.25722 18.212 4.0838 18.1788C3.90502 18.1447 3.72117 18.2073 3.6006 18.3437C3.47983 18.4799 3.43988 18.6699 3.49552 18.8433C4.24804 21.1927 6.18548 22.9208 8.52767 23.4477C6.58507 24.6644 4.36355 25.3017 2.03147 25.3017C1.54486 25.3017 1.05547 25.2731 0.5765 25.2165C0.338565 25.1882 0.111055 25.3287 0.0300229 25.5549C-0.0510093 25.7813 0.0348745 26.0337 0.2373 26.1634C3.23322 28.0844 6.69738 29.0997 10.2551 29.0997C17.249 29.0997 21.6242 25.8016 24.063 23.0349C27.104 19.585 28.8481 15.0186 28.8481 10.5067C28.8481 10.3182 28.8452 10.1278 28.8394 9.93812C30.0392 9.03417 31.0722 7.94018 31.9128 6.68279C32.0404 6.49182 32.0266 6.23943 31.8787 6.06364C31.731 5.88774 31.4848 5.83087 31.2746 5.92398Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/components/About/images/unicornEmbossDark.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
src/components/About/images/unicornEmbossLight.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
@@ -27,12 +27,12 @@ const TransactionState = styled(ExternalLink)<{ pending: boolean; success?: bool
|
||||
padding: 0.25rem 0rem;
|
||||
font-weight: 500;
|
||||
font-size: 0.825rem;
|
||||
color: ${({ theme }) => theme.deprecated_primary1};
|
||||
color: ${({ theme }) => theme.accentAction};
|
||||
`
|
||||
|
||||
const IconWrapper = styled.div<{ pending: boolean; success?: boolean }>`
|
||||
color: ${({ pending, success, theme }) =>
|
||||
pending ? theme.deprecated_primary1 : success ? theme.deprecated_green1 : theme.deprecated_red1};
|
||||
pending ? theme.accentAction : success ? theme.accentSuccess : theme.accentFailure};
|
||||
`
|
||||
|
||||
export default function Transaction({ hash }: { hash: string }) {
|
||||
|
||||
@@ -14,18 +14,15 @@ import {
|
||||
CollectFeesTransactionInfo,
|
||||
CreateV3PoolTransactionInfo,
|
||||
DelegateTransactionInfo,
|
||||
DepositLiquidityStakingTransactionInfo,
|
||||
ExactInputSwapTransactionInfo,
|
||||
ExactOutputSwapTransactionInfo,
|
||||
ExecuteTransactionInfo,
|
||||
MigrateV2LiquidityToV3TransactionInfo,
|
||||
QueueTransactionInfo,
|
||||
RemoveLiquidityV3TransactionInfo,
|
||||
SubmitProposalTransactionInfo,
|
||||
TransactionInfo,
|
||||
TransactionType,
|
||||
VoteTransactionInfo,
|
||||
WithdrawLiquidityStakingTransactionInfo,
|
||||
WrapTransactionInfo,
|
||||
} from '../../state/transactions/types'
|
||||
|
||||
@@ -83,7 +80,7 @@ function ClaimSummary({ info: { recipient, uniAmountRaw } }: { info: ClaimTransa
|
||||
)
|
||||
}
|
||||
|
||||
function SubmitProposalTransactionSummary(_: { info: SubmitProposalTransactionInfo }) {
|
||||
function SubmitProposalTransactionSummary() {
|
||||
return <Trans>Submit new proposal</Trans>
|
||||
}
|
||||
|
||||
@@ -175,13 +172,13 @@ function WrapSummary({ info: { chainId, currencyAmountRaw, unwrapped } }: { info
|
||||
}
|
||||
}
|
||||
|
||||
function DepositLiquidityStakingSummary(_: { info: DepositLiquidityStakingTransactionInfo }) {
|
||||
function DepositLiquidityStakingSummary() {
|
||||
// not worth rendering the tokens since you can should no longer deposit liquidity in the staking contracts
|
||||
// todo: deprecate and delete the code paths that allow this, show user more information
|
||||
return <Trans>Deposit liquidity</Trans>
|
||||
}
|
||||
|
||||
function WithdrawLiquidityStakingSummary(_: { info: WithdrawLiquidityStakingTransactionInfo }) {
|
||||
function WithdrawLiquidityStakingSummary() {
|
||||
return <Trans>Withdraw deposited liquidity</Trans>
|
||||
}
|
||||
|
||||
@@ -319,10 +316,10 @@ export function TransactionSummary({ info }: { info: TransactionInfo }) {
|
||||
return <ClaimSummary info={info} />
|
||||
|
||||
case TransactionType.DEPOSIT_LIQUIDITY_STAKING:
|
||||
return <DepositLiquidityStakingSummary info={info} />
|
||||
return <DepositLiquidityStakingSummary />
|
||||
|
||||
case TransactionType.WITHDRAW_LIQUIDITY_STAKING:
|
||||
return <WithdrawLiquidityStakingSummary info={info} />
|
||||
return <WithdrawLiquidityStakingSummary />
|
||||
|
||||
case TransactionType.SWAP:
|
||||
return <SwapSummary info={info} />
|
||||
@@ -358,6 +355,6 @@ export function TransactionSummary({ info }: { info: TransactionInfo }) {
|
||||
return <ExecuteSummary info={info} />
|
||||
|
||||
case TransactionType.SUBMIT_PROPOSAL:
|
||||
return <SubmitProposalTransactionSummary info={info} />
|
||||
return <SubmitProposalTransactionSummary />
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { useAppDispatch } from 'state/hooks'
|
||||
import { updateSelectedWallet } from 'state/user/reducer'
|
||||
import { removeConnectedWallet } from 'state/wallets/reducer'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
import { flexColumnNoWrap, flexRowNoWrap } from 'theme/styles'
|
||||
import { isMobile } from 'utils/userAgent'
|
||||
|
||||
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
||||
@@ -20,10 +21,10 @@ import { AutoRow } from '../Row'
|
||||
import Transaction from './Transaction'
|
||||
|
||||
const HeaderRow = styled.div`
|
||||
${({ theme }) => theme.flexRowNoWrap};
|
||||
${flexRowNoWrap};
|
||||
padding: 1rem 1rem;
|
||||
font-weight: 500;
|
||||
color: ${(props) => (props.color === 'blue' ? ({ theme }) => theme.deprecated_primary1 : 'inherit')};
|
||||
color: ${(props) => (props.color === 'blue' ? ({ theme }) => theme.accentAction : 'inherit')};
|
||||
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
|
||||
padding: 1rem;
|
||||
`};
|
||||
@@ -60,14 +61,14 @@ const InfoCard = styled.div`
|
||||
`
|
||||
|
||||
const AccountGroupingRow = styled.div`
|
||||
${({ theme }) => theme.flexRowNoWrap};
|
||||
${flexColumnNoWrap};
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
font-weight: 400;
|
||||
color: ${({ theme }) => theme.deprecated_text1};
|
||||
color: ${({ theme }) => theme.textPrimary};
|
||||
|
||||
div {
|
||||
${({ theme }) => theme.flexRowNoWrap}
|
||||
${flexColumnNoWrap};
|
||||
align-items: center;
|
||||
}
|
||||
`
|
||||
@@ -90,18 +91,18 @@ const YourAccount = styled.div`
|
||||
`
|
||||
|
||||
const LowerSection = styled.div`
|
||||
${({ theme }) => theme.flexColumnNoWrap}
|
||||
${flexColumnNoWrap};
|
||||
padding: 1.5rem;
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
background-color: ${({ theme }) => theme.deprecated_bg2};
|
||||
background-color: ${({ theme }) => theme.backgroundInteractive};
|
||||
border-bottom-left-radius: 20px;
|
||||
border-bottom-right-radius: 20px;
|
||||
|
||||
h5 {
|
||||
margin: 0;
|
||||
font-weight: 400;
|
||||
color: ${({ theme }) => theme.deprecated_text3};
|
||||
color: ${({ theme }) => theme.textTertiary};
|
||||
}
|
||||
`
|
||||
|
||||
@@ -128,14 +129,14 @@ const AccountControl = styled.div`
|
||||
`
|
||||
|
||||
const AddressLink = styled(ExternalLink)`
|
||||
color: ${({ theme }) => theme.deprecated_text3};
|
||||
color: ${({ theme }) => theme.textTertiary};
|
||||
margin-left: 1rem;
|
||||
font-size: 0.825rem;
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
text-decoration: none !important;
|
||||
:hover {
|
||||
color: ${({ theme }) => theme.deprecated_text2};
|
||||
color: ${({ theme }) => theme.textSecondary};
|
||||
}
|
||||
`
|
||||
|
||||
@@ -159,11 +160,11 @@ const WalletName = styled.div`
|
||||
width: initial;
|
||||
font-size: 0.825rem;
|
||||
font-weight: 500;
|
||||
color: ${({ theme }) => theme.deprecated_text3};
|
||||
color: ${({ theme }) => theme.textTertiary};
|
||||
`
|
||||
|
||||
const TransactionListWrapper = styled.div`
|
||||
${({ theme }) => theme.flexColumnNoWrap};
|
||||
${flexColumnNoWrap};
|
||||
`
|
||||
|
||||
const WalletAction = styled(ButtonSecondary)`
|
||||
@@ -315,7 +316,7 @@ export default function AccountDetails({
|
||||
</LowerSection>
|
||||
) : (
|
||||
<LowerSection>
|
||||
<ThemedText.DeprecatedBody color={theme.deprecated_text1}>
|
||||
<ThemedText.DeprecatedBody color={theme.textPrimary}>
|
||||
<Trans>Your transactions will appear here...</Trans>
|
||||
</ThemedText.DeprecatedBody>
|
||||
</LowerSection>
|
||||
|
||||
@@ -5,7 +5,7 @@ import styled, { css } from 'styled-components/macro'
|
||||
|
||||
import { nativeOnChain } from '../../constants/tokens'
|
||||
import { useCurrency } from '../../hooks/Tokens'
|
||||
import CurrencyLogo from '../CurrencyLogo'
|
||||
import CurrencyLogo from '../Logo/CurrencyLogo'
|
||||
|
||||
const CurrencyWrap = styled.div`
|
||||
position: relative;
|
||||
@@ -39,26 +39,32 @@ const getCurrency = ({ info, chainId }: { info: TransactionInfo; chainId: number
|
||||
switch (info.type) {
|
||||
case TransactionType.ADD_LIQUIDITY_V3_POOL:
|
||||
case TransactionType.REMOVE_LIQUIDITY_V3:
|
||||
case TransactionType.CREATE_V3_POOL:
|
||||
case TransactionType.CREATE_V3_POOL: {
|
||||
const { baseCurrencyId, quoteCurrencyId } = info
|
||||
return { currencyId0: baseCurrencyId, currencyId1: quoteCurrencyId }
|
||||
case TransactionType.SWAP:
|
||||
}
|
||||
case TransactionType.SWAP: {
|
||||
const { inputCurrencyId, outputCurrencyId } = info
|
||||
return { currencyId0: inputCurrencyId, currencyId1: outputCurrencyId }
|
||||
case TransactionType.WRAP:
|
||||
}
|
||||
case TransactionType.WRAP: {
|
||||
const { unwrapped } = info
|
||||
const native = info.chainId ? nativeOnChain(info.chainId) : undefined
|
||||
const base = 'ETH'
|
||||
const wrappedCurrency = native?.wrapped.address ?? 'WETH'
|
||||
return { currencyId0: unwrapped ? wrappedCurrency : base, currencyId1: unwrapped ? base : wrappedCurrency }
|
||||
case TransactionType.COLLECT_FEES:
|
||||
}
|
||||
case TransactionType.COLLECT_FEES: {
|
||||
const { currencyId0, currencyId1 } = info
|
||||
return { currencyId0, currencyId1 }
|
||||
case TransactionType.APPROVAL:
|
||||
}
|
||||
case TransactionType.APPROVAL: {
|
||||
return { currencyId0: info.tokenAddress, currencyId1: undefined }
|
||||
case TransactionType.CLAIM:
|
||||
}
|
||||
case TransactionType.CLAIM: {
|
||||
const uniAddress = chainId ? UNI_ADDRESS[chainId] : undefined
|
||||
return { currencyId0: uniAddress, currencyId1: undefined }
|
||||
}
|
||||
default:
|
||||
return { currencyId0: undefined, currencyId1: undefined }
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { SupportedChainId } from 'constants/chains'
|
||||
import { useMemo } from 'react'
|
||||
import { AlertTriangle, CheckCircle } from 'react-feather'
|
||||
import styled from 'styled-components/macro'
|
||||
import { ExternalLink } from 'theme'
|
||||
import { colors } from 'theme/colors'
|
||||
|
||||
import { TransactionDetails } from '../../state/transactions/types'
|
||||
@@ -17,13 +18,14 @@ export enum TransactionState {
|
||||
Failed,
|
||||
}
|
||||
|
||||
const Grid = styled.a`
|
||||
const Grid = styled(ExternalLink)<{ isLastTransactionInList?: boolean }>`
|
||||
cursor: pointer;
|
||||
display: grid;
|
||||
grid-template-columns: 44px auto 24px;
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
border-bottom: ${({ theme }) => `1px solid ${theme.backgroundOutline}`};
|
||||
border-bottom: ${({ theme, isLastTransactionInList }) =>
|
||||
isLastTransactionInList ? 'none' : `1px solid ${theme.backgroundOutline}`};
|
||||
padding: 12px;
|
||||
|
||||
&:hover {
|
||||
@@ -46,7 +48,13 @@ const IconStyleWrap = styled.span`
|
||||
height: 16px;
|
||||
`
|
||||
|
||||
export const TransactionSummary = ({ transactionDetails }: { transactionDetails: TransactionDetails }) => {
|
||||
export const TransactionSummary = ({
|
||||
transactionDetails,
|
||||
isLastTransactionInList = false,
|
||||
}: {
|
||||
transactionDetails: TransactionDetails
|
||||
isLastTransactionInList?: boolean
|
||||
}) => {
|
||||
const { chainId = 1 } = useWeb3React()
|
||||
const tx = transactionDetails
|
||||
const { explorer } = getChainInfoOrDefault(chainId ? chainId : SupportedChainId.MAINNET)
|
||||
@@ -67,7 +75,7 @@ export const TransactionSummary = ({ transactionDetails }: { transactionDetails:
|
||||
const link = `${explorer}tx/${hash}`
|
||||
|
||||
return chainId ? (
|
||||
<Grid href={link} target="_blank">
|
||||
<Grid href={link} target="_blank" isLastTransactionInList={isLastTransactionInList}>
|
||||
<LogoView info={info} />
|
||||
<TextContainer as="span">
|
||||
<TransactionBody info={info} transactionState={transactionState} />
|
||||
|
||||
@@ -4,6 +4,7 @@ import { t } from '@lingui/macro'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { ChangeEvent, ReactNode, useCallback } from 'react'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
import { flexColumnNoWrap } from 'theme/styles'
|
||||
|
||||
import useENS from '../../hooks/useENS'
|
||||
import { ExternalLink, ThemedText } from '../../theme'
|
||||
@@ -12,7 +13,7 @@ import { AutoColumn } from '../Column'
|
||||
import { RowBetween } from '../Row'
|
||||
|
||||
const InputPanel = styled.div`
|
||||
${({ theme }) => theme.flexColumnNoWrap}
|
||||
${flexColumnNoWrap};
|
||||
position: relative;
|
||||
border-radius: 1.25rem;
|
||||
background-color: ${({ theme }) => theme.deprecated_bg1};
|
||||
@@ -25,7 +26,7 @@ const ContainerRow = styled.div<{ error: boolean }>`
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 1.25rem;
|
||||
border: 1px solid ${({ error, theme }) => (error ? theme.deprecated_red1 : theme.deprecated_bg2)};
|
||||
border: 1px solid ${({ error, theme }) => (error ? theme.accentFailure : theme.backgroundInteractive)};
|
||||
transition: border-color 300ms ${({ error }) => (error ? 'step-end' : 'step-start')},
|
||||
color 500ms ${({ error }) => (error ? 'step-end' : 'step-start')};
|
||||
background-color: ${({ theme }) => theme.deprecated_bg1};
|
||||
@@ -44,7 +45,7 @@ const Input = styled.input<{ error?: boolean }>`
|
||||
width: 0;
|
||||
background-color: ${({ theme }) => theme.deprecated_bg1};
|
||||
transition: color 300ms ${({ error }) => (error ? 'step-end' : 'step-start')};
|
||||
color: ${({ error, theme }) => (error ? theme.deprecated_red1 : theme.deprecated_text1)};
|
||||
color: ${({ error, theme }) => (error ? theme.accentFailure : theme.textPrimary)};
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: 500;
|
||||
@@ -108,7 +109,7 @@ export default function AddressInputPanel({
|
||||
<InputContainer>
|
||||
<AutoColumn gap="md">
|
||||
<RowBetween>
|
||||
<ThemedText.DeprecatedBlack color={theme.deprecated_text2} fontWeight={500} fontSize={14}>
|
||||
<ThemedText.DeprecatedBlack color={theme.textSecondary} fontWeight={500} fontSize={14}>
|
||||
{label ?? <Trans>Recipient</Trans>}
|
||||
</ThemedText.DeprecatedBlack>
|
||||
{address && chainId && (
|
||||
|
||||
335
src/components/AirdropModal/index.tsx
Normal file
@@ -0,0 +1,335 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import type { TransactionResponse } from '@ethersproject/providers'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import uniswapNftAirdropClaim from 'abis/uniswap-nft-airdrop-claim.json'
|
||||
import airdropBackgroundv2 from 'assets/images/airdopBackground.png'
|
||||
import { ButtonEmphasis, ButtonSize, ThemeButton } from 'components/Button'
|
||||
import { OpacityHoverState } from 'components/Common'
|
||||
import Loader from 'components/Loader'
|
||||
import { UNISWAP_NFT_AIRDROP_CLAIM_ADDRESS } from 'constants/addresses'
|
||||
import { useContract } from 'hooks/useContract'
|
||||
import { ChevronRightIcon } from 'nft/components/icons'
|
||||
import { useIsNftClaimAvailable } from 'nft/hooks/useIsNftClaimAvailable'
|
||||
import { CollectionRewardsFetcher } from 'nft/queries/genie/GetAirdorpMerkle'
|
||||
import { Airdrop, Rewards } from 'nft/types/airdrop'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { AlertTriangle } from 'react-feather'
|
||||
import { useModalIsOpen, useToggleModal } from 'state/application/hooks'
|
||||
import { ApplicationModal } from 'state/application/reducer'
|
||||
import styled from 'styled-components/macro'
|
||||
import { CloseIcon, ThemedText } from 'theme'
|
||||
|
||||
import Modal from '../Modal'
|
||||
|
||||
const ModalWrap = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`
|
||||
|
||||
const Body = styled.div`
|
||||
padding: 28px 20px 20px 20px;
|
||||
`
|
||||
|
||||
const ClaimButton = styled(ThemeButton)`
|
||||
width: 100%;
|
||||
background-color: ${({ theme }) => theme.accentAction};
|
||||
border-radius: 12px;
|
||||
color: ${({ theme }) => theme.white};
|
||||
`
|
||||
|
||||
const Line = styled.div`
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
opacity: 0.24;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
`
|
||||
|
||||
const LinkWrap = styled.a`
|
||||
text-decoration: none;
|
||||
${OpacityHoverState}
|
||||
`
|
||||
|
||||
const ImageContainer = styled.div`
|
||||
position: relative;
|
||||
width: 100%;
|
||||
`
|
||||
|
||||
const StyledImage = styled.img`
|
||||
width: 100%;
|
||||
height: 170px;
|
||||
`
|
||||
|
||||
const USDCLabel = styled.div`
|
||||
font-weight: 700;
|
||||
font-size: 36px;
|
||||
line-height: 44px;
|
||||
margin-top: 8px;
|
||||
color: white;
|
||||
`
|
||||
|
||||
const TextContainer = styled.div`
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
`
|
||||
|
||||
const RewardsDetailsContainer = styled.div`
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
`
|
||||
|
||||
const CurrencyText = styled.span`
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
line-height: 14.5px;
|
||||
`
|
||||
|
||||
const ClaimContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
height: 380px;
|
||||
padding: 60px 28px;
|
||||
padding-bottom: 20px;
|
||||
`
|
||||
|
||||
const SuccessText = styled.div`
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 8px;
|
||||
`
|
||||
|
||||
const EtherscanLink = styled.a`
|
||||
text-decoration: none;
|
||||
|
||||
${OpacityHoverState}
|
||||
`
|
||||
|
||||
const CloseButton = styled(ThemeButton)`
|
||||
max-width: 68px;
|
||||
margin-top: auto;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
`
|
||||
|
||||
const SyledCloseIcon = styled(CloseIcon)`
|
||||
float: right;
|
||||
height: 24px;
|
||||
|
||||
${OpacityHoverState}
|
||||
`
|
||||
|
||||
const Error = styled.div`
|
||||
display: flex;
|
||||
color: ${({ theme }) => theme.accentCritical};
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
border-radius: 16px;
|
||||
padding: 12px 20px;
|
||||
font-size: 14px;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
`
|
||||
|
||||
const ReactLinkWrap = styled.div`
|
||||
margin-bottom: 40px;
|
||||
`
|
||||
|
||||
const RewardsText = styled.span`
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: ${({ theme }) => theme.white};
|
||||
|
||||
&:first-child {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
`
|
||||
|
||||
const RewardsInformationText = styled.span`
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: ${({ theme }) => theme.textPrimary};
|
||||
margin-bottom: 28px;
|
||||
`
|
||||
|
||||
const MainHeader = styled.span`
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
color: ${({ theme }) => theme.white};
|
||||
`
|
||||
|
||||
const EtherscanLinkWrap = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
`
|
||||
|
||||
enum RewardAmounts {
|
||||
tradingRewardAmount = 300,
|
||||
holderRewardAmount = 1000,
|
||||
combinedAmount = 1300,
|
||||
}
|
||||
|
||||
const AirdropModal = () => {
|
||||
const { account, provider } = useWeb3React()
|
||||
const [claim, setClaim] = useState<Rewards>()
|
||||
const [isClaimed, setIsClaimed] = useState(false)
|
||||
const [hash, setHash] = useState('')
|
||||
const [error, setError] = useState(false)
|
||||
const setIsClaimAvailable = useIsNftClaimAvailable((state) => state.setIsClaimAvailable)
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const [totalAmount, setTotalAmount] = useState(0)
|
||||
const isOpen = useModalIsOpen(ApplicationModal.UNISWAP_NFT_AIRDROP_CLAIM)
|
||||
const usdcAirdropToggle = useToggleModal(ApplicationModal.UNISWAP_NFT_AIRDROP_CLAIM)
|
||||
const contract = useContract(UNISWAP_NFT_AIRDROP_CLAIM_ADDRESS, uniswapNftAirdropClaim)
|
||||
|
||||
const displayError = () => {
|
||||
setIsSubmitting(false)
|
||||
setError(true)
|
||||
setTimeout(() => {
|
||||
setError(false)
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (account && provider && contract) {
|
||||
;(async () => {
|
||||
try {
|
||||
const { data } = await CollectionRewardsFetcher(account)
|
||||
const claim = data.find((claim) => claim?.rewardType === Airdrop.GENIE_UNISWAP_USDC_AIRDROP)
|
||||
|
||||
if (!claim) return
|
||||
|
||||
const [isClaimed] = await contract.connect(provider).functions.isClaimed(claim?.index)
|
||||
|
||||
if (claim && isClaimed === false) {
|
||||
const usdAmount = BigNumber.from(claim.amount).div(10 ** 6)
|
||||
setClaim(claim)
|
||||
setTotalAmount(usdAmount.toNumber())
|
||||
setIsClaimAvailable(true)
|
||||
}
|
||||
} catch (err) {
|
||||
displayError()
|
||||
}
|
||||
})()
|
||||
}
|
||||
}, [account, contract, provider, setIsClaimAvailable])
|
||||
|
||||
const makeClaim = async () => {
|
||||
try {
|
||||
if (contract && claim && claim.amount && claim.merkleProof && provider) {
|
||||
setIsSubmitting(true)
|
||||
|
||||
const response: TransactionResponse = await contract
|
||||
.connect(provider?.getSigner())
|
||||
.functions.claim(claim.index, account, claim?.amount, claim?.merkleProof)
|
||||
|
||||
await response.wait()
|
||||
|
||||
setHash(response.hash)
|
||||
setIsSubmitting(false)
|
||||
setIsClaimed(true)
|
||||
setIsClaimAvailable(false)
|
||||
}
|
||||
} catch (err) {
|
||||
setIsSubmitting(false)
|
||||
displayError()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal hideBorder isOpen={isOpen} onDismiss={usdcAirdropToggle} maxHeight={90} maxWidth={400}>
|
||||
<ModalWrap>
|
||||
{isClaimed ? (
|
||||
<ClaimContainer>
|
||||
<ThemedText.HeadlineSmall>Congratulations!</ThemedText.HeadlineSmall>
|
||||
<SuccessText>
|
||||
You have successfully claimed {totalAmount} USDC. Thank you for supporting Genie.xyz.
|
||||
</SuccessText>
|
||||
<EtherscanLink href={`https://etherscan.io/tx/${hash}`} target="_blank">
|
||||
<ThemedText.Link>
|
||||
<EtherscanLinkWrap>
|
||||
<span>Etherscan</span>
|
||||
<ChevronRightIcon />
|
||||
</EtherscanLinkWrap>
|
||||
</ThemedText.Link>
|
||||
</EtherscanLink>
|
||||
|
||||
<CloseButton size={ButtonSize.medium} emphasis={ButtonEmphasis.medium} onClick={usdcAirdropToggle}>
|
||||
Close
|
||||
</CloseButton>
|
||||
</ClaimContainer>
|
||||
) : (
|
||||
<>
|
||||
<ImageContainer>
|
||||
<TextContainer>
|
||||
<SyledCloseIcon onClick={usdcAirdropToggle} stroke="white" />
|
||||
<MainHeader>Uniswap NFT Airdrop</MainHeader>
|
||||
<USDCLabel>{totalAmount} USDC</USDCLabel>
|
||||
<Line />
|
||||
<RewardsDetailsContainer>
|
||||
<RewardsText>Trading rewards</RewardsText>{' '}
|
||||
<CurrencyText>
|
||||
{totalAmount === RewardAmounts.tradingRewardAmount || totalAmount === RewardAmounts.combinedAmount
|
||||
? `${RewardAmounts.tradingRewardAmount} USDC`
|
||||
: '0'}
|
||||
</CurrencyText>
|
||||
</RewardsDetailsContainer>
|
||||
<RewardsDetailsContainer>
|
||||
<RewardsText>Genie NFT holder rewards</RewardsText>{' '}
|
||||
<CurrencyText>
|
||||
{totalAmount !== RewardAmounts.tradingRewardAmount
|
||||
? `${RewardAmounts.holderRewardAmount} USDC`
|
||||
: '0'}
|
||||
</CurrencyText>
|
||||
</RewardsDetailsContainer>
|
||||
</TextContainer>
|
||||
<StyledImage src={airdropBackgroundv2} />
|
||||
</ImageContainer>
|
||||
<Body>
|
||||
<RewardsInformationText>
|
||||
As a long time supporter of Genie, you’ve been awarded {totalAmount} USDC tokens.
|
||||
</RewardsInformationText>
|
||||
<ReactLinkWrap>
|
||||
<LinkWrap href="https://uniswap.org/blog/uniswap-nft-aggregator-announcement" target="_blank">
|
||||
<ThemedText.Link>Read more about Uniswap NFT.</ThemedText.Link>
|
||||
</LinkWrap>
|
||||
</ReactLinkWrap>
|
||||
|
||||
{error && (
|
||||
<Error>
|
||||
<AlertTriangle />
|
||||
Claim USDC failed. Please try again later
|
||||
</Error>
|
||||
)}
|
||||
|
||||
<ClaimButton
|
||||
onClick={makeClaim}
|
||||
size={ButtonSize.medium}
|
||||
emphasis={ButtonEmphasis.medium}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
{isSubmitting && <Loader stroke="white" />}
|
||||
<span>Claim{isSubmitting && 'ing'} USDC</span>
|
||||
</ClaimButton>
|
||||
</Body>
|
||||
</>
|
||||
)}
|
||||
</ModalWrap>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default AirdropModal
|
||||
@@ -17,7 +17,7 @@ const BadgeText = styled.div`
|
||||
`
|
||||
|
||||
const ActiveDot = styled.span`
|
||||
background-color: ${({ theme }) => theme.deprecated_success};
|
||||
background-color: ${({ theme }) => theme.accentSuccess};
|
||||
border-radius: 50%;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { readableColor } from 'polished'
|
||||
import { PropsWithChildren } from 'react'
|
||||
import styled, { DefaultTheme } from 'styled-components/macro'
|
||||
import { Color } from 'theme/styled'
|
||||
|
||||
export enum BadgeVariant {
|
||||
DEFAULT = 'DEFAULT',
|
||||
@@ -17,27 +16,27 @@ interface BadgeProps {
|
||||
variant?: BadgeVariant
|
||||
}
|
||||
|
||||
function pickBackgroundColor(variant: BadgeVariant | undefined, theme: DefaultTheme): Color {
|
||||
function pickBackgroundColor(variant: BadgeVariant | undefined, theme: DefaultTheme): string {
|
||||
switch (variant) {
|
||||
case BadgeVariant.NEGATIVE:
|
||||
return theme.deprecated_error
|
||||
return theme.accentFailure
|
||||
case BadgeVariant.POSITIVE:
|
||||
return theme.deprecated_success
|
||||
return theme.accentSuccess
|
||||
case BadgeVariant.PRIMARY:
|
||||
return theme.deprecated_primary1
|
||||
return theme.accentAction
|
||||
case BadgeVariant.WARNING:
|
||||
return theme.deprecated_warning
|
||||
return theme.accentWarning
|
||||
case BadgeVariant.WARNING_OUTLINE:
|
||||
return 'transparent'
|
||||
default:
|
||||
return theme.deprecated_bg2
|
||||
return theme.backgroundInteractive
|
||||
}
|
||||
}
|
||||
|
||||
function pickBorder(variant: BadgeVariant | undefined, theme: DefaultTheme): string {
|
||||
switch (variant) {
|
||||
case BadgeVariant.WARNING_OUTLINE:
|
||||
return `1px solid ${theme.deprecated_warning}`
|
||||
return `1px solid ${theme.accentWarning}`
|
||||
default:
|
||||
return 'unset'
|
||||
}
|
||||
@@ -46,15 +45,15 @@ function pickBorder(variant: BadgeVariant | undefined, theme: DefaultTheme): str
|
||||
function pickFontColor(variant: BadgeVariant | undefined, theme: DefaultTheme): string {
|
||||
switch (variant) {
|
||||
case BadgeVariant.NEGATIVE:
|
||||
return readableColor(theme.deprecated_error)
|
||||
return readableColor(theme.accentFailure)
|
||||
case BadgeVariant.POSITIVE:
|
||||
return readableColor(theme.deprecated_success)
|
||||
return readableColor(theme.accentSuccess)
|
||||
case BadgeVariant.WARNING:
|
||||
return readableColor(theme.deprecated_warning)
|
||||
return readableColor(theme.accentWarning)
|
||||
case BadgeVariant.WARNING_OUTLINE:
|
||||
return theme.deprecated_warning
|
||||
return theme.accentWarning
|
||||
default:
|
||||
return readableColor(theme.deprecated_bg2)
|
||||
return readableColor(theme.backgroundInteractive)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
13
src/components/Button/LoadingButtonSpinner.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { SpinnerSVG } from 'theme'
|
||||
|
||||
const ButtonLoadingSpinner = (props: React.ComponentPropsWithoutRef<'svg'>) => (
|
||||
<SpinnerSVG width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" {...props}>
|
||||
<path
|
||||
opacity="0.1"
|
||||
d="M18.8334 10.0003C18.8334 14.6027 15.1025 18.3337 10.5001 18.3337C5.89771 18.3337 2.16675 14.6027 2.16675 10.0003C2.16675 5.39795 5.89771 1.66699 10.5001 1.66699C15.1025 1.66699 18.8334 5.39795 18.8334 10.0003ZM4.66675 10.0003C4.66675 13.222 7.27842 15.8337 10.5001 15.8337C13.7217 15.8337 16.3334 13.222 16.3334 10.0003C16.3334 6.77867 13.7217 4.16699 10.5001 4.16699C7.27842 4.16699 4.66675 6.77867 4.66675 10.0003Z"
|
||||
/>
|
||||
<path d="M17.5834 10.0003C18.2738 10.0003 18.843 9.4376 18.7398 8.755C18.6392 8.0891 18.458 7.43633 18.1991 6.8113C17.7803 5.80025 17.1665 4.88159 16.3926 4.10777C15.6188 3.33395 14.7002 2.72012 13.6891 2.30133C13.0641 2.04243 12.4113 1.86121 11.7454 1.76057C11.0628 1.6574 10.5001 2.22664 10.5001 2.91699C10.5001 3.60735 11.066 4.15361 11.7405 4.30041C12.0789 4.37406 12.4109 4.47786 12.7324 4.61103C13.4401 4.90418 14.0832 5.33386 14.6249 5.87554C15.1665 6.41721 15.5962 7.06027 15.8894 7.76801C16.0225 8.08949 16.1264 8.42147 16.2 8.75986C16.3468 9.43443 16.8931 10.0003 17.5834 10.0003Z" />
|
||||
</SpinnerSVG>
|
||||
)
|
||||
|
||||
export default ButtonLoadingSpinner
|
||||
@@ -5,16 +5,31 @@ import styled, { DefaultTheme, useTheme } from 'styled-components/macro'
|
||||
|
||||
import { RowBetween } from '../Row'
|
||||
|
||||
export { default as LoadingButtonSpinner } from './LoadingButtonSpinner'
|
||||
|
||||
type ButtonProps = Omit<ButtonPropsOriginal, 'css'>
|
||||
|
||||
export const BaseButton = styled(RebassButton)<
|
||||
{
|
||||
padding?: string
|
||||
width?: string
|
||||
$borderRadius?: string
|
||||
altDisabledStyle?: boolean
|
||||
} & ButtonProps
|
||||
>`
|
||||
const ButtonOverlay = styled.div`
|
||||
background-color: transparent;
|
||||
bottom: 0;
|
||||
border-radius: inherit;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transition: 150ms ease background-color;
|
||||
width: 100%;
|
||||
`
|
||||
|
||||
type BaseButtonProps = {
|
||||
padding?: string
|
||||
width?: string
|
||||
$borderRadius?: string
|
||||
altDisabledStyle?: boolean
|
||||
} & ButtonProps
|
||||
|
||||
export const BaseButton = styled(RebassButton)<BaseButtonProps>`
|
||||
padding: ${({ padding }) => padding ?? '16px'};
|
||||
width: ${({ width }) => width ?? '100%'};
|
||||
font-weight: 500;
|
||||
@@ -22,7 +37,7 @@ export const BaseButton = styled(RebassButton)<
|
||||
border-radius: ${({ $borderRadius }) => $borderRadius ?? '20px'};
|
||||
outline: none;
|
||||
border: 1px solid transparent;
|
||||
color: ${({ theme }) => theme.deprecated_text1};
|
||||
color: ${({ theme }) => theme.textPrimary};
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -57,21 +72,21 @@ export const ButtonPrimary = styled(BaseButton)`
|
||||
padding: 16px;
|
||||
color: ${({ theme }) => theme.accentTextLightPrimary};
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.05, theme.deprecated_primary1)};
|
||||
background-color: ${({ theme }) => darken(0.05, theme.deprecated_primary1)};
|
||||
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.05, theme.accentAction)};
|
||||
background-color: ${({ theme }) => darken(0.05, theme.accentAction)};
|
||||
}
|
||||
&:hover {
|
||||
background-color: ${({ theme }) => darken(0.05, theme.deprecated_primary1)};
|
||||
background-color: ${({ theme }) => darken(0.05, theme.accentAction)};
|
||||
}
|
||||
&:active {
|
||||
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.1, theme.deprecated_primary1)};
|
||||
background-color: ${({ theme }) => darken(0.1, theme.deprecated_primary1)};
|
||||
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.1, theme.accentAction)};
|
||||
background-color: ${({ theme }) => darken(0.1, theme.accentAction)};
|
||||
}
|
||||
&:disabled {
|
||||
background-color: ${({ theme, altDisabledStyle, disabled }) =>
|
||||
altDisabledStyle ? (disabled ? theme.deprecated_primary1 : theme.deprecated_bg2) : theme.deprecated_bg2};
|
||||
altDisabledStyle ? (disabled ? theme.accentAction : theme.backgroundInteractive) : theme.backgroundInteractive};
|
||||
color: ${({ altDisabledStyle, disabled, theme }) =>
|
||||
altDisabledStyle ? (disabled ? theme.deprecated_white : theme.deprecated_text2) : theme.deprecated_text2};
|
||||
altDisabledStyle ? (disabled ? theme.white : theme.textSecondary) : theme.textSecondary};
|
||||
cursor: auto;
|
||||
box-shadow: none;
|
||||
border: 1px solid transparent;
|
||||
@@ -79,7 +94,14 @@ export const ButtonPrimary = styled(BaseButton)`
|
||||
}
|
||||
`
|
||||
|
||||
export const ButtonLight = styled(BaseButton)`
|
||||
export const SmallButtonPrimary = styled(ButtonPrimary)`
|
||||
width: auto;
|
||||
font-size: 16px;
|
||||
padding: 10px 16px;
|
||||
border-radius: 12px;
|
||||
`
|
||||
|
||||
const BaseButtonLight = styled(BaseButton)`
|
||||
background-color: ${({ theme }) => theme.accentActionSoft};
|
||||
color: ${({ theme }) => theme.accentAction};
|
||||
font-size: 20px;
|
||||
@@ -96,6 +118,19 @@ export const ButtonLight = styled(BaseButton)`
|
||||
box-shadow: 0 0 0 1pt ${({ theme, disabled }) => !disabled && theme.accentActionSoft};
|
||||
background-color: ${({ theme, disabled }) => !disabled && theme.accentActionSoft};
|
||||
}
|
||||
|
||||
:hover {
|
||||
${ButtonOverlay} {
|
||||
background-color: ${({ theme }) => theme.stateOverlayHover};
|
||||
}
|
||||
}
|
||||
|
||||
:active {
|
||||
${ButtonOverlay} {
|
||||
background-color: ${({ theme }) => theme.stateOverlayPressed};
|
||||
}
|
||||
}
|
||||
|
||||
:disabled {
|
||||
opacity: 0.4;
|
||||
:hover {
|
||||
@@ -110,21 +145,21 @@ export const ButtonLight = styled(BaseButton)`
|
||||
|
||||
export const ButtonGray = styled(BaseButton)`
|
||||
background-color: ${({ theme }) => theme.deprecated_bg1};
|
||||
color: ${({ theme }) => theme.deprecated_text2};
|
||||
color: ${({ theme }) => theme.textSecondary};
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
background-color: ${({ theme, disabled }) => !disabled && darken(0.05, theme.deprecated_bg2)};
|
||||
background-color: ${({ theme, disabled }) => !disabled && darken(0.05, theme.backgroundInteractive)};
|
||||
}
|
||||
&:active {
|
||||
background-color: ${({ theme, disabled }) => !disabled && darken(0.1, theme.deprecated_bg2)};
|
||||
background-color: ${({ theme, disabled }) => !disabled && darken(0.1, theme.backgroundInteractive)};
|
||||
}
|
||||
`
|
||||
|
||||
export const ButtonSecondary = styled(BaseButton)`
|
||||
border: 1px solid ${({ theme }) => theme.deprecated_primary4};
|
||||
color: ${({ theme }) => theme.deprecated_primary1};
|
||||
color: ${({ theme }) => theme.accentAction};
|
||||
background-color: transparent;
|
||||
font-size: 16px;
|
||||
border-radius: 12px;
|
||||
@@ -151,14 +186,14 @@ export const ButtonSecondary = styled(BaseButton)`
|
||||
`
|
||||
|
||||
export const ButtonOutlined = styled(BaseButton)`
|
||||
border: 1px solid ${({ theme }) => theme.deprecated_bg2};
|
||||
border: 1px solid ${({ theme }) => theme.backgroundOutline};
|
||||
background-color: transparent;
|
||||
color: ${({ theme }) => theme.deprecated_text1};
|
||||
color: ${({ theme }) => theme.textPrimary};
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1px ${({ theme }) => theme.deprecated_bg4};
|
||||
}
|
||||
&:hover {
|
||||
box-shadow: 0 0 0 1px ${({ theme }) => theme.deprecated_bg4};
|
||||
box-shadow: 0 0 0 1px ${({ theme }) => theme.textTertiary};
|
||||
}
|
||||
&:active {
|
||||
box-shadow: 0 0 0 1px ${({ theme }) => theme.deprecated_bg4};
|
||||
@@ -191,7 +226,7 @@ export const ButtonYellow = styled(BaseButton)`
|
||||
|
||||
export const ButtonEmpty = styled(BaseButton)`
|
||||
background-color: transparent;
|
||||
color: ${({ theme }) => theme.deprecated_primary1};
|
||||
color: ${({ theme }) => theme.accentAction};
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -217,11 +252,9 @@ export const ButtonText = styled(BaseButton)`
|
||||
background: none;
|
||||
text-decoration: none;
|
||||
&:focus {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
text-decoration: underline;
|
||||
}
|
||||
&:hover {
|
||||
// text-decoration: underline;
|
||||
opacity: 0.9;
|
||||
}
|
||||
&:active {
|
||||
@@ -235,38 +268,38 @@ export const ButtonText = styled(BaseButton)`
|
||||
|
||||
const ButtonConfirmedStyle = styled(BaseButton)`
|
||||
background-color: ${({ theme }) => theme.deprecated_bg3};
|
||||
color: ${({ theme }) => theme.deprecated_text1};
|
||||
/* border: 1px solid ${({ theme }) => theme.deprecated_green1}; */
|
||||
color: ${({ theme }) => theme.textPrimary};
|
||||
/* border: 1px solid ${({ theme }) => theme.accentSuccess}; */
|
||||
|
||||
&:disabled {
|
||||
opacity: 50%;
|
||||
background-color: ${({ theme }) => theme.deprecated_bg2};
|
||||
color: ${({ theme }) => theme.deprecated_text2};
|
||||
background-color: ${({ theme }) => theme.backgroundInteractive};
|
||||
color: ${({ theme }) => theme.textSecondary};
|
||||
cursor: auto;
|
||||
}
|
||||
`
|
||||
|
||||
const ButtonErrorStyle = styled(BaseButton)`
|
||||
background-color: ${({ theme }) => theme.deprecated_red1};
|
||||
border: 1px solid ${({ theme }) => theme.deprecated_red1};
|
||||
background-color: ${({ theme }) => theme.accentFailure};
|
||||
border: 1px solid ${({ theme }) => theme.accentFailure};
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.05, theme.deprecated_red1)};
|
||||
background-color: ${({ theme }) => darken(0.05, theme.deprecated_red1)};
|
||||
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.05, theme.accentFailure)};
|
||||
background-color: ${({ theme }) => darken(0.05, theme.accentFailure)};
|
||||
}
|
||||
&:hover {
|
||||
background-color: ${({ theme }) => darken(0.05, theme.deprecated_red1)};
|
||||
background-color: ${({ theme }) => darken(0.05, theme.accentFailure)};
|
||||
}
|
||||
&:active {
|
||||
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.1, theme.deprecated_red1)};
|
||||
background-color: ${({ theme }) => darken(0.1, theme.deprecated_red1)};
|
||||
box-shadow: 0 0 0 1pt ${({ theme }) => darken(0.1, theme.accentFailure)};
|
||||
background-color: ${({ theme }) => darken(0.1, theme.accentFailure)};
|
||||
}
|
||||
&:disabled {
|
||||
opacity: 50%;
|
||||
cursor: auto;
|
||||
box-shadow: none;
|
||||
background-color: ${({ theme }) => theme.deprecated_red1};
|
||||
border: 1px solid ${({ theme }) => theme.deprecated_red1};
|
||||
background-color: ${({ theme }) => theme.accentFailure};
|
||||
border: 1px solid ${({ theme }) => theme.accentFailure};
|
||||
}
|
||||
`
|
||||
|
||||
@@ -314,14 +347,14 @@ export function ButtonDropdownLight({ disabled = false, children, ...rest }: { d
|
||||
|
||||
const ActiveOutlined = styled(ButtonOutlined)`
|
||||
border: 1px solid;
|
||||
border-color: ${({ theme }) => theme.deprecated_primary1};
|
||||
border-color: ${({ theme }) => theme.accentAction};
|
||||
`
|
||||
|
||||
const Circle = styled.div`
|
||||
height: 17px;
|
||||
width: 17px;
|
||||
border-radius: 50%;
|
||||
background-color: ${({ theme }) => theme.deprecated_primary1};
|
||||
background-color: ${({ theme }) => theme.accentAction};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -355,7 +388,7 @@ export function ButtonRadioChecked({ active = false, children, ...rest }: { acti
|
||||
{children}
|
||||
<CheckboxWrapper>
|
||||
<Circle>
|
||||
<ResponsiveCheck size={13} stroke={theme.deprecated_white} />
|
||||
<ResponsiveCheck size={13} stroke={theme.white} />
|
||||
</Circle>
|
||||
</CheckboxWrapper>
|
||||
</RowBetween>
|
||||
@@ -364,18 +397,6 @@ export function ButtonRadioChecked({ active = false, children, ...rest }: { acti
|
||||
}
|
||||
}
|
||||
|
||||
const ButtonOverlay = styled.div`
|
||||
background-color: transparent;
|
||||
bottom: 0;
|
||||
border-radius: 16px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
transition: 150ms ease background-color;
|
||||
width: 100%;
|
||||
`
|
||||
export enum ButtonSize {
|
||||
small,
|
||||
medium,
|
||||
@@ -390,7 +411,7 @@ export enum ButtonEmphasis {
|
||||
warning,
|
||||
destructive,
|
||||
}
|
||||
interface BaseButtonProps {
|
||||
interface BaseThemeButtonProps {
|
||||
size: ButtonSize
|
||||
emphasis: ButtonEmphasis
|
||||
}
|
||||
@@ -414,7 +435,42 @@ function pickThemeButtonBackgroundColor({ theme, emphasis }: { theme: DefaultThe
|
||||
return theme.backgroundInteractive
|
||||
}
|
||||
}
|
||||
|
||||
function pickThemeButtonFontSize({ size }: { size: ButtonSize }) {
|
||||
switch (size) {
|
||||
case ButtonSize.large:
|
||||
return '20px'
|
||||
case ButtonSize.medium:
|
||||
return '16px'
|
||||
case ButtonSize.small:
|
||||
return '14px'
|
||||
default:
|
||||
return '16px'
|
||||
}
|
||||
}
|
||||
function pickThemeButtonLineHeight({ size }: { size: ButtonSize }) {
|
||||
switch (size) {
|
||||
case ButtonSize.large:
|
||||
return '24px'
|
||||
case ButtonSize.medium:
|
||||
return '20px'
|
||||
case ButtonSize.small:
|
||||
return '16px'
|
||||
default:
|
||||
return '20px'
|
||||
}
|
||||
}
|
||||
function pickThemeButtonPadding({ size }: { size: ButtonSize }) {
|
||||
switch (size) {
|
||||
case ButtonSize.large:
|
||||
return '16px'
|
||||
case ButtonSize.medium:
|
||||
return '10px 12px'
|
||||
case ButtonSize.small:
|
||||
return '8px'
|
||||
default:
|
||||
return '10px 12px'
|
||||
}
|
||||
}
|
||||
function pickThemeButtonTextColor({ theme, emphasis }: { theme: DefaultTheme; emphasis: ButtonEmphasis }) {
|
||||
switch (emphasis) {
|
||||
case ButtonEmphasis.high:
|
||||
@@ -434,7 +490,7 @@ function pickThemeButtonTextColor({ theme, emphasis }: { theme: DefaultTheme; em
|
||||
}
|
||||
}
|
||||
|
||||
const BaseThemeButton = styled.button<BaseButtonProps>`
|
||||
const BaseThemeButton = styled.button<BaseThemeButtonProps>`
|
||||
align-items: center;
|
||||
background-color: ${pickThemeButtonBackgroundColor};
|
||||
border-radius: 16px;
|
||||
@@ -443,22 +499,21 @@ const BaseThemeButton = styled.button<BaseButtonProps>`
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: ${pickThemeButtonFontSize};
|
||||
font-weight: 600;
|
||||
gap: 12px;
|
||||
justify-content: center;
|
||||
padding: 16px;
|
||||
line-height: ${pickThemeButtonLineHeight};
|
||||
padding: ${pickThemeButtonPadding};
|
||||
position: relative;
|
||||
transition: 150ms ease opacity;
|
||||
user-select: none;
|
||||
|
||||
:active {
|
||||
${ButtonOverlay} {
|
||||
background-color: ${({ theme }) => theme.stateOverlayPressed};
|
||||
}
|
||||
}
|
||||
:disabled {
|
||||
cursor: default;
|
||||
opacity: 0.6;
|
||||
}
|
||||
:focus {
|
||||
${ButtonOverlay} {
|
||||
background-color: ${({ theme }) => theme.stateOverlayPressed};
|
||||
@@ -469,9 +524,20 @@ const BaseThemeButton = styled.button<BaseButtonProps>`
|
||||
background-color: ${({ theme }) => theme.stateOverlayHover};
|
||||
}
|
||||
}
|
||||
:disabled {
|
||||
cursor: default;
|
||||
opacity: 0.6;
|
||||
}
|
||||
:disabled:active,
|
||||
:disabled:focus,
|
||||
:disabled:hover {
|
||||
${ButtonOverlay} {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
interface ThemeButtonProps extends React.ComponentPropsWithoutRef<'button'>, BaseButtonProps {}
|
||||
interface ThemeButtonProps extends React.ComponentPropsWithoutRef<'button'>, BaseThemeButtonProps {}
|
||||
|
||||
export const ThemeButton = ({ children, ...rest }: ThemeButtonProps) => {
|
||||
return (
|
||||
@@ -481,3 +547,12 @@ export const ThemeButton = ({ children, ...rest }: ThemeButtonProps) => {
|
||||
</BaseThemeButton>
|
||||
)
|
||||
}
|
||||
|
||||
export const ButtonLight = ({ children, ...rest }: BaseButtonProps) => {
|
||||
return (
|
||||
<BaseButtonLight {...rest}>
|
||||
<ButtonOverlay />
|
||||
{children}
|
||||
</BaseButtonLight>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,24 +10,20 @@ const Card = styled(Box)<{ width?: string; padding?: string; border?: string; $b
|
||||
export default Card
|
||||
|
||||
export const LightCard = styled(Card)`
|
||||
border: 1px solid ${({ theme }) => theme.deprecated_bg2};
|
||||
border: 1px solid ${({ theme }) => theme.backgroundInteractive};
|
||||
background-color: ${({ theme }) => theme.deprecated_bg1};
|
||||
`
|
||||
|
||||
export const LightGrayCard = styled(Card)`
|
||||
background-color: ${({ theme }) => theme.deprecated_bg2};
|
||||
`
|
||||
|
||||
export const GrayCard = styled(Card)`
|
||||
background-color: ${({ theme }) => theme.deprecated_bg3};
|
||||
`
|
||||
|
||||
export const DarkGrayCard = styled(Card)`
|
||||
background-color: ${({ theme }) => theme.deprecated_bg2};
|
||||
background-color: ${({ theme }) => theme.backgroundInteractive};
|
||||
`
|
||||
|
||||
export const DarkCard = styled(Card)`
|
||||
background-color: ${({ theme }) => theme.deprecated_bg0};
|
||||
background-color: ${({ theme }) => theme.backgroundSurface};
|
||||
`
|
||||
|
||||
export const OutlineCard = styled(Card)`
|
||||
@@ -42,6 +38,6 @@ export const YellowCard = styled(Card)`
|
||||
|
||||
export const BlueCard = styled(Card)`
|
||||
background-color: ${({ theme }) => theme.deprecated_primary5};
|
||||
color: ${({ theme }) => theme.deprecated_blue2};
|
||||
color: ${({ theme }) => theme.accentAction};
|
||||
border-radius: 12px;
|
||||
`
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Group } from '@visx/group'
|
||||
import { LinePath } from '@visx/shape'
|
||||
import { easeCubicInOut } from 'd3'
|
||||
import { easeSinOut } from 'd3'
|
||||
import ms from 'ms.macro'
|
||||
import React from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { animated, useSpring } from 'react-spring'
|
||||
@@ -11,8 +12,8 @@ import { LineChartProps } from './LineChart'
|
||||
type AnimatedInLineChartProps<T> = Omit<LineChartProps<T>, 'height' | 'width' | 'children'>
|
||||
|
||||
const config = {
|
||||
duration: 800,
|
||||
easing: easeCubicInOut,
|
||||
duration: ms`0.8s`,
|
||||
easing: easeSinOut,
|
||||
}
|
||||
|
||||
// code reference: https://airbnb.io/visx/lineradial
|
||||
@@ -91,4 +92,4 @@ function AnimatedInLineChart<T>({
|
||||
)
|
||||
}
|
||||
|
||||
export default AnimatedInLineChart
|
||||
export default React.memo(AnimatedInLineChart) as typeof AnimatedInLineChart
|
||||
|
||||
86
src/components/Charts/FadeInLineChart.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import { Group } from '@visx/group'
|
||||
import { LinePath } from '@visx/shape'
|
||||
import { easeCubicInOut } from 'd3'
|
||||
import React from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { animated, useSpring } from 'react-spring'
|
||||
import { useTheme } from 'styled-components/macro'
|
||||
|
||||
import { LineChartProps } from './LineChart'
|
||||
|
||||
type FadedInLineChartProps<T> = Omit<LineChartProps<T>, 'height' | 'width' | 'children'> & { dashed?: boolean }
|
||||
|
||||
const config = {
|
||||
duration: 3000,
|
||||
easing: easeCubicInOut,
|
||||
}
|
||||
|
||||
// code reference: https://airbnb.io/visx/lineradial
|
||||
|
||||
function FadedInLineChart<T>({
|
||||
data,
|
||||
getX,
|
||||
getY,
|
||||
marginTop,
|
||||
curve,
|
||||
color,
|
||||
strokeWidth,
|
||||
dashed,
|
||||
}: FadedInLineChartProps<T>) {
|
||||
const lineRef = useRef<SVGPathElement>(null)
|
||||
const [lineLength, setLineLength] = useState(0)
|
||||
const [shouldAnimate, setShouldAnimate] = useState(false)
|
||||
const [hasAnimatedIn, setHasAnimatedIn] = useState(false)
|
||||
|
||||
const spring = useSpring({
|
||||
frame: shouldAnimate ? 0 : 1,
|
||||
config,
|
||||
onRest: () => {
|
||||
setShouldAnimate(false)
|
||||
setHasAnimatedIn(true)
|
||||
},
|
||||
})
|
||||
|
||||
// We need to check to see after the "invisble" line has been drawn
|
||||
// what the length is to be able to animate in the line for the first time
|
||||
// This will run on each render to see if there is a new line length
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
useEffect(() => {
|
||||
if (lineRef.current) {
|
||||
const length = lineRef.current.getTotalLength()
|
||||
if (length !== lineLength) {
|
||||
setLineLength(length)
|
||||
}
|
||||
if (length > 0 && !shouldAnimate && !hasAnimatedIn) {
|
||||
setShouldAnimate(true)
|
||||
}
|
||||
}
|
||||
})
|
||||
const theme = useTheme()
|
||||
const lineColor = color ?? theme.accentAction
|
||||
|
||||
return (
|
||||
<Group top={marginTop}>
|
||||
<LinePath curve={curve} x={getX} y={getY}>
|
||||
{({ path }) => {
|
||||
const d = path(data) || ''
|
||||
return (
|
||||
<>
|
||||
<animated.path
|
||||
d={d}
|
||||
ref={lineRef}
|
||||
strokeWidth={strokeWidth}
|
||||
strokeOpacity={hasAnimatedIn ? 1 : spring.frame.to((v) => 1 - v)}
|
||||
fill="none"
|
||||
stroke={lineColor}
|
||||
strokeDasharray={dashed ? '4,4' : undefined}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}}
|
||||
</LinePath>
|
||||
</Group>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(FadedInLineChart) as typeof FadedInLineChart
|
||||
@@ -4,7 +4,6 @@ import { CurveFactory } from 'd3'
|
||||
import React from 'react'
|
||||
import { ReactNode } from 'react'
|
||||
import { useTheme } from 'styled-components/macro'
|
||||
import { Color } from 'theme/styled'
|
||||
|
||||
export interface LineChartProps<T> {
|
||||
data: T[]
|
||||
@@ -12,7 +11,7 @@ export interface LineChartProps<T> {
|
||||
getY: (t: T) => number
|
||||
marginTop?: number
|
||||
curve: CurveFactory
|
||||
color?: Color
|
||||
color?: string
|
||||
strokeWidth: number
|
||||
children?: ReactNode
|
||||
width: number
|
||||
|
||||
@@ -2,7 +2,6 @@ import { SparkLineLoadingBubble } from 'components/Tokens/TokenTable/TokenRow'
|
||||
import { curveCardinal, scaleLinear } from 'd3'
|
||||
import { SparklineMap, TopToken } from 'graphql/data/TopTokens'
|
||||
import { PricePoint } from 'graphql/data/util'
|
||||
import { TimePeriod } from 'graphql/data/util'
|
||||
import { memo } from 'react'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
|
||||
@@ -21,18 +20,10 @@ interface SparklineChartProps {
|
||||
height: number
|
||||
tokenData: TopToken
|
||||
pricePercentChange: number | undefined | null
|
||||
timePeriod: TimePeriod
|
||||
sparklineMap: SparklineMap
|
||||
}
|
||||
|
||||
function _SparklineChart({
|
||||
width,
|
||||
height,
|
||||
tokenData,
|
||||
pricePercentChange,
|
||||
timePeriod,
|
||||
sparklineMap,
|
||||
}: SparklineChartProps) {
|
||||
function _SparklineChart({ width, height, tokenData, pricePercentChange, sparklineMap }: SparklineChartProps) {
|
||||
const theme = useTheme()
|
||||
// for sparkline
|
||||
const pricePoints = tokenData?.address ? sparklineMap[tokenData.address] : null
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import styled from 'styled-components/macro'
|
||||
import styled, { DefaultTheme } from 'styled-components/macro'
|
||||
|
||||
const Column = styled.div`
|
||||
type Gap = keyof DefaultTheme['grids']
|
||||
|
||||
export const Column = styled.div<{
|
||||
gap?: Gap
|
||||
}>`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
gap: ${({ gap, theme }) => gap && theme.grids[gap]};
|
||||
`
|
||||
export const ColumnCenter = styled(Column)`
|
||||
width: 100%;
|
||||
@@ -11,12 +16,12 @@ export const ColumnCenter = styled(Column)`
|
||||
`
|
||||
|
||||
export const AutoColumn = styled.div<{
|
||||
gap?: 'sm' | 'md' | 'lg' | string
|
||||
gap?: Gap | string
|
||||
justify?: 'stretch' | 'center' | 'start' | 'end' | 'flex-start' | 'flex-end' | 'space-between'
|
||||
}>`
|
||||
display: grid;
|
||||
grid-auto-rows: auto;
|
||||
grid-row-gap: ${({ gap }) => (gap === 'sm' && '8px') || (gap === 'md' && '12px') || (gap === 'lg' && '24px') || gap};
|
||||
grid-row-gap: ${({ gap, theme }) => (gap && theme.grids[gap as Gap]) || gap};
|
||||
justify-items: ${({ justify }) => justify && justify};
|
||||
`
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import ReactConfetti from 'react-confetti'
|
||||
|
||||
import { useWindowSize } from '../../hooks/useWindowSize'
|
||||
|
||||
// eslint-disable-next-line react/prop-types
|
||||
export default function Confetti({ start, variant }: { start: boolean; variant?: string }) {
|
||||
const { width, height } = useWindowSize()
|
||||
|
||||
const _variant = variant ? variant : height && width && height > 1.5 * width ? 'bottom' : variant
|
||||
|
||||
return start && width && height ? (
|
||||
<ReactConfetti
|
||||
style={{ zIndex: 1401 }}
|
||||
numberOfPieces={400}
|
||||
recycle={false}
|
||||
run={true}
|
||||
width={width}
|
||||
height={height}
|
||||
confettiSource={{
|
||||
h: height,
|
||||
w: width,
|
||||
x: 0,
|
||||
y: _variant === 'top' ? height * 0.25 : _variant === 'bottom' ? height * 0.75 : height * 0.5,
|
||||
}}
|
||||
initialVelocityX={15}
|
||||
initialVelocityY={30}
|
||||
gravity={0.45}
|
||||
tweenDuration={100}
|
||||
wind={0.05}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import Column from 'components/Column'
|
||||
import { AlertOctagon } from 'react-feather'
|
||||
import { BlockedIcon } from 'components/TokenSafety/TokenSafetyIcon'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
import { ExternalLink, ThemedText } from 'theme'
|
||||
|
||||
@@ -13,11 +13,6 @@ const ContentWrapper = styled(Column)`
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
`
|
||||
const WarningIcon = styled(AlertOctagon)`
|
||||
min-height: 22px;
|
||||
min-width: 22px;
|
||||
color: ${({ theme }) => theme.deprecated_warning};
|
||||
`
|
||||
const Copy = styled(CopyHelper)`
|
||||
font-size: 12px;
|
||||
`
|
||||
@@ -32,7 +27,7 @@ export default function ConnectedAccountBlocked(props: ConnectedAccountBlockedPr
|
||||
return (
|
||||
<Modal isOpen={props.isOpen} onDismiss={Function.prototype()}>
|
||||
<ContentWrapper>
|
||||
<WarningIcon />
|
||||
<BlockedIcon size="22px" />
|
||||
<ThemedText.DeprecatedLargeHeader lineHeight={2} marginBottom={1} marginTop={1}>
|
||||
<Trans>Blocked Address</Trans>
|
||||
</ThemedText.DeprecatedLargeHeader>
|
||||
@@ -54,7 +49,7 @@ export default function ConnectedAccountBlocked(props: ConnectedAccountBlockedPr
|
||||
fontSize={14}
|
||||
iconSize={16}
|
||||
gap={6}
|
||||
color={theme.deprecated_primary1}
|
||||
color={theme.accentAction}
|
||||
iconPosition="right"
|
||||
>
|
||||
compliance@uniswap.org
|
||||
|
||||
@@ -1,45 +1,72 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { t } from '@lingui/macro'
|
||||
import { formatCurrencyAmount, formatPriceImpact, NumberType } from '@uniswap/conedison/format'
|
||||
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||
import { useMemo } from 'react'
|
||||
import { useTheme } from 'styled-components/macro'
|
||||
import { LoadingBubble } from 'components/Tokens/loading'
|
||||
import { MouseoverTooltip } from 'components/Tooltip'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
|
||||
import { ThemedText } from '../../theme'
|
||||
import { warningSeverity } from '../../utils/prices'
|
||||
import { MouseoverTooltip } from '../Tooltip'
|
||||
|
||||
const FiatLoadingBubble = styled(LoadingBubble)`
|
||||
border-radius: 4px;
|
||||
width: 4rem;
|
||||
height: 1rem;
|
||||
`
|
||||
|
||||
export function FiatValue({
|
||||
fiatValue,
|
||||
priceImpact,
|
||||
isLoading = false,
|
||||
}: {
|
||||
fiatValue: CurrencyAmount<Currency> | null | undefined
|
||||
priceImpact?: Percent
|
||||
isLoading?: boolean
|
||||
}) {
|
||||
const theme = useTheme()
|
||||
const [showLoadingPlaceholder, setShowLoadingPlaceholder] = useState(false)
|
||||
const priceImpactColor = useMemo(() => {
|
||||
if (!priceImpact) return undefined
|
||||
if (priceImpact.lessThan('0')) return theme.deprecated_green1
|
||||
if (priceImpact.lessThan('0')) return theme.accentSuccess
|
||||
const severity = warningSeverity(priceImpact)
|
||||
if (severity < 1) return theme.deprecated_text3
|
||||
if (severity < 1) return theme.textTertiary
|
||||
if (severity < 3) return theme.deprecated_yellow1
|
||||
return theme.deprecated_red1
|
||||
}, [priceImpact, theme.deprecated_green1, theme.deprecated_red1, theme.deprecated_text3, theme.deprecated_yellow1])
|
||||
return theme.accentFailure
|
||||
}, [priceImpact, theme.accentSuccess, theme.accentFailure, theme.textTertiary, theme.deprecated_yellow1])
|
||||
|
||||
const p = Number(fiatValue?.toFixed())
|
||||
const visibleDecimalPlaces = p < 1.05 ? 4 : 2
|
||||
useEffect(() => {
|
||||
const stale = false
|
||||
let timeoutId = 0
|
||||
if (isLoading && !fiatValue) {
|
||||
timeoutId = setTimeout(() => {
|
||||
if (!stale) setShowLoadingPlaceholder(true)
|
||||
}, 200) as unknown as number
|
||||
} else {
|
||||
setShowLoadingPlaceholder(false)
|
||||
}
|
||||
return () => clearTimeout(timeoutId)
|
||||
}, [isLoading, fiatValue])
|
||||
|
||||
return (
|
||||
<ThemedText.DeprecatedBody fontSize={14} color={theme.textSecondary}>
|
||||
{fiatValue && <>${fiatValue?.toFixed(visibleDecimalPlaces, { groupSeparator: ',' })}</>}
|
||||
{priceImpact ? (
|
||||
<span style={{ color: priceImpactColor }}>
|
||||
{' '}
|
||||
<MouseoverTooltip text={t`The estimated difference between the USD values of input and output amounts.`}>
|
||||
(<Trans>{priceImpact.multiply(-1).toSignificant(3)}%</Trans>)
|
||||
</MouseoverTooltip>
|
||||
</span>
|
||||
) : null}
|
||||
{showLoadingPlaceholder ? (
|
||||
<FiatLoadingBubble />
|
||||
) : (
|
||||
<div>
|
||||
{fiatValue && <>{formatCurrencyAmount(fiatValue, NumberType.FiatTokenPrice)}</>}
|
||||
{priceImpact && (
|
||||
<span style={{ color: priceImpactColor }}>
|
||||
{' '}
|
||||
<MouseoverTooltip text={t`The estimated difference between the USD values of input and output amounts.`}>
|
||||
(<Trans>{formatPriceImpact(priceImpact)}</Trans>)
|
||||
</MouseoverTooltip>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</ThemedText.DeprecatedBody>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,18 +6,19 @@ import { Pair } from '@uniswap/v2-sdk'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { AutoColumn } from 'components/Column'
|
||||
import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled'
|
||||
import CurrencyLogo from 'components/Logo/CurrencyLogo'
|
||||
import { isSupportedChain } from 'constants/chains'
|
||||
import { darken } from 'polished'
|
||||
import { ReactNode, useCallback, useState } from 'react'
|
||||
import { ReactNode, useCallback, useEffect, useState } from 'react'
|
||||
import { Lock } from 'react-feather'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
import { flexColumnNoWrap, flexRowNoWrap } from 'theme/styles'
|
||||
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
|
||||
|
||||
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
|
||||
import { useCurrencyBalance } from '../../state/connection/hooks'
|
||||
import { ThemedText } from '../../theme'
|
||||
import { ButtonGray } from '../Button'
|
||||
import CurrencyLogo from '../CurrencyLogo'
|
||||
import DoubleCurrencyLogo from '../DoubleLogo'
|
||||
import { Input as NumericalInput } from '../NumericalInput'
|
||||
import { RowBetween, RowFixed } from '../Row'
|
||||
@@ -25,7 +26,7 @@ import CurrencySearchModal from '../SearchModal/CurrencySearchModal'
|
||||
import { FiatValue } from './FiatValue'
|
||||
|
||||
const InputPanel = styled.div<{ hideInput?: boolean }>`
|
||||
${({ theme }) => theme.flexColumnNoWrap}
|
||||
${flexColumnNoWrap};
|
||||
position: relative;
|
||||
border-radius: ${({ hideInput }) => (hideInput ? '16px' : '20px')};
|
||||
z-index: 1;
|
||||
@@ -61,7 +62,7 @@ const CurrencySelect = styled(ButtonGray)<{
|
||||
background-color: ${({ selected, theme }) => (selected ? theme.backgroundInteractive : theme.accentAction)};
|
||||
opacity: ${({ disabled }) => (!disabled ? 1 : 0.4)};
|
||||
box-shadow: ${({ selected }) => (selected ? 'none' : '0px 6px 10px rgba(0, 0, 0, 0.075)')};
|
||||
color: ${({ selected, theme }) => (selected ? theme.deprecated_text1 : theme.deprecated_white)};
|
||||
color: ${({ selected, theme }) => (selected ? theme.textPrimary : theme.white)};
|
||||
cursor: pointer;
|
||||
height: unset;
|
||||
border-radius: 16px;
|
||||
@@ -106,13 +107,13 @@ const CurrencySelect = styled(ButtonGray)<{
|
||||
`
|
||||
|
||||
const InputRow = styled.div`
|
||||
${({ theme }) => theme.flexRowNoWrap}
|
||||
${flexRowNoWrap};
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
`
|
||||
|
||||
const LabelRow = styled.div`
|
||||
${({ theme }) => theme.flexRowNoWrap}
|
||||
${flexRowNoWrap};
|
||||
align-items: center;
|
||||
color: ${({ theme }) => theme.textSecondary};
|
||||
font-size: 0.75rem;
|
||||
@@ -120,7 +121,7 @@ const LabelRow = styled.div`
|
||||
|
||||
span:hover {
|
||||
cursor: pointer;
|
||||
color: ${({ theme }) => darken(0.2, theme.deprecated_text2)};
|
||||
color: ${({ theme }) => darken(0.2, theme.textSecondary)};
|
||||
}
|
||||
`
|
||||
|
||||
@@ -143,7 +144,7 @@ const StyledDropDown = styled(DropDown)<{ selected: boolean }>`
|
||||
margin-left: 8px;
|
||||
|
||||
path {
|
||||
stroke: ${({ selected, theme }) => (selected ? theme.deprecated_text1 : theme.deprecated_white)};
|
||||
stroke: ${({ selected, theme }) => (selected ? theme.textPrimary : theme.white)};
|
||||
stroke-width: 2px;
|
||||
}
|
||||
`
|
||||
@@ -228,6 +229,7 @@ export default function SwapCurrencyInputPanel({
|
||||
...rest
|
||||
}: SwapCurrencyInputPanelProps) {
|
||||
const [modalOpen, setModalOpen] = useState(false)
|
||||
const [fiatValueIsLoading, setFiatValueIsLoading] = useState(false)
|
||||
const { account, chainId } = useWeb3React()
|
||||
const selectedCurrencyBalance = useCurrencyBalance(account ?? undefined, currency ?? undefined)
|
||||
const theme = useTheme()
|
||||
@@ -238,6 +240,10 @@ export default function SwapCurrencyInputPanel({
|
||||
|
||||
const chainAllowed = isSupportedChain(chainId)
|
||||
|
||||
useEffect(() => {
|
||||
!!value && !fiatValue ? setFiatValueIsLoading(true) : setFiatValueIsLoading(false)
|
||||
}, [fiatValueIsLoading, value, fiatValue])
|
||||
|
||||
return (
|
||||
<InputPanel id={id} hideInput={hideInput} {...rest}>
|
||||
{locked && (
|
||||
@@ -301,11 +307,11 @@ export default function SwapCurrencyInputPanel({
|
||||
</Aligner>
|
||||
</CurrencySelect>
|
||||
</InputRow>
|
||||
{!hideInput && !hideBalance && currency && (
|
||||
{Boolean(!hideInput && !hideBalance) && (
|
||||
<FiatRow>
|
||||
<RowBetween>
|
||||
<LoadingOpacityContainer $loading={loading}>
|
||||
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
|
||||
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} isLoading={fiatValueIsLoading} />
|
||||
</LoadingOpacityContainer>
|
||||
{account ? (
|
||||
<RowFixed style={{ height: '17px' }}>
|
||||
|
||||
@@ -11,24 +11,25 @@ import { darken } from 'polished'
|
||||
import { ReactNode, useCallback, useState } from 'react'
|
||||
import { Lock } from 'react-feather'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
import { flexColumnNoWrap, flexRowNoWrap } from 'theme/styles'
|
||||
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
|
||||
|
||||
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
|
||||
import { useCurrencyBalance } from '../../state/connection/hooks'
|
||||
import { ThemedText } from '../../theme'
|
||||
import { ButtonGray } from '../Button'
|
||||
import CurrencyLogo from '../CurrencyLogo'
|
||||
import DoubleCurrencyLogo from '../DoubleLogo'
|
||||
import CurrencyLogo from '../Logo/CurrencyLogo'
|
||||
import { Input as NumericalInput } from '../NumericalInput'
|
||||
import { RowBetween, RowFixed } from '../Row'
|
||||
import CurrencySearchModal from '../SearchModal/CurrencySearchModal'
|
||||
import { FiatValue } from './FiatValue'
|
||||
|
||||
const InputPanel = styled.div<{ hideInput?: boolean }>`
|
||||
${({ theme }) => theme.flexColumnNoWrap}
|
||||
${flexColumnNoWrap};
|
||||
position: relative;
|
||||
border-radius: ${({ hideInput }) => (hideInput ? '16px' : '20px')};
|
||||
background-color: ${({ theme, hideInput }) => (hideInput ? 'transparent' : theme.deprecated_bg2)};
|
||||
background-color: ${({ theme, hideInput }) => (hideInput ? 'transparent' : theme.backgroundInteractive)};
|
||||
z-index: 1;
|
||||
width: ${({ hideInput }) => (hideInput ? '100%' : 'initial')};
|
||||
transition: height 1s ease;
|
||||
@@ -40,7 +41,7 @@ const FixedContainer = styled.div`
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
border-radius: 20px;
|
||||
background-color: ${({ theme }) => theme.deprecated_bg2};
|
||||
background-color: ${({ theme }) => theme.backgroundInteractive};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -49,7 +50,7 @@ const FixedContainer = styled.div`
|
||||
|
||||
const Container = styled.div<{ hideInput: boolean; disabled: boolean }>`
|
||||
border-radius: ${({ hideInput }) => (hideInput ? '16px' : '20px')};
|
||||
border: 1px solid ${({ theme }) => theme.deprecated_bg0};
|
||||
border: 1px solid ${({ theme }) => theme.backgroundSurface};
|
||||
background-color: ${({ theme }) => theme.deprecated_bg1};
|
||||
width: ${({ hideInput }) => (hideInput ? '100%' : 'initial')};
|
||||
${({ theme, hideInput, disabled }) =>
|
||||
@@ -69,11 +70,11 @@ const CurrencySelect = styled(ButtonGray)<{
|
||||
disabled?: boolean
|
||||
}>`
|
||||
align-items: center;
|
||||
background-color: ${({ selected, theme }) => (selected ? theme.deprecated_bg2 : theme.deprecated_primary1)};
|
||||
background-color: ${({ selected, theme }) => (selected ? theme.backgroundInteractive : theme.accentAction)};
|
||||
opacity: ${({ disabled }) => (!disabled ? 1 : 0.4)};
|
||||
box-shadow: ${({ selected }) => (selected ? 'none' : '0px 6px 10px rgba(0, 0, 0, 0.075)')};
|
||||
box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075);
|
||||
color: ${({ selected, theme }) => (selected ? theme.deprecated_text1 : theme.deprecated_white)};
|
||||
color: ${({ selected, theme }) => (selected ? theme.textPrimary : theme.white)};
|
||||
cursor: pointer;
|
||||
border-radius: 16px;
|
||||
outline: none;
|
||||
@@ -88,29 +89,28 @@ const CurrencySelect = styled(ButtonGray)<{
|
||||
margin-left: ${({ hideInput }) => (hideInput ? '0' : '12px')};
|
||||
:focus,
|
||||
:hover {
|
||||
background-color: ${({ selected, theme }) =>
|
||||
selected ? theme.deprecated_bg3 : darken(0.05, theme.deprecated_primary1)};
|
||||
background-color: ${({ selected, theme }) => (selected ? theme.deprecated_bg3 : darken(0.05, theme.accentAction))};
|
||||
}
|
||||
visibility: ${({ visible }) => (visible ? 'visible' : 'hidden')};
|
||||
`
|
||||
|
||||
const InputRow = styled.div<{ selected: boolean }>`
|
||||
${({ theme }) => theme.flexRowNoWrap}
|
||||
${flexRowNoWrap};
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: ${({ selected }) => (selected ? ' 1rem 1rem 0.75rem 1rem' : '1rem 1rem 1rem 1rem')};
|
||||
`
|
||||
|
||||
const LabelRow = styled.div`
|
||||
${({ theme }) => theme.flexRowNoWrap}
|
||||
${flexRowNoWrap};
|
||||
align-items: center;
|
||||
color: ${({ theme }) => theme.deprecated_text1};
|
||||
color: ${({ theme }) => theme.textPrimary};
|
||||
font-size: 0.75rem;
|
||||
line-height: 1rem;
|
||||
padding: 0 1rem 1rem;
|
||||
span:hover {
|
||||
cursor: pointer;
|
||||
color: ${({ theme }) => darken(0.2, theme.deprecated_text2)};
|
||||
color: ${({ theme }) => darken(0.2, theme.textSecondary)};
|
||||
}
|
||||
`
|
||||
|
||||
@@ -132,7 +132,7 @@ const StyledDropDown = styled(DropDown)<{ selected: boolean }>`
|
||||
height: 35%;
|
||||
|
||||
path {
|
||||
stroke: ${({ selected, theme }) => (selected ? theme.deprecated_text1 : theme.deprecated_white)};
|
||||
stroke: ${({ selected, theme }) => (selected ? theme.textPrimary : theme.white)};
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
`
|
||||
@@ -147,7 +147,7 @@ const StyledBalanceMax = styled.button<{ disabled?: boolean }>`
|
||||
background-color: ${({ theme }) => theme.deprecated_primary5};
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
color: ${({ theme }) => theme.deprecated_primary1};
|
||||
color: ${({ theme }) => theme.accentAction};
|
||||
cursor: pointer;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
@@ -299,7 +299,7 @@ export default function CurrencyInputPanel({
|
||||
<RowFixed style={{ height: '17px' }}>
|
||||
<ThemedText.DeprecatedBody
|
||||
onClick={onMax}
|
||||
color={theme.deprecated_text3}
|
||||
color={theme.textTertiary}
|
||||
fontWeight={500}
|
||||
fontSize={14}
|
||||
style={{ display: 'inline', cursor: 'pointer' }}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs'
|
||||
import React, { useMemo } from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import Logo from '../Logo'
|
||||
|
||||
const StyledLogo = styled(Logo)<{ 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 black;
|
||||
-webkit-box-shadow: 0 0 1px black;
|
||||
box-shadow: 0 0 1px black;
|
||||
border: 0px solid rgba(255, 255, 255, 0);
|
||||
`
|
||||
|
||||
const StyledNativeLogo = styled(StyledLogo)`
|
||||
-mox-box-shadow: 0 0 1px white;
|
||||
-webkit-box-shadow: 0 0 1px white;
|
||||
box-shadow: 0 0 1px white;
|
||||
`
|
||||
|
||||
export default function CurrencyLogo({
|
||||
currency,
|
||||
symbol,
|
||||
size = '24px',
|
||||
style,
|
||||
src,
|
||||
...rest
|
||||
}: {
|
||||
currency?: Currency | null
|
||||
symbol?: string | null
|
||||
size?: string
|
||||
style?: React.CSSProperties
|
||||
src?: string | null
|
||||
}) {
|
||||
const logoURIs = useCurrencyLogoURIs(currency)
|
||||
const srcs = useMemo(() => (src ? [src, ...logoURIs] : logoURIs), [src, logoURIs])
|
||||
const props = {
|
||||
alt: `${currency?.symbol ?? 'token'} logo`,
|
||||
size,
|
||||
srcs,
|
||||
symbol: symbol ?? currency?.symbol,
|
||||
style,
|
||||
...rest,
|
||||
}
|
||||
|
||||
return currency?.isNative ? <StyledNativeLogo {...props} /> : <StyledLogo {...props} />
|
||||
}
|
||||