diff --git a/package-lock.json b/package-lock.json index 07a0037..00aa601 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,12 +31,10 @@ "@types/react-blockies": "^1.4.1", "@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.6.0", "ethers": "^5.5.1", "highlightjs-solidity": "^2.0.2", - "query-string": "^7.0.1", "react": "^17.0.2", "react-blockies": "^1.4.1", "react-chartjs-2": "^4.0.0", @@ -44,7 +42,7 @@ "react-error-boundary": "^3.1.4", "react-helmet-async": "^1.1.2", "react-image": "^4.0.3", - "react-router-dom": "^5.3.0", + "react-router-dom": "^6.0.2", "react-scripts": "4.0.3", "react-syntax-highlighter": "^15.4.5", "serve": "^13.0.2", @@ -3053,11 +3051,6 @@ "@types/unist": "*" } }, - "node_modules/@types/history": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz", - "integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==" - }, "node_modules/@types/html-minifier-terser": { "version": "5.1.1", "license": "MIT" @@ -3160,25 +3153,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-router": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.15.tgz", - "integrity": "sha512-z3UlMG/x91SFEVmmvykk9FLTliDvfdIUky4k2rCfXWQ0NKbrP8o9BTCaCTPuYsB8gDkUnUmkcA2vYlm2DR+HAA==", - "dependencies": { - "@types/history": "*", - "@types/react": "*" - } - }, - "node_modules/@types/react-router-dom": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.2.tgz", - "integrity": "sha512-ELEYRUie2czuJzaZ5+ziIp9Hhw+juEw8b7C11YNA4QdLCVbQ3qLi2l4aq8XnlqM7V31LZX8dxUuFUCrzHm6sqQ==", - "dependencies": { - "@types/history": "*", - "@types/react": "*", - "@types/react-router": "*" - } - }, "node_modules/@types/react-syntax-highlighter": { "version": "13.5.2", "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-13.5.2.tgz", @@ -8559,14 +8533,6 @@ "node": ">=0.10.0" } }, - "node_modules/filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/finalhandler": { "version": "1.1.2", "license": "MIT", @@ -9288,16 +9254,11 @@ "integrity": "sha512-q0aYUKiZ9MPQg41qx/KpXKaCpqql50qTvmwGYyLFfcjt9AE/+C9CwjVIdJZc7EYj6NGgJuFJ4im1gfgrzUU1fQ==" }, "node_modules/history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.1.0.tgz", + "integrity": "sha512-zPuQgPacm2vH2xdORvGGz1wQMuHSIB56yNAy5FnLuwOwgSYyPKptJtcMm6Ev+hRGeS+GzhbmRacHzvlESbFwDg==", "dependencies": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" + "@babel/runtime": "^7.7.6" } }, "node_modules/hmac-drbg": { @@ -9309,19 +9270,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/hoopy": { "version": "0.1.4", "license": "MIT", @@ -11674,19 +11622,6 @@ "node": ">=4" } }, - "node_modules/mini-create-react-context": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", - "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", - "dependencies": { - "@babel/runtime": "^7.12.1", - "tiny-warning": "^1.0.3" - }, - "peerDependencies": { - "prop-types": "^15.0.0", - "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/mini-css-extract-plugin": { "version": "0.11.3", "license": "MIT", @@ -14223,23 +14158,6 @@ "node": ">=0.6" } }, - "node_modules/query-string": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.0.1.tgz", - "integrity": "sha512-uIw3iRvHnk9to1blJCG3BTc+Ro56CBowJXKmNNAm3RulvPBzWLRqKSiiDk+IplJhsydwtuNMHi8UGQFcCLVfkA==", - "dependencies": { - "decode-uri-component": "^0.2.0", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/querystring": { "version": "0.2.0", "engines": { @@ -14594,60 +14512,29 @@ } }, "node_modules/react-router": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", - "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.0.2.tgz", + "integrity": "sha512-8/Wm3Ed8t7TuedXjAvV39+c8j0vwrI5qVsYqjFr5WkJjsJpEvNSoLRUbtqSEYzqaTUj1IV+sbPJxvO+accvU0Q==", "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "history": "^5.1.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=16.8" } }, "node_modules/react-router-dom": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", - "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.0.2.tgz", + "integrity": "sha512-cOpJ4B6raFutr0EG8O/M2fEoyQmwvZWomf1c6W2YXBZuFBx8oTk/zqjXghwScyhfrtnt0lANXV2182NQblRxFA==", "dependencies": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.2.1", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "history": "^5.1.0", + "react-router": "6.0.2" }, "peerDependencies": { - "react": ">=15" + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/react-router/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/react-router/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/react-router/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/react-scripts": { "version": "4.0.3", "license": "MIT", @@ -15430,11 +15317,6 @@ "node": ">=4" } }, - "node_modules/resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, "node_modules/resolve-url": { "version": "0.2.1", "license": "MIT" @@ -16724,14 +16606,6 @@ "node": ">= 6" } }, - "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", - "engines": { - "node": ">=6" - } - }, "node_modules/split-string": { "version": "3.1.0", "license": "MIT", @@ -16869,14 +16743,6 @@ "version": "1.0.1", "license": "MIT" }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", - "engines": { - "node": ">=4" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "license": "MIT", @@ -17854,16 +17720,6 @@ "version": "0.3.0", "license": "MIT" }, - "node_modules/tiny-invariant": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", - "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" - }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, "node_modules/tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -18477,11 +18333,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" - }, "node_modules/vary": { "version": "1.1.2", "license": "MIT", @@ -21545,11 +21396,6 @@ "@types/unist": "*" } }, - "@types/history": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz", - "integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==" - }, "@types/html-minifier-terser": { "version": "5.1.1" }, @@ -21640,25 +21486,6 @@ "@types/react": "*" } }, - "@types/react-router": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.15.tgz", - "integrity": "sha512-z3UlMG/x91SFEVmmvykk9FLTliDvfdIUky4k2rCfXWQ0NKbrP8o9BTCaCTPuYsB8gDkUnUmkcA2vYlm2DR+HAA==", - "requires": { - "@types/history": "*", - "@types/react": "*" - } - }, - "@types/react-router-dom": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.2.tgz", - "integrity": "sha512-ELEYRUie2czuJzaZ5+ziIp9Hhw+juEw8b7C11YNA4QdLCVbQ3qLi2l4aq8XnlqM7V31LZX8dxUuFUCrzHm6sqQ==", - "requires": { - "@types/history": "*", - "@types/react": "*", - "@types/react-router": "*" - } - }, "@types/react-syntax-highlighter": { "version": "13.5.2", "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-13.5.2.tgz", @@ -25321,11 +25148,6 @@ "to-regex-range": "^2.1.0" } }, - "filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=" - }, "finalhandler": { "version": "1.1.2", "requires": { @@ -25790,16 +25612,11 @@ "integrity": "sha512-q0aYUKiZ9MPQg41qx/KpXKaCpqql50qTvmwGYyLFfcjt9AE/+C9CwjVIdJZc7EYj6NGgJuFJ4im1gfgrzUU1fQ==" }, "history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.1.0.tgz", + "integrity": "sha512-zPuQgPacm2vH2xdORvGGz1wQMuHSIB56yNAy5FnLuwOwgSYyPKptJtcMm6Ev+hRGeS+GzhbmRacHzvlESbFwDg==", "requires": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" + "@babel/runtime": "^7.7.6" } }, "hmac-drbg": { @@ -25810,21 +25627,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "requires": { - "react-is": "^16.7.0" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - } - } - }, "hoopy": { "version": "0.1.4" }, @@ -27345,15 +27147,6 @@ "min-indent": { "version": "1.0.1" }, - "mini-create-react-context": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", - "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", - "requires": { - "@babel/runtime": "^7.12.1", - "tiny-warning": "^1.0.3" - } - }, "mini-css-extract-plugin": { "version": "0.11.3", "requires": { @@ -29076,17 +28869,6 @@ "qs": { "version": "6.7.0" }, - "query-string": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.0.1.tgz", - "integrity": "sha512-uIw3iRvHnk9to1blJCG3BTc+Ro56CBowJXKmNNAm3RulvPBzWLRqKSiiDk+IplJhsydwtuNMHi8UGQFcCLVfkA==", - "requires": { - "decode-uri-component": "^0.2.0", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - }, "querystring": { "version": "0.2.0" }, @@ -29320,54 +29102,20 @@ "version": "0.8.3" }, "react-router": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", - "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.0.2.tgz", + "integrity": "sha512-8/Wm3Ed8t7TuedXjAvV39+c8j0vwrI5qVsYqjFr5WkJjsJpEvNSoLRUbtqSEYzqaTUj1IV+sbPJxvO+accvU0Q==", "requires": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "requires": { - "isarray": "0.0.1" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - } + "history": "^5.1.0" } }, "react-router-dom": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz", - "integrity": "sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.0.2.tgz", + "integrity": "sha512-cOpJ4B6raFutr0EG8O/M2fEoyQmwvZWomf1c6W2YXBZuFBx8oTk/zqjXghwScyhfrtnt0lANXV2182NQblRxFA==", "requires": { - "@babel/runtime": "^7.12.13", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.2.1", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "history": "^5.1.0", + "react-router": "6.0.2" } }, "react-scripts": { @@ -29904,11 +29652,6 @@ "resolve-from": { "version": "3.0.0" }, - "resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, "resolve-url": { "version": "0.2.1" }, @@ -30824,11 +30567,6 @@ } } }, - "split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" - }, "split-string": { "version": "3.1.0", "requires": { @@ -30925,11 +30663,6 @@ "stream-shift": { "version": "1.0.1" }, - "strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" - }, "string_decoder": { "version": "1.3.0", "requires": { @@ -31597,16 +31330,6 @@ "timsort": { "version": "0.3.0" }, - "tiny-invariant": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", - "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" - }, - "tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, "tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -32004,11 +31727,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" - }, "vary": { "version": "1.1.2" }, diff --git a/package.json b/package.json index 4cdea99..95e2ed6 100644 --- a/package.json +++ b/package.json @@ -26,12 +26,10 @@ "@types/react-blockies": "^1.4.1", "@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.6.0", "ethers": "^5.5.1", "highlightjs-solidity": "^2.0.2", - "query-string": "^7.0.1", "react": "^17.0.2", "react-blockies": "^1.4.1", "react-chartjs-2": "^4.0.0", @@ -39,7 +37,7 @@ "react-error-boundary": "^3.1.4", "react-helmet-async": "^1.1.2", "react-image": "^4.0.3", - "react-router-dom": "^5.3.0", + "react-router-dom": "^6.0.2", "react-scripts": "4.0.3", "react-syntax-highlighter": "^15.4.5", "serve": "^13.0.2", diff --git a/src/AddressTransactions.tsx b/src/AddressTransactions.tsx index a1013c8..52432fd 100644 --- a/src/AddressTransactions.tsx +++ b/src/AddressTransactions.tsx @@ -1,15 +1,14 @@ import React, { useState, useEffect, useMemo, useContext } from "react"; import { useParams, - useLocation, - useHistory, - Switch, + useNavigate, + Routes, Route, + useSearchParams, } from "react-router-dom"; import { BlockTag } from "@ethersproject/abstract-provider"; import { getAddress, isAddress } from "@ethersproject/address"; import { Tab } from "@headlessui/react"; -import queryString from "query-string"; import Blockies from "react-blockies"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCircleNotch } from "@fortawesome/free-solid-svg-icons/faCircleNotch"; @@ -35,47 +34,50 @@ import { useMultipleMetadata } from "./useSourcify"; import { ChecksummedAddress } from "./types"; import SourcifyLogo from "./sourcify.svg"; -type BlockParams = { - addressOrName: string; - direction?: string; -}; - -type PageParams = { - p?: number; -}; - const AddressTransactions: React.FC = () => { const { provider } = useContext(RuntimeContext); - const params = useParams(); - const location = useLocation(); - const history = useHistory(); - const qs = queryString.parse(location.search); - let hash: string | undefined; - if (qs.h) { - hash = qs.h as string; + const { addressOrName, direction } = useParams(); + if (addressOrName === undefined) { + throw new Error("addressOrName couldn't be undefined here"); } - const [checksummedAddress, setChecksummedAddress] = useState(); + const navigate = useNavigate(); + + const [searchParams] = useSearchParams(); + const h = searchParams.get("h"); + let hash: string | undefined; + if (h) { + hash = h; + } + + const [checksummedAddress, setChecksummedAddress] = useState< + string | undefined + >(); const [isENS, setENS] = useState(); const [error, setError] = useState(); // If it looks like it is an ENS name, try to resolve it useEffect(() => { - if (isAddress(params.addressOrName)) { + // TODO: handle and offer fallback to bad checksummed addresses + if (isAddress(addressOrName)) { setENS(false); setError(false); // Normalize to checksummed address - const _checksummedAddress = getAddress(params.addressOrName); - if (_checksummedAddress !== params.addressOrName) { + const _checksummedAddress = getAddress(addressOrName); + if (_checksummedAddress !== addressOrName) { // Request came with a non-checksummed address; fix the URL - history.replace( + navigate( `/address/${_checksummedAddress}${ - params.direction ? "/" + params.direction : "" - }${location.search}` + direction ? "/" + direction : "" + }?${searchParams.toString()}`, + { replace: true } ); + return; } + setChecksummedAddress(_checksummedAddress); + document.title = `Address ${_checksummedAddress} | Otterscan`; return; } @@ -83,11 +85,12 @@ const AddressTransactions: React.FC = () => { return; } const resolveName = async () => { - const resolvedAddress = await provider.resolveName(params.addressOrName); + const resolvedAddress = await provider.resolveName(addressOrName); if (resolvedAddress !== null) { setENS(true); setError(false); setChecksummedAddress(resolvedAddress); + document.title = `Address ${addressOrName} | Otterscan`; } else { setENS(false); setError(true); @@ -95,13 +98,7 @@ const AddressTransactions: React.FC = () => { } }; resolveName(); - }, [ - provider, - params.addressOrName, - history, - params.direction, - location.search, - ]); + }, [provider, addressOrName, navigate, direction, searchParams]); const [controller, setController] = useState(); useEffect(() => { @@ -142,28 +139,28 @@ const AddressTransactions: React.FC = () => { }; // Page load from scratch - if (params.direction === "first" || params.direction === undefined) { + if (direction === "first" || direction === undefined) { if (!controller?.isFirst || controller.address !== checksummedAddress) { readFirstPage(); } - } else if (params.direction === "prev") { + } else if (direction === "prev") { if (controller && controller.address === checksummedAddress) { prevPage(); } else { readMiddlePage(false); } - } else if (params.direction === "next") { + } else if (direction === "next") { if (controller && controller.address === checksummedAddress) { nextPage(); } else { readMiddlePage(true); } - } else if (params.direction === "last") { + } else if (direction === "last") { if (!controller?.isLast || controller.address !== checksummedAddress) { readLastPage(); } } - }, [provider, checksummedAddress, params.direction, hash, controller]); + }, [provider, checksummedAddress, direction, hash, controller]); const page = useMemo(() => controller?.getPage(), [controller]); const addrCollector = useMemo(() => pageCollector(page), [page]); @@ -177,8 +174,6 @@ const AddressTransactions: React.FC = () => { }, [page]); const priceMap = useMultipleETHUSDOracle(provider, blockTags); - document.title = `Address ${params.addressOrName} | Otterscan`; - const [feeDisplay, feeDisplayToggler] = useFeeToggler(); const selectionCtx = useSelection(); @@ -212,7 +207,7 @@ const AddressTransactions: React.FC = () => { {error ? ( - "{params.addressOrName}" is not an ETH address or ENS name. + "{addressOrName}" is not an ETH address or ENS name. ) : ( checksummedAddress && ( @@ -231,7 +226,7 @@ const AddressTransactions: React.FC = () => { {isENS && ( - ENS: {params.addressOrName} + ENS: {addressOrName} )} @@ -274,73 +269,81 @@ const AddressTransactions: React.FC = () => { - - - -
-
- {page === undefined ? ( - <>Waiting for search results... - ) : ( - <>{page.length} transactions on this page - )} -
- -
- - {page ? ( - - {page.map((tx) => ( - - ))} -
-
- {page === undefined ? ( - <>Waiting for search results... - ) : ( - <>{page.length} transactions on this page - )} -
- + + +
+
+ {page === undefined ? ( + <>Waiting for search results... + ) : ( + <>{page.length} transactions on this page + )}
- - ) : ( - - )} - - - - - - + +
+ + {page ? ( + + {page.map((tx) => ( + + ))} +
+
+ {page === undefined ? ( + <>Waiting for search results... + ) : ( + <>{page.length} transactions on this page + )} +
+ +
+
+ ) : ( + + )} + + } + /> + + } + /> +
@@ -350,4 +353,4 @@ const AddressTransactions: React.FC = () => { ); }; -export default React.memo(AddressTransactions); +export default AddressTransactions; diff --git a/src/App.tsx b/src/App.tsx index 110d626..4ee2dca 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,15 +1,12 @@ -import React, { Suspense, useMemo, useState } from "react"; -import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; +import React, { Suspense } from "react"; +import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import WarningHeader from "./WarningHeader"; import Home from "./Home"; -import Search from "./Search"; -import Title from "./Title"; +import Main from "./Main"; import ConnectionErrorPanel from "./ConnectionErrorPanel"; import Footer from "./Footer"; import { ConnectionStatus } from "./types"; import { RuntimeContext, useRuntime } from "./useRuntime"; -import { AppConfig, AppConfigContext } from "./useAppConfig"; -import { SourcifySource } from "./url"; const Block = React.lazy( () => import(/* webpackChunkName: "block", webpackPrefetch: true */ "./Block") @@ -39,15 +36,6 @@ const London = React.lazy( const App = () => { const runtime = useRuntime(); - const [sourcifySource, setSourcifySource] = useState( - SourcifySource.IPFS_IPNS - ); - const appConfig = useMemo((): AppConfig => { - return { - sourcifySource, - setSourcifySource, - }; - }, [sourcifySource, setSourcifySource]); return ( @@ -61,34 +49,27 @@ const App = () => {
- - - + + } /> + } /> + }> + } /> + } + /> + } /> + } + /> + } + /> + } /> - - - - - - - - - - <Route path="/block/:blockNumberOrHash" exact> - <Block /> - </Route> - <Route path="/block/:blockNumber/txs" exact> - <BlockTransactions /> - </Route> - <Route path="/tx/:txhash"> - <Transaction /> - </Route> - <Route path="/address/:addressOrName/:direction?"> - <AddressTransactions /> - </Route> - </AppConfigContext.Provider> - </Route> - </Switch> + </Routes> </Router> <Footer /> </div> @@ -98,4 +79,4 @@ const App = () => { ); }; -export default React.memo(App); +export default App; diff --git a/src/Block.tsx b/src/Block.tsx index df16643..473ef75 100644 --- a/src/Block.tsx +++ b/src/Block.tsx @@ -26,15 +26,14 @@ import { blockTxsURL } from "./url"; import { useBlockData } from "./useErigonHooks"; import { useETHUSDOracle } from "./usePriceOracle"; -type BlockParams = { - blockNumberOrHash: string; -}; - const Block: React.FC = () => { const { provider } = useContext(RuntimeContext); - const params = useParams<BlockParams>(); + const { blockNumberOrHash } = useParams(); + if (blockNumberOrHash === undefined) { + throw new Error("blockNumberOrHash couldn't be undefined here"); + } - const block = useBlockData(provider, params.blockNumberOrHash); + const block = useBlockData(provider, blockNumberOrHash); useEffect(() => { if (block) { document.title = `Block #${block.number} | Otterscan`; @@ -63,9 +62,7 @@ const Block: React.FC = () => { <StandardSubtitle> <div className="flex space-x-1 items-baseline"> <span>Block</span> - <span className="text-base text-gray-500"> - #{params.blockNumberOrHash} - </span> + <span className="text-base text-gray-500">#{blockNumberOrHash}</span> {block && ( <NavBlock blockNumber={block.number} @@ -192,4 +189,4 @@ const Block: React.FC = () => { ); }; -export default React.memo(Block); +export default Block; diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index ed9b2c7..b1fe5af 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -1,31 +1,24 @@ import React, { useMemo, useContext } from "react"; -import { useParams, useLocation } from "react-router"; +import { useParams } from "react-router"; import { BigNumber } from "@ethersproject/bignumber"; -import queryString from "query-string"; import StandardFrame from "./StandardFrame"; import BlockTransactionHeader from "./block/BlockTransactionHeader"; import BlockTransactionResults from "./block/BlockTransactionResults"; import { PAGE_SIZE } from "./params"; import { RuntimeContext } from "./useRuntime"; import { useBlockTransactions } from "./useErigonHooks"; - -type BlockParams = { - blockNumber: string; -}; - -type PageParams = { - p?: number; -}; +import { useSearchParams } from "react-router-dom"; const BlockTransactions: React.FC = () => { const { provider } = useContext(RuntimeContext); - const params = useParams<BlockParams>(); - const location = useLocation<PageParams>(); - const qs = queryString.parse(location.search); + const params = useParams(); + + const [searchParams] = useSearchParams(); let pageNumber = 1; - if (qs.p) { + const p = searchParams.get("p"); + if (p) { try { - pageNumber = parseInt(qs.p as string); + pageNumber = parseInt(p); } catch (err) {} } @@ -56,4 +49,4 @@ const BlockTransactions: React.FC = () => { ); }; -export default React.memo(BlockTransactions); +export default BlockTransactions; diff --git a/src/Home.tsx b/src/Home.tsx index 103639a..cdb47c9 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -1,5 +1,5 @@ import React, { useState, useContext } from "react"; -import { NavLink, useHistory } from "react-router-dom"; +import { NavLink, useNavigate } from "react-router-dom"; import { commify } from "@ethersproject/units"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faBurn } from "@fortawesome/free-solid-svg-icons/faBurn"; @@ -9,18 +9,20 @@ import Timestamp from "./components/Timestamp"; import { RuntimeContext } from "./useRuntime"; import { useLatestBlock } from "./useLatestBlock"; import { blockURL } from "./url"; +import { search } from "./search/search"; const CameraScanner = React.lazy(() => import("./search/CameraScanner")); const Home: React.FC = () => { const { provider } = useContext(RuntimeContext); - const [search, setSearch] = useState<string>(); + const [searchString, setSearchString] = useState<string>(""); const [canSubmit, setCanSubmit] = useState<boolean>(false); - const history = useHistory(); + const navigate = useNavigate(); const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => { - setCanSubmit(e.target.value.trim().length > 0); - setSearch(e.target.value.trim()); + const searchTerm = e.target.value.trim(); + setCanSubmit(searchTerm.length > 0); + setSearchString(searchTerm); }; const handleSubmit: React.FormEventHandler<HTMLFormElement> = (e) => { @@ -29,7 +31,7 @@ const Home: React.FC = () => { return; } - history.push(`/search?q=${search}`); + search(searchString, navigate); }; const latestBlock = useLatestBlock(provider); diff --git a/src/Main.tsx b/src/Main.tsx new file mode 100644 index 0000000..4a8cbf4 --- /dev/null +++ b/src/Main.tsx @@ -0,0 +1,26 @@ +import React, { useMemo, useState } from "react"; +import { Outlet } from "react-router-dom"; +import Title from "./Title"; +import { AppConfig, AppConfigContext } from "./useAppConfig"; +import { SourcifySource } from "./url"; + +const Main: React.FC = () => { + const [sourcifySource, setSourcifySource] = useState<SourcifySource>( + SourcifySource.IPFS_IPNS + ); + const appConfig = useMemo((): AppConfig => { + return { + sourcifySource, + setSourcifySource, + }; + }, [sourcifySource, setSourcifySource]); + + return ( + <AppConfigContext.Provider value={appConfig}> + <Title /> + <Outlet /> + </AppConfigContext.Provider> + ); +}; + +export default Main; diff --git a/src/Search.tsx b/src/Search.tsx deleted file mode 100644 index 78dc724..0000000 --- a/src/Search.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { useLocation, useHistory } from "react-router-dom"; -import { isAddress } from "@ethersproject/address"; -import { isHexString } from "@ethersproject/bytes"; -import queryString from "query-string"; - -type SearchParams = { - q: string; -}; - -const Search: React.FC = () => { - const location = useLocation<SearchParams>(); - const history = useHistory(); - - const qs = queryString.parse(location.search); - const q = (qs.q ?? "").toString(); - if (isAddress(q)) { - history.replace(`/address/${q}`); - return <></>; - } - if (isHexString(q, 32)) { - history.replace(`/tx/${q}`); - return <></>; - } - - const blockNumber = parseInt(q); - if (!isNaN(blockNumber)) { - history.replace(`/block/${blockNumber}`); - return <></>; - } - - // Assume it is an ENS name - history.replace(`/address/${q}`); - return <></>; -}; - -export default Search; diff --git a/src/Title.tsx b/src/Title.tsx index e1e9b8e..f23a92e 100644 --- a/src/Title.tsx +++ b/src/Title.tsx @@ -1,24 +1,26 @@ import React, { useState, useRef, useContext } from "react"; -import { Link, useHistory } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faQrcode } from "@fortawesome/free-solid-svg-icons/faQrcode"; import useKeyboardShortcut from "use-keyboard-shortcut"; import PriceBox from "./PriceBox"; import SourcifyMenu from "./SourcifyMenu"; import { RuntimeContext } from "./useRuntime"; +import { search } from "./search/search"; import Otter from "./otter.jpg"; const CameraScanner = React.lazy(() => import("./search/CameraScanner")); const Title: React.FC = () => { const { provider } = useContext(RuntimeContext); - const [search, setSearch] = useState<string>(); + const [searchString, setSearchString] = useState<string>(""); const [canSubmit, setCanSubmit] = useState<boolean>(false); - const history = useHistory(); + const navigate = useNavigate(); const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => { - setCanSubmit(e.target.value.trim().length > 0); - setSearch(e.target.value.trim()); + const searchTerm = e.target.value.trim(); + setCanSubmit(searchTerm.length > 0); + setSearchString(searchTerm); }; const handleSubmit: React.FormEventHandler<HTMLFormElement> = (e) => { @@ -27,7 +29,10 @@ const Title: React.FC = () => { return; } - history.push(`/search?q=${search}`); + if (searchRef.current) { + searchRef.current.value = ""; + } + search(searchString, navigate); }; const searchRef = useRef<HTMLInputElement>(null); @@ -92,4 +97,4 @@ const Title: React.FC = () => { ); }; -export default React.memo(Title); +export default Title; diff --git a/src/Transaction.tsx b/src/Transaction.tsx index 168c83f..4b8008c 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -1,5 +1,5 @@ import React, { useMemo, useContext } from "react"; -import { Route, Switch, useParams } from "react-router-dom"; +import { useParams, Routes, Route } from "react-router-dom"; import { Tab } from "@headlessui/react"; import StandardFrame from "./StandardFrame"; import StandardSubtitle from "./StandardSubtitle"; @@ -37,14 +37,12 @@ const Trace = React.lazy( ) ); -type TransactionParams = { - txhash: string; -}; - const Transaction: React.FC = () => { const { provider } = useContext(RuntimeContext); - const params = useParams<TransactionParams>(); - const { txhash } = params; + const { txhash } = useParams(); + if (txhash === undefined) { + throw new Error("txhash couldn't be undefined here"); + } const txData = useTxData(provider, txhash); const addrCollector = useMemo( @@ -97,44 +95,53 @@ const Transaction: React.FC = () => { <SelectionContext.Provider value={selectionCtx}> <Tab.Group> <Tab.List className="flex space-x-2 border-l border-r border-t rounded-t-lg bg-white"> - <NavTab href={`/tx/${txhash}`}>Overview</NavTab> + <NavTab href=".">Overview</NavTab> {txData.confirmedData?.blockNumber !== undefined && ( - <NavTab href={`/tx/${txhash}/logs`}> + <NavTab href="logs"> Logs {txData && ` (${txData.confirmedData?.logs?.length ?? 0})`} </NavTab> )} - <NavTab href={`/tx/${txhash}/trace`}>Trace</NavTab> + <NavTab href="trace">Trace</NavTab> </Tab.List> </Tab.Group> <React.Suspense fallback={null}> - <Switch> - <Route path="/tx/:txhash/" exact> - <Details - txData={txData} - txDesc={txDesc} - userDoc={metadata?.output.userdoc} - devDoc={metadata?.output.devdoc} - internalOps={internalOps} - sendsEthToMiner={sendsEthToMiner} - ethUSDPrice={blockETHUSDPrice} - resolvedAddresses={resolvedAddresses} - /> - </Route> - <Route path="/tx/:txhash/logs/" exact> - <Logs - txData={txData} - metadata={metadata} - resolvedAddresses={resolvedAddresses} - /> - </Route> - <Route path="/tx/:txhash/trace" exact> - <Trace - txData={txData} - resolvedAddresses={resolvedAddresses} - /> - </Route> - </Switch> + <Routes> + <Route + index + element={ + <Details + txData={txData} + txDesc={txDesc} + userDoc={metadata?.output.userdoc} + devDoc={metadata?.output.devdoc} + internalOps={internalOps} + sendsEthToMiner={sendsEthToMiner} + ethUSDPrice={blockETHUSDPrice} + resolvedAddresses={resolvedAddresses} + /> + } + /> + <Route + path="logs" + element={ + <Logs + txData={txData} + metadata={metadata} + resolvedAddresses={resolvedAddresses} + /> + } + /> + <Route + path="trace" + element={ + <Trace + txData={txData} + resolvedAddresses={resolvedAddresses} + /> + } + /> + </Routes> </React.Suspense> </SelectionContext.Provider> )} @@ -143,4 +150,4 @@ const Transaction: React.FC = () => { ); }; -export default React.memo(Transaction); +export default Transaction; diff --git a/src/components/NavTab.tsx b/src/components/NavTab.tsx index e16d193..6b3c66c 100644 --- a/src/components/NavTab.tsx +++ b/src/components/NavTab.tsx @@ -9,7 +9,7 @@ type NavTabProps = { const NavTab: React.FC<NavTabProps> = ({ href, children }) => ( <Tab as={Fragment}> <NavLink - className={(isActive) => + className={({ isActive }) => `${ isActive ? "text-link-blue border-link-blue" @@ -17,7 +17,7 @@ const NavTab: React.FC<NavTabProps> = ({ href, children }) => ( } hover:text-link-blue text-sm font-bold px-3 py-3 border-b-2` } to={href} - exact + end replace > {children} diff --git a/src/search/CameraScanner.tsx b/src/search/CameraScanner.tsx index b32d707..5766814 100644 --- a/src/search/CameraScanner.tsx +++ b/src/search/CameraScanner.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useHistory } from "react-router-dom"; +import { useNavigate } from "react-router-dom"; import { isAddress } from "@ethersproject/address"; import { QrReader } from "@blackbox-vision/react-qr-reader"; import { OnResultFunction } from "@blackbox-vision/react-qr-reader/dist-types/types"; @@ -11,7 +11,7 @@ type CameraScannerProps = { }; const CameraScanner: React.FC<CameraScannerProps> = ({ turnOffScan }) => { - const history = useHistory(); + const navigate = useNavigate(); const evaluateScan: OnResultFunction = (result, error, codeReader) => { console.log("scan"); @@ -23,7 +23,7 @@ const CameraScanner: React.FC<CameraScannerProps> = ({ turnOffScan }) => { return; } - history.push(`/search?q=${text}`); + navigate(`/search?q=${text}`); turnOffScan(); } }; diff --git a/src/search/search.ts b/src/search/search.ts index 26af5e2..0453a44 100644 --- a/src/search/search.ts +++ b/src/search/search.ts @@ -1,4 +1,7 @@ import { JsonRpcProvider, TransactionResponse } from "@ethersproject/providers"; +import { isAddress } from "@ethersproject/address"; +import { isHexString } from "@ethersproject/bytes"; +import { NavigateFunction } from "react-router"; import { PAGE_SIZE } from "../params"; import { ProcessedTransaction, TransactionChunk } from "../types"; @@ -194,3 +197,24 @@ export class SearchController { return this; } } + +export const search = (q: string, navigate: NavigateFunction) => { + if (isAddress(q)) { + navigate(`/address/${q}`, { replace: true }); + return; + } + + if (isHexString(q, 32)) { + navigate(`/tx/${q}`, { replace: true }); + return; + } + + const blockNumber = parseInt(q); + if (!isNaN(blockNumber)) { + navigate(`/block/${blockNumber}`, { replace: true }); + return; + } + + // Assume it is an ENS name + navigate(`/address/${q}`); +};