diff --git a/.nvmrc b/.nvmrc index a5e323e..ff65059 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v14.17.3 +v16.13.0 diff --git a/Dockerfile b/Dockerfile index aec42e4..0d910e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,4 @@ -FROM node:14.17.3-alpine3.14 AS builder -RUN npm i -g npm@7.19.1 +FROM node:16.13.0-alpine3.14 AS builder WORKDIR /otterscan-build COPY ["package.json", "package-lock.json", "/otterscan-build/"] RUN npm install diff --git a/nginx/conf.d/default.conf b/nginx/conf.d/default.conf index b5d141b..4fdf9a1 100644 --- a/nginx/conf.d/default.conf +++ b/nginx/conf.d/default.conf @@ -118,7 +118,7 @@ server { index index.html; try_files $uri /index.html; - brotli_static on; + # brotli_static on; } #error_page 404 /404.html; diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 7364514..72d7924 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -4,7 +4,7 @@ worker_processes auto; error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; -load_module modules/ngx_http_brotli_static_module.so; +#load_module modules/ngx_http_brotli_static_module.so; events { worker_connections 1024; diff --git a/package-lock.json b/package-lock.json index ef51571..d3f7ea8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@blackbox-vision/react-qr-reader": "^5.0.0", "@chainlink/contracts": "^0.2.2", "@craco/craco": "^6.4.0", - "@fontsource/fira-code": "^4.5.1", + "@fontsource/fira-code": "^4.5.2", "@fontsource/roboto": "^4.5.1", "@fontsource/roboto-mono": "^4.5.0", "@fontsource/space-grotesk": "^4.5.0", @@ -21,21 +21,21 @@ "@fortawesome/free-regular-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.16", - "@headlessui/react": "^1.4.1", - "@testing-library/jest-dom": "^5.14.1", + "@headlessui/react": "^1.4.2", + "@testing-library/jest-dom": "^5.15.0", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.24", "@types/node": "^14.17.5", - "@types/react": "^17.0.33", + "@types/react": "^17.0.35", "@types/react-blockies": "^1.4.1", - "@types/react-dom": "^17.0.10", + "@types/react-dom": "^17.0.11", "@types/react-highlight": "^0.12.5", "@types/react-router-dom": "^5.3.2", "@types/react-syntax-highlighter": "^13.5.2", "chart.js": "^3.5.1", "ethers": "^5.5.1", - "highlightjs-solidity": "^2.0.1", + "highlightjs-solidity": "^2.0.2", "query-string": "^7.0.1", "react": "^17.0.2", "react-blockies": "^1.4.1", @@ -46,8 +46,8 @@ "react-image": "^4.0.3", "react-router-dom": "^5.3.0", "react-scripts": "4.0.3", - "react-syntax-highlighter": "^15.4.4", - "serve": "^12.0.1", + "react-syntax-highlighter": "^15.4.5", + "serve": "^13.0.2", "typescript": "^4.4.4", "use-keyboard-shortcut": "^1.0.6", "web-vitals": "^1.0.1" @@ -2049,9 +2049,9 @@ } }, "node_modules/@fontsource/fira-code": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.5.1.tgz", - "integrity": "sha512-8KTCsfs5m3UgICpHLglIKAS7vc2FFOu7/vvpWcE/42SWbh+9X8EJbEyJp6W96kU5iDVlAlUv4Cqc36Z9XUpLmA==" + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.5.2.tgz", + "integrity": "sha512-wNUvcqmm1dZYTbJlkbFZL9Huu7p+Hwaa4CLNTPql3CG90Rh9dSi43wNg5AnVHxjAhWQOGlCpSrEswnnHu1CkxA==" }, "node_modules/@fontsource/roboto": { "version": "4.5.1", @@ -2167,9 +2167,9 @@ } }, "node_modules/@headlessui/react": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.1.tgz", - "integrity": "sha512-gL6Ns5xQM57cZBzX6IVv6L7nsam8rDEpRhs5fg28SN64ikfmuuMgunc+Rw5C1cMScnvFM+cz32ueVrlSFEVlSg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.2.tgz", + "integrity": "sha512-N8tv7kLhg9qGKBkVdtg572BvKvWhmiudmeEpOCyNwzOsZHCXBtl8AazGikIfUS+vBoub20Fse3BjawXDVPPdug==", "engines": { "node": ">=10" }, @@ -2887,9 +2887,9 @@ } }, "node_modules/@testing-library/jest-dom": { - "version": "5.14.1", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.14.1.tgz", - "integrity": "sha512-dfB7HVIgTNCxH22M1+KU6viG5of2ldoA5ly8Ar8xkezKHKXjRvznCdbMbqjYGgO2xjRbwnR+rR8MLUIqF3kKbQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.15.0.tgz", + "integrity": "sha512-lOMuQidnL1tWHLEWIhL6UvSZC1Qt3OkNe1khvi2h6xFiqpe5O8arYs46OU0qyUGq0cSTbroQyMktYNXu3a7sAA==", "dependencies": { "@babel/runtime": "^7.9.2", "@types/testing-library__jest-dom": "^5.9.1", @@ -3127,9 +3127,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.33.tgz", - "integrity": "sha512-pLWntxXpDPaU+RTAuSGWGSEL2FRTNyRQOjSWDke/rxRg14ncsZvx8AKWMWZqvc1UOaJIAoObdZhAWvRaHFi5rw==", + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.35.tgz", + "integrity": "sha512-r3C8/TJuri/SLZiiwwxQoLAoavaczARfT9up9b4Jr65+ErAUX3MIkU0oMOQnrpfgHme8zIqZLX7O5nnjm5Wayw==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -3145,9 +3145,9 @@ } }, "node_modules/@types/react-dom": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.10.tgz", - "integrity": "sha512-8oz3NAUId2z/zQdFI09IMhQPNgIbiP8Lslhv39DIDamr846/0spjZK0vnrMak0iB8EKb9QFTTIdg2Wj2zH5a3g==", + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", + "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", "dependencies": { "@types/react": "*" } @@ -3752,50 +3752,11 @@ "license": "MIT" }, "node_modules/ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dependencies": { - "string-width": "^2.0.0" - } - }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" + "string-width": "^4.1.0" } }, "node_modules/ansi-colors": { @@ -3839,8 +3800,9 @@ } }, "node_modules/ansi-regex": { - "version": "5.0.0", - "license": "MIT", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { "node": ">=8" } @@ -5145,110 +5107,62 @@ "license": "ISC" }, "node_modules/boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", "dependencies": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/boxen/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "engines": { - "node": ">=4" - } - }, - "node_modules/boxen/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" + "node": ">=10" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/boxen/node_modules/camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/boxen/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/boxen/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/boxen/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/boxen/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "node": ">=10" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/boxen/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/boxen/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/brace-expansion": { @@ -5818,11 +5732,14 @@ } }, "node_modules/cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/clipboardy": { @@ -9366,9 +9283,9 @@ } }, "node_modules/highlightjs-solidity": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/highlightjs-solidity/-/highlightjs-solidity-2.0.1.tgz", - "integrity": "sha512-9YY+HQpXMTrF8HgRByjeQhd21GXAz2ktMPTcs6oWSj5HJR52fgsNoelMOmgigwcpt9j4tu4IVSaWaJB2n2TbvQ==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/highlightjs-solidity/-/highlightjs-solidity-2.0.2.tgz", + "integrity": "sha512-q0aYUKiZ9MPQg41qx/KpXKaCpqql50qTvmwGYyLFfcjt9AE/+C9CwjVIdJZc7EYj6NGgJuFJ4im1gfgrzUU1fQ==" }, "node_modules/history": { "version": "4.10.1", @@ -14188,11 +14105,6 @@ "version": "1.0.1", "license": "MIT" }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, "node_modules/psl": { "version": "1.8.0", "license": "MIT" @@ -15008,20 +14920,25 @@ } }, "node_modules/react-syntax-highlighter": { - "version": "15.4.4", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.4.4.tgz", - "integrity": "sha512-PsOFHNTzkb3OroXdoR897eKN5EZ6grht1iM+f1lJSq7/L0YVnkJaNVwC3wEUYPOAmeyl5xyer1DjL6MrumO6Zw==", + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.4.5.tgz", + "integrity": "sha512-RC90KQTxZ/b7+9iE6s9nmiFLFjWswUcfULi4GwVzdFVKVMQySkJWBuOmJFfjwjMVCo0IUUuJrWebNKyviKpwLQ==", "dependencies": { "@babel/runtime": "^7.3.1", "highlight.js": "^10.4.1", "lowlight": "^1.17.0", - "prismjs": "^1.22.0", + "prismjs": "^1.25.0", "refractor": "^3.2.0" }, "peerDependencies": { "react": ">= 0.14.0" } }, + "node_modules/react-syntax-highlighter/node_modules/prismjs": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz", + "integrity": "sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==" + }, "node_modules/read-pkg": { "version": "5.2.0", "license": "MIT", @@ -16100,14 +16017,14 @@ } }, "node_modules/serve": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/serve/-/serve-12.0.1.tgz", - "integrity": "sha512-CQ4ikLpxg/wmNM7yivulpS6fhjRiFG6OjmP8ty3/c1SBnSk23fpKmLAV4HboTA2KrZhkUPlDfjDhnRmAjQ5Phw==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/serve/-/serve-13.0.2.tgz", + "integrity": "sha512-71R6fKvNgKrqARAag6lYJNnxDzpH7DCNrMuvPY5PLVaC2PDhJsGTj/34o4o4tPWhTuLgEXqvgnAWbATQ9zGZTQ==", "dependencies": { "@zeit/schemas": "2.6.0", "ajv": "6.12.6", "arg": "2.0.0", - "boxen": "1.3.0", + "boxen": "5.1.2", "chalk": "2.4.1", "clipboardy": "2.3.0", "compression": "1.7.3", @@ -16983,12 +16900,24 @@ "license": "MIT" }, "node_modules/string-width": { - "version": "4.2.0", - "license": "MIT", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" @@ -17742,85 +17671,6 @@ "node": ">=6" } }, - "node_modules/term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "dependencies": { - "execa": "^0.7.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/term-size/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "node_modules/term-size/node_modules/execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/term-size/node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "engines": { - "node": ">=4" - } - }, - "node_modules/term-size/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/term-size/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/term-size/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/term-size/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, "node_modules/terminal-link": { "version": "2.1.1", "license": "MIT", @@ -19444,53 +19294,14 @@ "license": "ISC" }, "node_modules/widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "dependencies": { - "string-width": "^2.1.1" + "string-width": "^4.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/widest-line/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "engines": { - "node": ">=4" - } - }, - "node_modules/widest-line/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/widest-line/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/widest-line/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/word-wrap": { @@ -21089,9 +20900,9 @@ } }, "@fontsource/fira-code": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.5.1.tgz", - "integrity": "sha512-8KTCsfs5m3UgICpHLglIKAS7vc2FFOu7/vvpWcE/42SWbh+9X8EJbEyJp6W96kU5iDVlAlUv4Cqc36Z9XUpLmA==" + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.5.2.tgz", + "integrity": "sha512-wNUvcqmm1dZYTbJlkbFZL9Huu7p+Hwaa4CLNTPql3CG90Rh9dSi43wNg5AnVHxjAhWQOGlCpSrEswnnHu1CkxA==" }, "@fontsource/roboto": { "version": "4.5.1", @@ -21178,9 +20989,9 @@ } }, "@headlessui/react": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.1.tgz", - "integrity": "sha512-gL6Ns5xQM57cZBzX6IVv6L7nsam8rDEpRhs5fg28SN64ikfmuuMgunc+Rw5C1cMScnvFM+cz32ueVrlSFEVlSg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.2.tgz", + "integrity": "sha512-N8tv7kLhg9qGKBkVdtg572BvKvWhmiudmeEpOCyNwzOsZHCXBtl8AazGikIfUS+vBoub20Fse3BjawXDVPPdug==", "requires": {} }, "@istanbuljs/load-nyc-config": { @@ -21609,9 +21420,9 @@ } }, "@testing-library/jest-dom": { - "version": "5.14.1", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.14.1.tgz", - "integrity": "sha512-dfB7HVIgTNCxH22M1+KU6viG5of2ldoA5ly8Ar8xkezKHKXjRvznCdbMbqjYGgO2xjRbwnR+rR8MLUIqF3kKbQ==", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.15.0.tgz", + "integrity": "sha512-lOMuQidnL1tWHLEWIhL6UvSZC1Qt3OkNe1khvi2h6xFiqpe5O8arYs46OU0qyUGq0cSTbroQyMktYNXu3a7sAA==", "requires": { "@babel/runtime": "^7.9.2", "@types/testing-library__jest-dom": "^5.9.1", @@ -21796,9 +21607,9 @@ "version": "1.5.4" }, "@types/react": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.33.tgz", - "integrity": "sha512-pLWntxXpDPaU+RTAuSGWGSEL2FRTNyRQOjSWDke/rxRg14ncsZvx8AKWMWZqvc1UOaJIAoObdZhAWvRaHFi5rw==", + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.35.tgz", + "integrity": "sha512-r3C8/TJuri/SLZiiwwxQoLAoavaczARfT9up9b4Jr65+ErAUX3MIkU0oMOQnrpfgHme8zIqZLX7O5nnjm5Wayw==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -21814,9 +21625,9 @@ } }, "@types/react-dom": { - "version": "17.0.10", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.10.tgz", - "integrity": "sha512-8oz3NAUId2z/zQdFI09IMhQPNgIbiP8Lslhv39DIDamr846/0spjZK0vnrMak0iB8EKb9QFTTIdg2Wj2zH5a3g==", + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.11.tgz", + "integrity": "sha512-f96K3k+24RaLGVu/Y2Ng3e1EbZ8/cVJvypZWd7cy0ofCBaf2lcM46xNhycMZ2xGwbBjRql7hOlZ+e2WlJ5MH3Q==", "requires": { "@types/react": "*" } @@ -22243,40 +22054,11 @@ "version": "1.0.2" }, "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "requires": { - "string-width": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } + "string-width": "^4.1.0" } }, "ansi-colors": { @@ -22297,7 +22079,9 @@ "version": "0.0.7" }, "ansi-regex": { - "version": "5.0.0" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", @@ -23212,80 +22996,38 @@ "version": "1.0.0" }, "boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } } } @@ -23684,9 +23426,9 @@ "version": "2.2.0" }, "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" }, "clipboardy": { "version": "2.3.0", @@ -26043,9 +25785,9 @@ "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" }, "highlightjs-solidity": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/highlightjs-solidity/-/highlightjs-solidity-2.0.1.tgz", - "integrity": "sha512-9YY+HQpXMTrF8HgRByjeQhd21GXAz2ktMPTcs6oWSj5HJR52fgsNoelMOmgigwcpt9j4tu4IVSaWaJB2n2TbvQ==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/highlightjs-solidity/-/highlightjs-solidity-2.0.2.tgz", + "integrity": "sha512-q0aYUKiZ9MPQg41qx/KpXKaCpqql50qTvmwGYyLFfcjt9AE/+C9CwjVIdJZc7EYj6NGgJuFJ4im1gfgrzUU1fQ==" }, "history": { "version": "4.10.1", @@ -29246,11 +28988,6 @@ "prr": { "version": "1.0.1" }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, "psl": { "version": "1.8.0" }, @@ -29815,15 +29552,22 @@ } }, "react-syntax-highlighter": { - "version": "15.4.4", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.4.4.tgz", - "integrity": "sha512-PsOFHNTzkb3OroXdoR897eKN5EZ6grht1iM+f1lJSq7/L0YVnkJaNVwC3wEUYPOAmeyl5xyer1DjL6MrumO6Zw==", + "version": "15.4.5", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.4.5.tgz", + "integrity": "sha512-RC90KQTxZ/b7+9iE6s9nmiFLFjWswUcfULi4GwVzdFVKVMQySkJWBuOmJFfjwjMVCo0IUUuJrWebNKyviKpwLQ==", "requires": { "@babel/runtime": "^7.3.1", "highlight.js": "^10.4.1", "lowlight": "^1.17.0", - "prismjs": "^1.22.0", + "prismjs": "^1.25.0", "refractor": "^3.2.0" + }, + "dependencies": { + "prismjs": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz", + "integrity": "sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==" + } } }, "read-pkg": { @@ -30541,14 +30285,14 @@ } }, "serve": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/serve/-/serve-12.0.1.tgz", - "integrity": "sha512-CQ4ikLpxg/wmNM7yivulpS6fhjRiFG6OjmP8ty3/c1SBnSk23fpKmLAV4HboTA2KrZhkUPlDfjDhnRmAjQ5Phw==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/serve/-/serve-13.0.2.tgz", + "integrity": "sha512-71R6fKvNgKrqARAag6lYJNnxDzpH7DCNrMuvPY5PLVaC2PDhJsGTj/34o4o4tPWhTuLgEXqvgnAWbATQ9zGZTQ==", "requires": { "@zeit/schemas": "2.6.0", "ajv": "6.12.6", "arg": "2.0.0", - "boxen": "1.3.0", + "boxen": "5.1.2", "chalk": "2.4.1", "clipboardy": "2.3.0", "compression": "1.7.3", @@ -31203,11 +30947,23 @@ "version": "3.0.1" }, "string-width": { - "version": "4.2.0", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } } }, "string.prototype.matchall": { @@ -31730,72 +31486,6 @@ } } }, - "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "requires": { - "execa": "^0.7.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - } - } - }, "terminal-link": { "version": "2.1.1", "requires": { @@ -32868,40 +32558,11 @@ "version": "2.0.0" }, "widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "requires": { - "string-width": "^2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } + "string-width": "^4.0.0" } }, "word-wrap": { diff --git a/package.json b/package.json index d301e67..386cded 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "@blackbox-vision/react-qr-reader": "^5.0.0", "@chainlink/contracts": "^0.2.2", "@craco/craco": "^6.4.0", - "@fontsource/fira-code": "^4.5.1", + "@fontsource/fira-code": "^4.5.2", "@fontsource/roboto": "^4.5.1", "@fontsource/roboto-mono": "^4.5.0", "@fontsource/space-grotesk": "^4.5.0", @@ -16,21 +16,21 @@ "@fortawesome/free-regular-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.16", - "@headlessui/react": "^1.4.1", - "@testing-library/jest-dom": "^5.14.1", + "@headlessui/react": "^1.4.2", + "@testing-library/jest-dom": "^5.15.0", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.24", "@types/node": "^14.17.5", - "@types/react": "^17.0.33", + "@types/react": "^17.0.35", "@types/react-blockies": "^1.4.1", - "@types/react-dom": "^17.0.10", + "@types/react-dom": "^17.0.11", "@types/react-highlight": "^0.12.5", "@types/react-router-dom": "^5.3.2", "@types/react-syntax-highlighter": "^13.5.2", "chart.js": "^3.5.1", "ethers": "^5.5.1", - "highlightjs-solidity": "^2.0.1", + "highlightjs-solidity": "^2.0.2", "query-string": "^7.0.1", "react": "^17.0.2", "react-blockies": "^1.4.1", @@ -41,8 +41,8 @@ "react-image": "^4.0.3", "react-router-dom": "^5.3.0", "react-scripts": "4.0.3", - "react-syntax-highlighter": "^15.4.4", - "serve": "^12.0.1", + "react-syntax-highlighter": "^15.4.5", + "serve": "^13.0.2", "typescript": "^4.4.4", "use-keyboard-shortcut": "^1.0.6", "web-vitals": "^1.0.1" diff --git a/src/AddressTransactions.tsx b/src/AddressTransactions.tsx index 19d41bb..a1013c8 100644 --- a/src/AddressTransactions.tsx +++ b/src/AddressTransactions.tsx @@ -31,7 +31,8 @@ import { useFeeToggler } from "./search/useFeeToggler"; import { SelectionContext, useSelection } from "./useSelection"; import { useMultipleETHUSDOracle } from "./usePriceOracle"; import { useAppConfigContext } from "./useAppConfig"; -import { useSourcify } from "./useSourcify"; +import { useMultipleMetadata } from "./useSourcify"; +import { ChecksummedAddress } from "./types"; import SourcifyLogo from "./sourcify.svg"; type BlockParams = { @@ -181,12 +182,31 @@ const AddressTransactions: React.FC = () => { const [feeDisplay, feeDisplayToggler] = useFeeToggler(); const selectionCtx = useSelection(); + const addresses = useMemo(() => { + const _addresses: ChecksummedAddress[] = []; + if (checksummedAddress) { + _addresses.push(checksummedAddress); + } + if (page) { + for (const t of page) { + if (t.to) { + _addresses.push(t.to); + } + } + } + return _addresses; + }, [checksummedAddress, page]); const { sourcifySource } = useAppConfigContext(); - const rawMetadata = useSourcify( - checksummedAddress, + const metadatas = useMultipleMetadata( + undefined, + addresses, provider?.network.chainId, sourcifySource ); + const addressMetadata = + checksummedAddress !== undefined + ? metadatas[checksummedAddress] + : undefined; return ( @@ -224,18 +244,18 @@ const AddressTransactions: React.FC = () => { Contract - {rawMetadata === undefined ? ( + {addressMetadata === undefined ? ( - ) : rawMetadata === null ? ( + ) : addressMetadata === null ? ( @@ -288,6 +308,7 @@ const AddressTransactions: React.FC = () => { selectedAddress={checksummedAddress} feeDisplay={feeDisplay} priceMap={priceMap} + metadatas={metadatas} /> ))}
@@ -316,7 +337,7 @@ const AddressTransactions: React.FC = () => { diff --git a/src/TokenTransferItem.tsx b/src/TokenTransferItem.tsx index 03fa198..c56bc26 100644 --- a/src/TokenTransferItem.tsx +++ b/src/TokenTransferItem.tsx @@ -1,31 +1,31 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCaretRight } from "@fortawesome/free-solid-svg-icons/faCaretRight"; -import AddressHighlighter from "./components/AddressHighlighter"; +import TransactionAddress from "./components/TransactionAddress"; import ValueHighlighter from "./components/ValueHighlighter"; -import DecoratedAddressLink from "./components/DecoratedAddressLink"; import FormattedBalance from "./components/FormattedBalance"; import { AddressContext, + ChecksummedAddress, TokenMeta, TokenTransfer, - TransactionData, } from "./types"; import { ResolvedAddresses } from "./api/address-resolver"; +import { Metadata } from "./useSourcify"; type TokenTransferItemProps = { t: TokenTransfer; - txData: TransactionData; - tokenMeta?: TokenMeta | undefined; + tokenMeta?: TokenMeta | null | undefined; resolvedAddresses: ResolvedAddresses | undefined; + metadatas: Record; }; // TODO: handle partial const TokenTransferItem: React.FC = ({ t, - txData, tokenMeta, resolvedAddresses, + metadatas, }) => (
@@ -34,25 +34,21 @@ const TokenTransferItem: React.FC = ({
From - - - +
To - - - +
For @@ -64,12 +60,11 @@ const TokenTransferItem: React.FC = ({ /> - - - +
diff --git a/src/Transaction.tsx b/src/Transaction.tsx index 7107b32..168c83f 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -15,6 +15,7 @@ import { transactionDataCollector, useResolvedAddresses, } from "./useResolvedAddresses"; +import { SelectedTransactionContext } from "./useSelectedTransaction"; const Details = React.lazy( () => @@ -29,6 +30,12 @@ const Logs = React.lazy( /* webpackChunkName: "txlogs", webpackPrefetch: true */ "./transaction/Logs" ) ); +const Trace = React.lazy( + () => + import( + /* webpackChunkName: "txtrace", webpackPrefetch: true */ "./transaction/Trace" + ) +); type TransactionParams = { txhash: string; @@ -76,54 +83,63 @@ const Transaction: React.FC = () => { const txDesc = useTransactionDescription(metadata, txData); return ( - - Transaction Details - {txData === null && ( - -
- Transaction {txhash} not found. -
-
- )} - {txData && ( - - - - Overview - {txData.confirmedData?.blockNumber !== undefined && ( - - Logs - {txData && ` (${txData.confirmedData?.logs?.length ?? 0})`} - - )} - - - - - -
- - - - - - - - )} - + + + Transaction Details + {txData === null && ( + +
+ Transaction {txhash} not found. +
+
+ )} + {txData && ( + + + + Overview + {txData.confirmedData?.blockNumber !== undefined && ( + + Logs + {txData && ` (${txData.confirmedData?.logs?.length ?? 0})`} + + )} + Trace + + + + + +
+ + + + + + + + + + + )} + + ); }; diff --git a/src/api/address-resolver/ERCTokenResolver.ts b/src/api/address-resolver/ERCTokenResolver.ts index 02625dc..f087ec6 100644 --- a/src/api/address-resolver/ERCTokenResolver.ts +++ b/src/api/address-resolver/ERCTokenResolver.ts @@ -11,11 +11,17 @@ export class ERCTokenResolver implements IAddressResolver { ): Promise { const erc20Contract = new Contract(address, erc20, provider); try { - const [name, symbol, decimals] = await Promise.all([ + const [name, symbol, decimals] = (await Promise.all([ erc20Contract.name(), erc20Contract.symbol(), erc20Contract.decimals(), - ]); + ])) as [string, string, number]; + + // Prevent faulty tokens with empty name/symbol + if (!name.trim() || !symbol.trim()) { + return undefined; + } + return { name, symbol, diff --git a/src/api/address-resolver/HardcodedAddressResolver.ts b/src/api/address-resolver/HardcodedAddressResolver.ts new file mode 100644 index 0000000..42d1102 --- /dev/null +++ b/src/api/address-resolver/HardcodedAddressResolver.ts @@ -0,0 +1,22 @@ +import { BaseProvider } from "@ethersproject/providers"; +import { IAddressResolver } from "./address-resolver"; + +type HardcodedAddressMap = Record; + +export class HardcodedAddressResolver implements IAddressResolver { + async resolveAddress( + provider: BaseProvider, + address: string + ): Promise { + try { + const addressMap: HardcodedAddressMap = await import( + `./hardcoded-addresses/${provider.network.chainId}.json` + ); + + return addressMap[address]; + } catch (err) { + // Ignore on purpose + return undefined; + } + } +} diff --git a/src/api/address-resolver/hardcoded-addresses/1.json b/src/api/address-resolver/hardcoded-addresses/1.json new file mode 100644 index 0000000..072a2c0 --- /dev/null +++ b/src/api/address-resolver/hardcoded-addresses/1.json @@ -0,0 +1,13 @@ +{ + "0x7d655c57f71464B6f83811C55D84009Cd9f5221C": "Gitcoin: Bulk Checkout", + "0xf2354570bE2fB420832Fb7Ff6ff0AE0dF80CF2c6": "Gitcoin: GR8 Matching Payout", + "0x3342E3737732D879743f2682A3953a730ae4F47C": "Gitcoin: GR9 Matching Payout", + "0x3ebAFfe01513164e638480404c651E885cCA0AA4": "Gitcoin: GR10 Matching Payout", + "0x0EbD2E2130b73107d0C45fF2E16c93E7e2e10e3a": "Gitcoin: GR11 Matching Payout", + "0x722122dF12D4e14e13Ac3b6895a86e84145b6967": "Tornado Cash: Proxy", + "0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95": "Uniswap V1: Factory", + "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f": "Uniswap V2: Factory", + "0xf164fC0Ec4E93095b804a4795bBe1e041497b92a": "Uniswap V2: Router 1", + "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D": "Uniswap V2: Router 2", + "0x1F98431c8aD98523631AE4a59f267346ea31F984": "Uniswap V3: Router" +} \ No newline at end of file diff --git a/src/api/address-resolver/index.ts b/src/api/address-resolver/index.ts index dc72a9f..f1514be 100644 --- a/src/api/address-resolver/index.ts +++ b/src/api/address-resolver/index.ts @@ -1,5 +1,6 @@ import { BaseProvider } from "@ethersproject/providers"; import { ensRenderer } from "../../components/ENSName"; +import { plainStringRenderer } from "../../components/PlainString"; import { tokenRenderer } from "../../components/TokenName"; import { IAddressResolver, ResolvedAddressRenderer } from "./address-resolver"; import { @@ -8,16 +9,19 @@ import { } from "./CompositeAddressResolver"; import { ENSAddressResolver } from "./ENSAddressResolver"; import { ERCTokenResolver } from "./ERCTokenResolver"; +import { HardcodedAddressResolver } from "./HardcodedAddressResolver"; export type ResolvedAddresses = Record>; // Create and configure the main resolver export const ensResolver = new ENSAddressResolver(); export const ercTokenResolver = new ERCTokenResolver(); +export const hardcodedResolver = new HardcodedAddressResolver(); const _mainResolver = new CompositeAddressResolver(); _mainResolver.addResolver(ensResolver); _mainResolver.addResolver(ercTokenResolver); +_mainResolver.addResolver(hardcodedResolver); export const mainResolver: IAddressResolver> = _mainResolver; @@ -28,6 +32,7 @@ export const resolverRendererRegistry = new Map< >(); resolverRendererRegistry.set(ensResolver, ensRenderer); resolverRendererRegistry.set(ercTokenResolver, tokenRenderer); +resolverRendererRegistry.set(hardcodedResolver, plainStringRenderer); // TODO: implement progressive resolving export const batchPopulate = async ( diff --git a/src/block/BlockTransactionResults.tsx b/src/block/BlockTransactionResults.tsx index f9cfc27..969e4a4 100644 --- a/src/block/BlockTransactionResults.tsx +++ b/src/block/BlockTransactionResults.tsx @@ -9,9 +9,11 @@ import { useFeeToggler } from "../search/useFeeToggler"; import { RuntimeContext } from "../useRuntime"; import { SelectionContext, useSelection } from "../useSelection"; import { pageCollector, useResolvedAddresses } from "../useResolvedAddresses"; -import { ProcessedTransaction } from "../types"; +import { ChecksummedAddress, ProcessedTransaction } from "../types"; import { PAGE_SIZE } from "../params"; import { useMultipleETHUSDOracle } from "../usePriceOracle"; +import { useAppConfigContext } from "../useAppConfig"; +import { useMultipleMetadata } from "../useSourcify"; type BlockTransactionResultsProps = { blockTag: BlockTag; @@ -34,6 +36,21 @@ const BlockTransactionResults: React.FC = ({ const blockTags = useMemo(() => [blockTag], [blockTag]); const priceMap = useMultipleETHUSDOracle(provider, blockTags); + const addresses = useMemo((): ChecksummedAddress[] => { + if (!page) { + return []; + } + + return page.map((t) => t.to).filter((to): to is string => to !== undefined); + }, [page]); + const { sourcifySource } = useAppConfigContext(); + const metadatas = useMultipleMetadata( + undefined, + addresses, + provider?.network.chainId, + sourcifySource + ); + return (
@@ -63,6 +80,7 @@ const BlockTransactionResults: React.FC = ({ resolvedAddresses={resolvedAddresses} feeDisplay={feeDisplay} priceMap={priceMap} + metadatas={metadatas} /> ))}
diff --git a/src/components/AddressHighlighter.tsx b/src/components/AddressHighlighter.tsx index e8078d6..9c2c4c3 100644 --- a/src/components/AddressHighlighter.tsx +++ b/src/components/AddressHighlighter.tsx @@ -1,40 +1,22 @@ -import React, { useMemo } from "react"; -import { useSelectionContext } from "../useSelection"; +import React from "react"; +import SelectionHighlighter, { addressSelector } from "./SelectionHighlighter"; type AddressHighlighterProps = React.PropsWithChildren<{ address: string; }>; +// TODO: replace all occurences with SelectionHighlighter and remove this component const AddressHighlighter: React.FC = ({ address, children, -}) => { - const [selection, setSelection] = useSelectionContext(); - const [select, deselect] = useMemo(() => { - const _select = () => { - setSelection({ type: "address", content: address }); - }; - const _deselect = () => { - setSelection(null); - }; - return [_select, _deselect]; - }, [setSelection, address]); +}) => ( + + {children} + +); - return ( -
- {children} -
- ); -}; - -export default React.memo(AddressHighlighter); +export default AddressHighlighter; diff --git a/src/components/AddressLink.tsx b/src/components/AddressLink.tsx new file mode 100644 index 0000000..4b6f99e --- /dev/null +++ b/src/components/AddressLink.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import { NavLink } from "react-router-dom"; + +type AddressLinkProps = { + address: string; + text?: string; + dontOverrideColors?: boolean; +}; + +const AddressLink: React.FC = ({ + address, + text, + dontOverrideColors, +}) => ( + + + {text ?? address} + + +); + +export default AddressLink; diff --git a/src/components/DecoratedAddressLink.tsx b/src/components/DecoratedAddressLink.tsx index cadc77f..333e1ff 100644 --- a/src/components/DecoratedAddressLink.tsx +++ b/src/components/DecoratedAddressLink.tsx @@ -1,4 +1,5 @@ import React from "react"; +import { NavLink } from "react-router-dom"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faStar } from "@fortawesome/free-solid-svg-icons/faStar"; import { faBomb } from "@fortawesome/free-solid-svg-icons/faBomb"; @@ -8,6 +9,8 @@ import { faCoins } from "@fortawesome/free-solid-svg-icons/faCoins"; import AddressOrENSName from "./AddressOrENSName"; import { AddressContext, ZERO_ADDRESS } from "../types"; import { ResolvedAddresses } from "../api/address-resolver"; +import { Metadata } from "../useSourcify"; +import SourcifyLogo from "../sourcify.svg"; type DecoratedAddressLinkProps = { address: string; @@ -19,6 +22,7 @@ type DecoratedAddressLinkProps = { txFrom?: boolean; txTo?: boolean; resolvedAddresses?: ResolvedAddresses | undefined; + metadata?: Metadata | null | undefined; }; const DecoratedAddressLink: React.FC = ({ @@ -31,6 +35,7 @@ const DecoratedAddressLink: React.FC = ({ txFrom, txTo, resolvedAddresses, + metadata, }) => { const mint = addressCtx === AddressContext.FROM && address === ZERO_ADDRESS; const burn = addressCtx === AddressContext.TO && address === ZERO_ADDRESS; @@ -70,6 +75,20 @@ const DecoratedAddressLink: React.FC = ({ )} + {metadata && ( + + Sourcify logo + + )} = ({ + name, + address, + dontOverrideColors, +}) => ( + + ENS Logo + {name} + +); + +export default ENSNameLink; diff --git a/src/components/InternalCreate.tsx b/src/components/InternalCreate.tsx index 7a723ce..e086e9d 100644 --- a/src/components/InternalCreate.tsx +++ b/src/components/InternalCreate.tsx @@ -1,45 +1,44 @@ import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faAngleRight } from "@fortawesome/free-solid-svg-icons/faAngleRight"; +import TransactionAddress from "./TransactionAddress"; import AddressHighlighter from "./AddressHighlighter"; import DecoratedAddressLink from "./DecoratedAddressLink"; -import { TransactionData, InternalOperation } from "../types"; +import { InternalOperation } from "../types"; +import { ResolvedAddresses } from "../api/address-resolver"; type InternalCreateProps = { - txData: TransactionData; internalOp: InternalOperation; + resolvedAddresses: ResolvedAddresses | undefined; }; const InternalCreate: React.FC = ({ - txData, internalOp, -}) => { - return ( - <> -
- - CREATE - - Contract -
- - - -
- - (Creator:{" "} - - - - ) - -
- - ); -}; + resolvedAddresses, +}) => ( +
+ + CREATE + + Contract +
+ + + +
+ + (Creator:{" "} + + ) + +
+); -export default React.memo(InternalCreate); +export default InternalCreate; diff --git a/src/components/InternalSelfDestruct.tsx b/src/components/InternalSelfDestruct.tsx index 007fb32..794b987 100644 --- a/src/components/InternalSelfDestruct.tsx +++ b/src/components/InternalSelfDestruct.tsx @@ -1,52 +1,57 @@ -import React, { useContext } from "react"; +import React from "react"; import { formatEther } from "@ethersproject/units"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faAngleRight } from "@fortawesome/free-solid-svg-icons/faAngleRight"; import AddressHighlighter from "./AddressHighlighter"; import DecoratedAddressLink from "./DecoratedAddressLink"; -import { RuntimeContext } from "../useRuntime"; import { TransactionData, InternalOperation } from "../types"; - -const CHI_ADDRESS = "0x0000000000004946c0e9F43F4Dee607b0eF1fA1c"; -const GST2_ADDRESS = "0x0000000000b3F879cb30FE243b4Dfee438691c04"; +import { ResolvedAddresses } from "../api/address-resolver"; +import TransactionAddress from "./TransactionAddress"; type InternalSelfDestructProps = { txData: TransactionData; internalOp: InternalOperation; + resolvedAddresses: ResolvedAddresses | undefined; }; const InternalSelfDestruct: React.FC = ({ txData, internalOp, + resolvedAddresses, }) => { - const { provider } = useContext(RuntimeContext); - const network = provider?.network; - const toMiner = txData.confirmedData?.miner !== undefined && internalOp.to === txData.confirmedData.miner; return ( <> -
+
SELF DESTRUCT Contract
- +
- {network?.chainId === 1 && internalOp.to === CHI_ADDRESS && ( - (Chi Gastoken) - )} - {network?.chainId === 1 && internalOp.to === GST2_ADDRESS && ( - (GST2 Gastoken) + {internalOp.value.isZero() && ( +
+ (To:{" "} + + ) +
)}
{!internalOp.value.isZero() && ( -
+
TRANSFER @@ -59,7 +64,11 @@ const InternalSelfDestruct: React.FC = ({ toMiner ? "rounded px-2 py-1 bg-yellow-100" : "" }`} > - +
@@ -69,4 +78,4 @@ const InternalSelfDestruct: React.FC = ({ ); }; -export default React.memo(InternalSelfDestruct); +export default InternalSelfDestruct; diff --git a/src/components/InternalTransactionOperation.tsx b/src/components/InternalTransactionOperation.tsx index 7de3bb2..f167eb5 100644 --- a/src/components/InternalTransactionOperation.tsx +++ b/src/components/InternalTransactionOperation.tsx @@ -22,11 +22,18 @@ const InternalTransactionOperation: React.FC /> )} {internalOp.type === OperationType.SELF_DESTRUCT && ( - + )} {(internalOp.type === OperationType.CREATE || internalOp.type === OperationType.CREATE2) && ( - + )} ); diff --git a/src/components/InternalTransfer.tsx b/src/components/InternalTransfer.tsx index 2958452..bf46778 100644 --- a/src/components/InternalTransfer.tsx +++ b/src/components/InternalTransfer.tsx @@ -26,7 +26,7 @@ const InternalTransfer: React.FC = ({ internalOp.to === txData.confirmedData.miner; return ( -
+
TRANSFER @@ -44,6 +44,7 @@ const InternalTransfer: React.FC = ({ miner={fromMiner} txFrom={internalOp.from === txData.from} txTo={internalOp.from === txData.to} + resolvedAddresses={resolvedAddresses} />
@@ -61,6 +62,7 @@ const InternalTransfer: React.FC = ({ miner={toMiner} txFrom={internalOp.to === txData.from} txTo={internalOp.to === txData.to} + resolvedAddresses={resolvedAddresses} />
@@ -69,4 +71,4 @@ const InternalTransfer: React.FC = ({ ); }; -export default React.memo(InternalTransfer); +export default InternalTransfer; diff --git a/src/components/ModeTab.tsx b/src/components/ModeTab.tsx index 14a33fd..52ec3f9 100644 --- a/src/components/ModeTab.tsx +++ b/src/components/ModeTab.tsx @@ -1,13 +1,20 @@ import React from "react"; import { Tab } from "@headlessui/react"; -const ModeTab: React.FC = ({ children }) => ( +type ModeTabProps = { + disabled?: boolean | undefined; +}; + +const ModeTab: React.FC = ({ disabled, children }) => ( - `border rounded-lg px-2 py-1 bg-gray-100 hover:bg-gray-200 hover:shadow text-xs text-gray-500 hover:text-gray-600 ${ - selected ? "border-blue-300" : "" - }` + `border rounded-lg px-2 py-1 bg-gray-100 ${ + disabled + ? "border-gray-100 text-gray-300 cursor-default" + : "hover:bg-gray-200 hover:shadow text-gray-500 hover:text-gray-600" + } text-xs ${selected ? "border-blue-300" : ""}` } + disabled={disabled} > {children} diff --git a/src/components/PlainString.tsx b/src/components/PlainString.tsx new file mode 100644 index 0000000..5b891bf --- /dev/null +++ b/src/components/PlainString.tsx @@ -0,0 +1,53 @@ +import React from "react"; +import { NavLink } from "react-router-dom"; +import { ResolvedAddressRenderer } from "../api/address-resolver/address-resolver"; + +type PlainStringProps = { + address: string; + name: string; + linkable: boolean; + dontOverrideColors: boolean | undefined; +}; + +const PlainString: React.FC = ({ + address, + name, + linkable, + dontOverrideColors, +}) => { + if (linkable) { + return ( + + {name} + + ); + } + + return ( + + {name} + + ); +}; + +export const plainStringRenderer: ResolvedAddressRenderer = ( + address, + resolvedAddress, + linkable, + dontOverrideColors +) => ( + +); + +export default PlainString; diff --git a/src/components/SelectionHighlighter.tsx b/src/components/SelectionHighlighter.tsx new file mode 100644 index 0000000..40a3431 --- /dev/null +++ b/src/components/SelectionHighlighter.tsx @@ -0,0 +1,78 @@ +import React, { useMemo } from "react"; +import { + useSelectionContext, + OptionalSelection, + SelectionType, +} from "../useSelection"; + +export type ContentSelector = ( + selection: OptionalSelection, + content: string +) => boolean; + +export const genericSelector = + (type: SelectionType) => + (selection: OptionalSelection, content: string): boolean => + selection !== null && + selection.type === type && + selection.content === content; + +export const addressSelector: ContentSelector = genericSelector("address"); +export const functionSigSelector: ContentSelector = + genericSelector("functionSig"); + +type SelectionHighlighterProps = React.PropsWithChildren<{ + myType: SelectionType; + myContent: string; + selector: ContentSelector; +}>; + +const SelectionHighlighter: React.FC = ({ + myType, + myContent, + selector, + children, +}) => { + const [selection, setSelection] = useSelectionContext(); + const [select, deselect] = useMemo(() => { + const _select = () => { + setSelection({ type: myType, content: myContent }); + }; + const _deselect = () => { + setSelection(null); + }; + return [_select, _deselect]; + }, [setSelection, myType, myContent]); + + return ( + + {children} + + ); +}; + +type HighlighterBoxProps = { + selected: boolean; + select: () => void; + deselect: () => void; +}; + +const HighlighterBox: React.FC = React.memo( + ({ selected, select, deselect, children }) => ( +
+ {children} +
+ ) +); + +export default SelectionHighlighter; diff --git a/src/components/TransactionAddress.tsx b/src/components/TransactionAddress.tsx new file mode 100644 index 0000000..28540dd --- /dev/null +++ b/src/components/TransactionAddress.tsx @@ -0,0 +1,42 @@ +import React from "react"; +import AddressHighlighter from "./AddressHighlighter"; +import DecoratedAddressLink from "./DecoratedAddressLink"; +import { ResolvedAddresses } from "../api/address-resolver"; +import { useSelectedTransaction } from "../useSelectedTransaction"; +import { AddressContext } from "../types"; +import { Metadata } from "../useSourcify"; + +type TransactionAddressProps = { + address: string; + addressCtx?: AddressContext | undefined; + resolvedAddresses: ResolvedAddresses | undefined; + metadata?: Metadata | null | undefined; +}; + +const TransactionAddress: React.FC = ({ + address, + addressCtx, + resolvedAddresses, + metadata, +}) => { + const txData = useSelectedTransaction(); + // TODO: push down creation coloring logic into DecoratedAddressLink + const creation = address === txData?.confirmedData?.createdContractAddress; + + return ( + + + + ); +}; + +export default TransactionAddress; diff --git a/src/components/ValueHighlighter.tsx b/src/components/ValueHighlighter.tsx index c15b514..b9c813f 100644 --- a/src/components/ValueHighlighter.tsx +++ b/src/components/ValueHighlighter.tsx @@ -6,6 +6,7 @@ type ValueHighlighterProps = React.PropsWithChildren<{ value: BigNumber; }>; +// TODO: replace all occurences with SelectionHighlighter and remove this component const ValueHighlighter: React.FC = ({ value, children, diff --git a/src/params.ts b/src/params.ts index 2bfd757..5c95cfa 100644 --- a/src/params.ts +++ b/src/params.ts @@ -1,3 +1,3 @@ -export const MIN_API_LEVEL = 2; +export const MIN_API_LEVEL = 3; export const PAGE_SIZE = 25; diff --git a/src/search/TransactionItem.tsx b/src/search/TransactionItem.tsx index 2e6132d..446daf4 100644 --- a/src/search/TransactionItem.tsx +++ b/src/search/TransactionItem.tsx @@ -14,11 +14,12 @@ import TransactionDirection, { Flags, } from "../components/TransactionDirection"; import TransactionValue from "../components/TransactionValue"; -import { ProcessedTransaction } from "../types"; +import { ChecksummedAddress, ProcessedTransaction } from "../types"; import { FeeDisplay } from "./useFeeToggler"; import { formatValue } from "../components/formatter"; import ETH2USDValue from "../components/ETH2USDValue"; import { ResolvedAddresses } from "../api/address-resolver"; +import { Metadata } from "../useSourcify"; type TransactionItemProps = { tx: ProcessedTransaction; @@ -26,6 +27,7 @@ type TransactionItemProps = { selectedAddress?: string; feeDisplay: FeeDisplay; priceMap: Record; + metadatas: Record; }; const TransactionItem: React.FC = ({ @@ -34,6 +36,7 @@ const TransactionItem: React.FC = ({ selectedAddress, feeDisplay, priceMap, + metadatas, }) => { let direction: Direction | undefined; if (selectedAddress) { @@ -105,6 +108,7 @@ const TransactionItem: React.FC = ({ selectedAddress={selectedAddress} miner={tx.miner === tx.to} resolvedAddresses={resolvedAddresses} + metadata={metadatas[tx.to]} /> ) : ( @@ -114,6 +118,7 @@ const TransactionItem: React.FC = ({ selectedAddress={selectedAddress} creation resolvedAddresses={resolvedAddresses} + metadata={metadatas[tx.createdContractAddress!]} /> )} diff --git a/src/transaction/Details.tsx b/src/transaction/Details.tsx index 9c9e29d..e2613be 100644 --- a/src/transaction/Details.tsx +++ b/src/transaction/Details.tsx @@ -1,12 +1,6 @@ -import React, { useMemo } from "react"; -import { - TransactionDescription, - Fragment, - Interface, -} from "@ethersproject/abi"; +import React, { useContext, useMemo } from "react"; +import { TransactionDescription } from "@ethersproject/abi"; import { BigNumber } from "@ethersproject/bignumber"; -import { toUtf8String } from "@ethersproject/strings"; -import { Tab } from "@headlessui/react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCheckCircle } from "@fortawesome/free-solid-svg-icons/faCheckCircle"; import { faCube } from "@fortawesome/free-solid-svg-icons/faCube"; @@ -15,8 +9,7 @@ import ContentFrame from "../ContentFrame"; import InfoRow from "../components/InfoRow"; import BlockLink from "../components/BlockLink"; import BlockConfirmations from "../components/BlockConfirmations"; -import AddressHighlighter from "../components/AddressHighlighter"; -import DecoratedAddressLink from "../components/DecoratedAddressLink"; +import TransactionAddress from "../components/TransactionAddress"; import Copy from "../components/Copy"; import Nonce from "../components/Nonce"; import Timestamp from "../components/Timestamp"; @@ -29,16 +22,25 @@ import USDValue from "../components/USDValue"; import FormattedBalance from "../components/FormattedBalance"; import ETH2USDValue from "../components/ETH2USDValue"; import TokenTransferItem from "../TokenTransferItem"; -import { TransactionData, InternalOperation } from "../types"; +import { + TransactionData, + InternalOperation, + ChecksummedAddress, +} from "../types"; import PercentageBar from "../components/PercentageBar"; import ExternalLink from "../components/ExternalLink"; import RelativePosition from "../components/RelativePosition"; import PercentagePosition from "../components/PercentagePosition"; -import ModeTab from "../components/ModeTab"; -import DecodedParamsTable from "./decoder/DecodedParamsTable"; -import { rawInputTo4Bytes, use4Bytes } from "../use4Bytes"; -import { DevDoc, UserDoc } from "../useSourcify"; +import InputDecoder from "./decoder/InputDecoder"; +import { + rawInputTo4Bytes, + use4Bytes, + useTransactionDescription, +} from "../use4Bytes"; +import { DevDoc, useMultipleMetadata, UserDoc } from "../useSourcify"; import { ResolvedAddresses } from "../api/address-resolver"; +import { RuntimeContext } from "../useRuntime"; +import { useAppConfigContext } from "../useAppConfig"; type DetailsProps = { txData: TransactionData; @@ -65,35 +67,42 @@ const Details: React.FC = ({ txData.confirmedData?.blockBaseFeePerGas !== undefined && txData.confirmedData?.blockBaseFeePerGas !== null; - const utfInput = useMemo(() => { - try { - return txData && toUtf8String(txData.data); - } catch (err) { - console.warn("Error while converting input data to string"); - console.warn(err); - return ""; - } - }, [txData]); - const fourBytes = txData.to !== null ? rawInputTo4Bytes(txData.data) : "0x"; const fourBytesEntry = use4Bytes(fourBytes); - const fourBytesTxDesc = useMemo(() => { - if (!fourBytesEntry) { - return fourBytesEntry; - } - if (!txData || !fourBytesEntry.signature) { - return undefined; - } - const sig = fourBytesEntry?.signature; - const functionFragment = Fragment.fromString(`function ${sig}`); - const intf = new Interface([functionFragment]); - return intf.parseTransaction({ data: txData.data, value: txData.value }); - }, [txData, fourBytesEntry]); + const fourBytesTxDesc = useTransactionDescription( + fourBytesEntry, + txData.data, + txData.value + ); const resolvedTxDesc = txDesc ?? fourBytesTxDesc; const userMethod = txDesc ? userDoc?.methods[txDesc.signature] : undefined; const devMethod = txDesc ? devDoc?.methods[txDesc.signature] : undefined; + const { provider } = useContext(RuntimeContext); + const addresses = useMemo(() => { + const _addresses: ChecksummedAddress[] = []; + if (txData.to) { + _addresses.push(txData.to); + } + if (txData.confirmedData?.createdContractAddress) { + _addresses.push(txData.confirmedData.createdContractAddress); + } + for (const t of txData.tokenTransfers) { + _addresses.push(t.from); + _addresses.push(t.to); + _addresses.push(t.token); + } + return _addresses; + }, [txData]); + const { sourcifySource } = useAppConfigContext(); + const metadatas = useMultipleMetadata( + undefined, + addresses, + provider?.network.chainId, + sourcifySource + ); + return ( @@ -152,14 +161,10 @@ const Details: React.FC = ({
- - - +
@@ -170,14 +175,11 @@ const Details: React.FC = ({ {txData.to ? (
- - - +
) : txData.confirmedData === undefined ? ( @@ -186,21 +188,18 @@ const Details: React.FC = ({ ) : (
- - - + resolvedAddresses={resolvedAddresses} + metadata={ + metadatas?.[txData.confirmedData?.createdContractAddress!] + } + />
)} {internalOps && internalOps.length > 0 && ( -
+
{internalOps.map((op, i) => ( = ({ )} {txData.tokenTransfers.length > 0 && ( -
- {txData.tokenTransfers.map((t, i) => ( - - ))} -
+ {txData.tokenTransfers.map((t, i) => ( + + ))}
)} @@ -256,24 +253,16 @@ const Details: React.FC = ({ {txData.type === 2 && ( <> - - Ether ( - {" "} - Gwei) - + Ether ( + {" "} + Gwei) - - Ether ( - {" "} - Gwei) - + Ether ( + Gwei) )} @@ -315,18 +304,16 @@ const Details: React.FC = ({ )} {txData.confirmedData && hasEIP1559 && ( - - {" "} - Gwei ( - {" "} - wei) - + {" "} + Gwei ( + {" "} + wei) )} {txData.confirmedData && ( @@ -353,47 +340,15 @@ const Details: React.FC = ({ )} - - - Decoded - Raw - UTF-8 - - - - {fourBytes === "0x" ? ( - <>No parameters - ) : resolvedTxDesc === undefined ? ( - <>Waiting for data... - ) : resolvedTxDesc === null ? ( - <>Can't decode data - ) : ( - - )} - - -