diff --git a/.dockerignore b/.dockerignore index df120e1..ee24273 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,5 +2,6 @@ node_modules 4bytes !4bytes/signatures +!4bytes/with_parameter_names trustwallet !trustwallet/blockchains/ethereum/assets diff --git a/Dockerfile b/Dockerfile index 7583d23..af322ed 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,9 +14,14 @@ WORKDIR /assets COPY trustwallet/blockchains/ethereum/assets /assets/ RUN find . -name logo.png | parallel magick convert {} -filter Lanczos -resize 32x32 {} +FROM alpine:3.14.0 AS fourbytesbuilder +WORKDIR /signatures +COPY 4bytes/signatures /signatures/ +COPY 4bytes/with_parameter_names /signatures/ + FROM nginx:1.21.1-alpine RUN apk add jq -COPY 4bytes/signatures /usr/share/nginx/html/signatures/ +COPY --from=fourbytesbuilder /signatures /usr/share/nginx/html/signatures/ COPY --from=logobuilder /assets /usr/share/nginx/html/assets/ COPY nginx.conf /etc/nginx/conf.d/default.conf COPY --from=builder /otterscan-build/build /usr/share/nginx/html/ diff --git a/package-lock.json b/package-lock.json index 9d80934..495f958 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,10 +10,10 @@ "license": "MIT", "dependencies": { "@blackbox-vision/react-qr-reader": "^5.0.0", - "@chainlink/contracts": "^0.2.1", + "@chainlink/contracts": "^0.2.2", "@craco/craco": "^6.3.0", "@fontsource/fira-code": "^4.5.1", - "@fontsource/roboto": "^4.5.0", + "@fontsource/roboto": "^4.5.1", "@fontsource/roboto-mono": "^4.5.0", "@fontsource/space-grotesk": "^4.5.0", "@fortawesome/fontawesome-svg-core": "^1.2.36", @@ -27,19 +27,19 @@ "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.24", "@types/node": "^14.17.5", - "@types/react": "^17.0.20", + "@types/react": "^17.0.26", "@types/react-blockies": "^1.4.1", "@types/react-dom": "^17.0.9", - "@types/react-highlight": "^0.12.3", - "@types/react-router-dom": "^5.1.8", + "@types/react-highlight": "^0.12.4", + "@types/react-router-dom": "^5.3.0", "@types/react-syntax-highlighter": "^13.5.2", "chart.js": "^3.5.1", - "ethers": "^5.4.6", - "highlightjs-solidity": "^1.2.0", + "ethers": "^5.4.7", + "highlightjs-solidity": "^2.0.1", "query-string": "^7.0.1", "react": "^17.0.2", "react-blockies": "^1.4.1", - "react-chartjs-2": "^3.0.4", + "react-chartjs-2": "^3.0.5", "react-dom": "^17.0.2", "react-error-boundary": "^3.1.3", "react-image": "^4.0.3", @@ -52,8 +52,8 @@ "web-vitals": "^1.0.1" }, "devDependencies": { - "autoprefixer": "^9.8.6", - "postcss": "^7.0.36", + "autoprefixer": "^9.8.7", + "postcss": "^7.0.38", "source-map-explorer": "^2.5.2", "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.6" } @@ -1228,9 +1228,9 @@ } }, "node_modules/@chainlink/contracts": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@chainlink/contracts/-/contracts-0.2.1.tgz", - "integrity": "sha512-mAQgPQKiqW3tLMlp31NgcnXpwG3lttgKU0izAqKiirJ9LH7rQ+O0oHIVR5Qp2yuqgmfbLsgfdLo4GcVC8IFz3Q==" + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@chainlink/contracts/-/contracts-0.2.2.tgz", + "integrity": "sha512-wxXPbt7O3aZaUSG34ufFASC5amRSL6eeYCqsa+2gpqbB8Hk7B7FydEDCI5dqvAC444TlFskPHcVbizCZkRHPpw==" }, "node_modules/@cnakazawa/watch": { "version": "1.0.4", @@ -1455,9 +1455,9 @@ } }, "node_modules/@ethersproject/bignumber": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.4.1.tgz", - "integrity": "sha512-fJhdxqoQNuDOk6epfM7yD6J8Pol4NUCy1vkaGAkuujZm0+lNow//MKu1hLhRiYV4BsOHyBv5/lsTjF+7hWwhJg==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.4.2.tgz", + "integrity": "sha512-oIBDhsKy5bs7j36JlaTzFgNPaZjiNDOXsdSgSpXRucUl+UA6L/1YLlFeI3cPAoodcenzF4nxNPV13pcy7XbWjA==", "funding": [ { "type": "individual", @@ -2017,9 +2017,9 @@ "integrity": "sha512-8KTCsfs5m3UgICpHLglIKAS7vc2FFOu7/vvpWcE/42SWbh+9X8EJbEyJp6W96kU5iDVlAlUv4Cqc36Z9XUpLmA==" }, "node_modules/@fontsource/roboto": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.0.tgz", - "integrity": "sha512-ja4XYw/9kNRFM5Ndk9vwzHWsdBMXczyBazFkTXJQ74QQBnT0BbSsHn0pF60AU0Iznig1Wt9x3rADfG8LANvMpw==" + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.1.tgz", + "integrity": "sha512-3mhfL+eNPG/woMNqwD/OHaW5qMpeGEBsDwzmhFmjB1yUV+M+M9P0NhP/AyHvnGz3DrqkvZ7CPzNMa+UkVLeELg==" }, "node_modules/@fontsource/roboto-mono": { "version": "4.5.0", @@ -3090,9 +3090,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "17.0.20", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.20.tgz", - "integrity": "sha512-wWZrPlihslrPpcKyCSlmIlruakxr57/buQN1RjlIeaaTWDLtJkTtRW429MoQJergvVKc4IWBpRhWw7YNh/7GVA==", + "version": "17.0.26", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.26.tgz", + "integrity": "sha512-MXxuXrH2xOcv5cp/su4oz69dNQnSA90JjFw5HBd5wifw6Ihi94j7dRJm7qNsB30tnruXSCPc9qmlhGop4nh9Hw==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -3116,9 +3116,9 @@ } }, "node_modules/@types/react-highlight": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/@types/react-highlight/-/react-highlight-0.12.3.tgz", - "integrity": "sha512-mfhuHdE3dUjvRv1lvZIvda2B+VW7rkG1ufnFLKbDcRUp/L73bGUmEuEfpnjgdLgeWYho88ahQZRcMSh9GsZA0g==", + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/@types/react-highlight/-/react-highlight-0.12.4.tgz", + "integrity": "sha512-eq+1LUJYDTpZMx31KD3e8K0OJcfUlgWaxYGldKfD7uMkmg04x6O2+h6kG7Rm0SY1+XkeBWYhg2lyIFv8WpGrLQ==", "dependencies": { "@types/react": "*" } @@ -3133,9 +3133,9 @@ } }, "node_modules/@types/react-router-dom": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.8.tgz", - "integrity": "sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.0.tgz", + "integrity": "sha512-svUzpEpKDwK8nmfV2vpZNSsiijFNKY8+gUqGqvGGOVrXvX58k1JIJubZa5igkwacbq/0umphO5SsQn/BQsnKpw==", "dependencies": { "@types/history": "*", "@types/react": "*", @@ -4163,12 +4163,13 @@ } }, "node_modules/autoprefixer": { - "version": "9.8.6", - "license": "MIT", + "version": "9.8.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.7.tgz", + "integrity": "sha512-7Hg99B1eTH5+LgmUBUSmov1Z3bsggQJS7v3IMGo6wcScnbRuvtMc871J9J+4bSbIqa9LSX/zypFXJ8sXHpMJeQ==", "dependencies": { "browserslist": "^4.12.0", "caniuse-lite": "^1.0.30001109", - "colorette": "^1.2.1", + "nanocolors": "^0.2.8", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", "postcss": "^7.0.32", @@ -5562,8 +5563,13 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001191", - "license": "CC-BY-4.0" + "version": "1.0.30001263", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001263.tgz", + "integrity": "sha512-doiV5dft6yzWO1WwU19kt8Qz8R0/8DgEziz6/9n2FxUasteZNwNNYSmJO3GLBH8lCVE73AB1RPDPAeYbcO5Cvw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } }, "node_modules/capture-exit": { "version": "2.0.0", @@ -8119,9 +8125,9 @@ } }, "node_modules/ethers": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.4.6.tgz", - "integrity": "sha512-F7LXARyB/Px3AQC6/QKedWZ8eqCkgOLORqL4B/F0Mag/K+qJSFGqsR36EaOZ6fKg3ZonI+pdbhb4A8Knt/43jQ==", + "version": "5.4.7", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.4.7.tgz", + "integrity": "sha512-iZc5p2nqfWK1sj8RabwsPM28cr37Bpq7ehTQ5rWExBr2Y09Sn1lDKZOED26n+TsZMye7Y6mIgQ/1cwpSD8XZew==", "funding": [ { "type": "individual", @@ -8139,7 +8145,7 @@ "@ethersproject/address": "5.4.0", "@ethersproject/base64": "5.4.0", "@ethersproject/basex": "5.4.0", - "@ethersproject/bignumber": "5.4.1", + "@ethersproject/bignumber": "5.4.2", "@ethersproject/bytes": "5.4.0", "@ethersproject/constants": "5.4.0", "@ethersproject/contracts": "5.4.1", @@ -9288,9 +9294,9 @@ } }, "node_modules/highlightjs-solidity": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/highlightjs-solidity/-/highlightjs-solidity-1.2.0.tgz", - "integrity": "sha512-KXYcVzBRof3CBWHsxGffsSEAJF0YsPaOk1jgIYv2xSzrBSxkfNUJFXrlE2oZEWvYQKbPqLe4qprJyNbSDV+LZA==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/highlightjs-solidity/-/highlightjs-solidity-2.0.1.tgz", + "integrity": "sha512-9YY+HQpXMTrF8HgRByjeQhd21GXAz2ktMPTcs6oWSj5HJR52fgsNoelMOmgigwcpt9j4tu4IVSaWaJB2n2TbvQ==" }, "node_modules/history": { "version": "4.10.1", @@ -11877,6 +11883,11 @@ "license": "MIT", "optional": true }, + "node_modules/nanocolors": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/nanocolors/-/nanocolors-0.2.10.tgz", + "integrity": "sha512-i+EDWGsJClQwR/bhLIG/CObZZwaYaS5qt+yjxZbfV+77QiNHNzE9nj4d9Ut1TGZ0R0eSwPcQWzReASzXuw/7oA==" + }, "node_modules/nanoid": { "version": "3.1.23", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", @@ -12885,13 +12896,12 @@ } }, "node_modules/postcss": { - "version": "7.0.36", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", - "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "version": "7.0.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.38.tgz", + "integrity": "sha512-wNrSHWjHDQJR/IZL5IKGxRtFgrYNaAA/UrkW2WqbtZO6uxSLMxMN+s2iqUMwnAWm3fMROlDYZB41dr0Mt7vBwQ==", "dependencies": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "nanocolors": "^0.2.2", + "source-map": "^0.6.1" }, "engines": { "node": ">=6.0.0" @@ -13950,55 +13960,6 @@ "node": ">=6.14.4" } }, - "node_modules/postcss/node_modules/ansi-styles": { - "version": "3.2.1", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss/node_modules/chalk": { - "version": "2.4.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss/node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss/node_modules/escape-string-regexp": { - "version": "1.0.5", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/postcss/node_modules/supports-color": { - "version": "6.1.0", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/prelude-ls": { "version": "1.1.2", "engines": { @@ -14425,14 +14386,14 @@ } }, "node_modules/react-chartjs-2": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-3.0.4.tgz", - "integrity": "sha512-pcbFNpkPMTkGXXJ7k7hnukbRD0ZV01qB6JQY1ontITc2IYvhGlK6BBDy28VeydYs1Dl/c5ZpRgRVEtT5GUnxcQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-3.0.5.tgz", + "integrity": "sha512-fYr4E82agaZi9IFMe5GtOZ6WE/HWdxy/KywLNOzXsqgPkD2oo1IlrQLKMLUki/2UXko3p95TR2L8Q2rEss/opQ==", "dependencies": { "lodash": "^4.17.19" }, "peerDependencies": { - "chart.js": "^3.1.0", + "chart.js": "^3.5.0", "react": "^16.8.0 || ^17.0.0" } }, @@ -20513,9 +20474,9 @@ } }, "@chainlink/contracts": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@chainlink/contracts/-/contracts-0.2.1.tgz", - "integrity": "sha512-mAQgPQKiqW3tLMlp31NgcnXpwG3lttgKU0izAqKiirJ9LH7rQ+O0oHIVR5Qp2yuqgmfbLsgfdLo4GcVC8IFz3Q==" + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@chainlink/contracts/-/contracts-0.2.2.tgz", + "integrity": "sha512-wxXPbt7O3aZaUSG34ufFASC5amRSL6eeYCqsa+2gpqbB8Hk7B7FydEDCI5dqvAC444TlFskPHcVbizCZkRHPpw==" }, "@cnakazawa/watch": { "version": "1.0.4", @@ -20646,9 +20607,9 @@ } }, "@ethersproject/bignumber": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.4.1.tgz", - "integrity": "sha512-fJhdxqoQNuDOk6epfM7yD6J8Pol4NUCy1vkaGAkuujZm0+lNow//MKu1hLhRiYV4BsOHyBv5/lsTjF+7hWwhJg==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.4.2.tgz", + "integrity": "sha512-oIBDhsKy5bs7j36JlaTzFgNPaZjiNDOXsdSgSpXRucUl+UA6L/1YLlFeI3cPAoodcenzF4nxNPV13pcy7XbWjA==", "requires": { "@ethersproject/bytes": "^5.4.0", "@ethersproject/logger": "^5.4.0", @@ -20956,9 +20917,9 @@ "integrity": "sha512-8KTCsfs5m3UgICpHLglIKAS7vc2FFOu7/vvpWcE/42SWbh+9X8EJbEyJp6W96kU5iDVlAlUv4Cqc36Z9XUpLmA==" }, "@fontsource/roboto": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.0.tgz", - "integrity": "sha512-ja4XYw/9kNRFM5Ndk9vwzHWsdBMXczyBazFkTXJQ74QQBnT0BbSsHn0pF60AU0Iznig1Wt9x3rADfG8LANvMpw==" + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.1.tgz", + "integrity": "sha512-3mhfL+eNPG/woMNqwD/OHaW5qMpeGEBsDwzmhFmjB1yUV+M+M9P0NhP/AyHvnGz3DrqkvZ7CPzNMa+UkVLeELg==" }, "@fontsource/roboto-mono": { "version": "4.5.0", @@ -21658,9 +21619,9 @@ "version": "1.5.4" }, "@types/react": { - "version": "17.0.20", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.20.tgz", - "integrity": "sha512-wWZrPlihslrPpcKyCSlmIlruakxr57/buQN1RjlIeaaTWDLtJkTtRW429MoQJergvVKc4IWBpRhWw7YNh/7GVA==", + "version": "17.0.26", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.26.tgz", + "integrity": "sha512-MXxuXrH2xOcv5cp/su4oz69dNQnSA90JjFw5HBd5wifw6Ihi94j7dRJm7qNsB30tnruXSCPc9qmlhGop4nh9Hw==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -21684,9 +21645,9 @@ } }, "@types/react-highlight": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/@types/react-highlight/-/react-highlight-0.12.3.tgz", - "integrity": "sha512-mfhuHdE3dUjvRv1lvZIvda2B+VW7rkG1ufnFLKbDcRUp/L73bGUmEuEfpnjgdLgeWYho88ahQZRcMSh9GsZA0g==", + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/@types/react-highlight/-/react-highlight-0.12.4.tgz", + "integrity": "sha512-eq+1LUJYDTpZMx31KD3e8K0OJcfUlgWaxYGldKfD7uMkmg04x6O2+h6kG7Rm0SY1+XkeBWYhg2lyIFv8WpGrLQ==", "requires": { "@types/react": "*" } @@ -21701,9 +21662,9 @@ } }, "@types/react-router-dom": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.1.8.tgz", - "integrity": "sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.0.tgz", + "integrity": "sha512-svUzpEpKDwK8nmfV2vpZNSsiijFNKY8+gUqGqvGGOVrXvX58k1JIJubZa5igkwacbq/0umphO5SsQn/BQsnKpw==", "requires": { "@types/history": "*", "@types/react": "*", @@ -22381,11 +22342,13 @@ "version": "2.1.2" }, "autoprefixer": { - "version": "9.8.6", + "version": "9.8.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.7.tgz", + "integrity": "sha512-7Hg99B1eTH5+LgmUBUSmov1Z3bsggQJS7v3IMGo6wcScnbRuvtMc871J9J+4bSbIqa9LSX/zypFXJ8sXHpMJeQ==", "requires": { "browserslist": "^4.12.0", "caniuse-lite": "^1.0.30001109", - "colorette": "^1.2.1", + "nanocolors": "^0.2.8", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", "postcss": "^7.0.32", @@ -23399,7 +23362,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001191" + "version": "1.0.30001263", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001263.tgz", + "integrity": "sha512-doiV5dft6yzWO1WwU19kt8Qz8R0/8DgEziz6/9n2FxUasteZNwNNYSmJO3GLBH8lCVE73AB1RPDPAeYbcO5Cvw==" }, "capture-exit": { "version": "2.0.0", @@ -25078,9 +25043,9 @@ "version": "1.8.1" }, "ethers": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.4.6.tgz", - "integrity": "sha512-F7LXARyB/Px3AQC6/QKedWZ8eqCkgOLORqL4B/F0Mag/K+qJSFGqsR36EaOZ6fKg3ZonI+pdbhb4A8Knt/43jQ==", + "version": "5.4.7", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.4.7.tgz", + "integrity": "sha512-iZc5p2nqfWK1sj8RabwsPM28cr37Bpq7ehTQ5rWExBr2Y09Sn1lDKZOED26n+TsZMye7Y6mIgQ/1cwpSD8XZew==", "requires": { "@ethersproject/abi": "5.4.1", "@ethersproject/abstract-provider": "5.4.1", @@ -25088,7 +25053,7 @@ "@ethersproject/address": "5.4.0", "@ethersproject/base64": "5.4.0", "@ethersproject/basex": "5.4.0", - "@ethersproject/bignumber": "5.4.1", + "@ethersproject/bignumber": "5.4.2", "@ethersproject/bytes": "5.4.0", "@ethersproject/constants": "5.4.0", "@ethersproject/contracts": "5.4.1", @@ -25876,9 +25841,9 @@ "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" }, "highlightjs-solidity": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/highlightjs-solidity/-/highlightjs-solidity-1.2.0.tgz", - "integrity": "sha512-KXYcVzBRof3CBWHsxGffsSEAJF0YsPaOk1jgIYv2xSzrBSxkfNUJFXrlE2oZEWvYQKbPqLe4qprJyNbSDV+LZA==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/highlightjs-solidity/-/highlightjs-solidity-2.0.1.tgz", + "integrity": "sha512-9YY+HQpXMTrF8HgRByjeQhd21GXAz2ktMPTcs6oWSj5HJR52fgsNoelMOmgigwcpt9j4tu4IVSaWaJB2n2TbvQ==" }, "history": { "version": "4.10.1", @@ -27562,6 +27527,11 @@ "version": "2.14.2", "optional": true }, + "nanocolors": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/nanocolors/-/nanocolors-0.2.10.tgz", + "integrity": "sha512-i+EDWGsJClQwR/bhLIG/CObZZwaYaS5qt+yjxZbfV+77QiNHNzE9nj4d9Ut1TGZ0R0eSwPcQWzReASzXuw/7oA==" + }, "nanoid": { "version": "3.1.23", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", @@ -28212,46 +28182,12 @@ "version": "0.1.1" }, "postcss": { - "version": "7.0.36", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", - "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "version": "7.0.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.38.tgz", + "integrity": "sha512-wNrSHWjHDQJR/IZL5IKGxRtFgrYNaAA/UrkW2WqbtZO6uxSLMxMN+s2iqUMwnAWm3fMROlDYZB41dr0Mt7vBwQ==", "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "escape-string-regexp": { - "version": "1.0.5" - }, - "supports-color": { - "version": "6.1.0", - "requires": { - "has-flag": "^3.0.0" - } - } + "nanocolors": "^0.2.2", + "source-map": "^0.6.1" } }, "postcss-attribute-case-insensitive": { @@ -29288,9 +29224,9 @@ } }, "react-chartjs-2": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-3.0.4.tgz", - "integrity": "sha512-pcbFNpkPMTkGXXJ7k7hnukbRD0ZV01qB6JQY1ontITc2IYvhGlK6BBDy28VeydYs1Dl/c5ZpRgRVEtT5GUnxcQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-3.0.5.tgz", + "integrity": "sha512-fYr4E82agaZi9IFMe5GtOZ6WE/HWdxy/KywLNOzXsqgPkD2oo1IlrQLKMLUki/2UXko3p95TR2L8Q2rEss/opQ==", "requires": { "lodash": "^4.17.19" } diff --git a/package.json b/package.json index 67637e3..ad60da8 100644 --- a/package.json +++ b/package.json @@ -5,10 +5,10 @@ "license": "MIT", "dependencies": { "@blackbox-vision/react-qr-reader": "^5.0.0", - "@chainlink/contracts": "^0.2.1", + "@chainlink/contracts": "^0.2.2", "@craco/craco": "^6.3.0", "@fontsource/fira-code": "^4.5.1", - "@fontsource/roboto": "^4.5.0", + "@fontsource/roboto": "^4.5.1", "@fontsource/roboto-mono": "^4.5.0", "@fontsource/space-grotesk": "^4.5.0", "@fortawesome/fontawesome-svg-core": "^1.2.36", @@ -22,19 +22,19 @@ "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.24", "@types/node": "^14.17.5", - "@types/react": "^17.0.20", + "@types/react": "^17.0.26", "@types/react-blockies": "^1.4.1", "@types/react-dom": "^17.0.9", - "@types/react-highlight": "^0.12.3", - "@types/react-router-dom": "^5.1.8", + "@types/react-highlight": "^0.12.4", + "@types/react-router-dom": "^5.3.0", "@types/react-syntax-highlighter": "^13.5.2", "chart.js": "^3.5.1", - "ethers": "^5.4.6", - "highlightjs-solidity": "^1.2.0", + "ethers": "^5.4.7", + "highlightjs-solidity": "^2.0.1", "query-string": "^7.0.1", "react": "^17.0.2", "react-blockies": "^1.4.1", - "react-chartjs-2": "^3.0.4", + "react-chartjs-2": "^3.0.5", "react-dom": "^17.0.2", "react-error-boundary": "^3.1.3", "react-image": "^4.0.3", @@ -53,6 +53,7 @@ "eject": "react-scripts eject", "source-map-explorer": "source-map-explorer build/static/js/*.js", "assets-start": "docker run --rm -p 3001:80 --name otterscan-assets -d -v$(pwd)/4bytes/signatures:/usr/share/nginx/html/signatures/ -v$(pwd)/trustwallet/blockchains/ethereum/assets:/usr/share/nginx/html/assets -v$(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf nginx:1.21.1-alpine", + "assets-start-with-param-names": "docker run --rm -p 3001:80 --name otterscan-assets -d -v$(pwd)/4bytes/with_parameter_names:/usr/share/nginx/html/signatures/ -v$(pwd)/trustwallet/blockchains/ethereum/assets:/usr/share/nginx/html/assets -v$(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf nginx:1.21.1-alpine", "assets-stop": "docker stop otterscan-assets", "docker-build": "DOCKER_BUILDKIT=1 docker build -t otterscan -f Dockerfile .", "docker-start": "docker run --rm -p 5000:80 --name otterscan -d otterscan", @@ -77,8 +78,8 @@ ] }, "devDependencies": { - "autoprefixer": "^9.8.6", - "postcss": "^7.0.36", + "autoprefixer": "^9.8.7", + "postcss": "^7.0.38", "source-map-explorer": "^2.5.2", "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.6" } diff --git a/src/TokenTransferItem.tsx b/src/TokenTransferItem.tsx index c9f40a2..083f7f0 100644 --- a/src/TokenTransferItem.tsx +++ b/src/TokenTransferItem.tsx @@ -7,7 +7,7 @@ import DecoratedAddressLink from "./components/DecoratedAddressLink"; import FormattedBalance from "./components/FormattedBalance"; import { AddressContext, - TokenMetas, + TokenMeta, TokenTransfer, TransactionData, } from "./types"; @@ -15,14 +15,14 @@ import { type TokenTransferItemProps = { t: TokenTransfer; txData: TransactionData; - tokenMetas: TokenMetas; + tokenMeta?: TokenMeta | undefined; }; // TODO: handle partial const TokenTransferItem: React.FC = ({ t, txData, - tokenMetas, + tokenMeta, }) => (
@@ -57,7 +57,7 @@ const TokenTransferItem: React.FC = ({ @@ -65,11 +65,9 @@ const TokenTransferItem: React.FC = ({
diff --git a/src/Transaction.tsx b/src/Transaction.tsx index 29c7208..0edd994 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -82,6 +82,8 @@ const Transaction: React.FC = () => {
= ({ data }) => { - const rawFourBytes = data.slice(0, 10); - const methodName = use4Bytes(rawFourBytes); - const isSimpleTransfer = data === "0x"; + const rawFourBytes = rawInputTo4Bytes(data); + const fourBytesEntry = use4Bytes(rawFourBytes); + const methodName = fourBytesEntry?.name ?? rawFourBytes; + const isSimpleTransfer = rawFourBytes === "0x"; const methodTitle = isSimpleTransfer ? "ETH Transfer" : methodName === rawFourBytes diff --git a/src/components/NavTab.tsx b/src/components/NavTab.tsx index b8ff811..e16d193 100644 --- a/src/components/NavTab.tsx +++ b/src/components/NavTab.tsx @@ -6,13 +6,16 @@ type NavTabProps = { href: string; }; -// TODO: migrate activeClassName because of: https://github.com/remix-run/react-router/releases/tag/v5.3.0 -// TODO: @types/react-router-dom still doesn't support function in className const NavTab: React.FC = ({ href, children }) => ( + `${ + isActive + ? "text-link-blue border-link-blue" + : "text-gray-500 border-transparent" + } hover:text-link-blue text-sm font-bold px-3 py-3 border-b-2` + } to={href} exact replace diff --git a/src/transaction/DecodedParamRow.tsx b/src/transaction/DecodedParamRow.tsx deleted file mode 100644 index 9d9bcf8..0000000 --- a/src/transaction/DecodedParamRow.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from "react"; -import AddressHighlighter from "../components/AddressHighlighter"; -import DecoratedAddressLink from "../components/DecoratedAddressLink"; -import Copy from "../components/Copy"; -import { ParamType } from "@ethersproject/abi"; -import { TransactionData } from "../types"; - -type DecodedParamRowProps = { - prefix?: string; - i?: number | undefined; - r: any; - paramType: ParamType; - txData: TransactionData; -}; - -const DecodedParamRow: React.FC = ({ - prefix, - i, - r, - paramType, - txData, -}) => { - return ( - <> - - - {prefix && {prefix}} - {paramType.name}{" "} - {i !== undefined && ( - ({i}) - )} - - {paramType.type} - - {paramType.baseType === "address" ? ( -
- - - - -
- ) : paramType.baseType === "bool" ? ( - - {r.toString()} - - ) : paramType.baseType === "bytes" ? ( - - {r.toString()}{" "} - - {r.toString().length / 2 - 1}{" "} - {r.toString().length / 2 - 1 === 1 ? "byte" : "bytes"} - - - ) : paramType.baseType === "tuple" ? ( - <> - ) : ( - r.toString() - )} - - - {paramType.baseType === "tuple" && - r.map((e: any, idx: number) => ( - - ))} - - ); -}; - -export default React.memo(DecodedParamRow); diff --git a/src/transaction/Details.tsx b/src/transaction/Details.tsx index bea1587..716c529 100644 --- a/src/transaction/Details.tsx +++ b/src/transaction/Details.tsx @@ -1,5 +1,9 @@ import React, { useMemo } from "react"; -import { TransactionDescription } from "@ethersproject/abi"; +import { + TransactionDescription, + Fragment, + Interface, +} from "@ethersproject/abi"; import { BigNumber } from "@ethersproject/bignumber"; import { toUtf8String } from "@ethersproject/strings"; import { Tab } from "@headlessui/react"; @@ -31,11 +35,15 @@ import ExternalLink from "../components/ExternalLink"; import RelativePosition from "../components/RelativePosition"; import PercentagePosition from "../components/PercentagePosition"; import ModeTab from "../components/ModeTab"; -import DecodedParamsTable from "./DecodedParamsTable"; +import DecodedParamsTable from "./decoder/DecodedParamsTable"; +import { rawInputTo4Bytes, use4Bytes } from "../use4Bytes"; +import { DevDoc, UserDoc } from "../useSourcify"; type DetailsProps = { txData: TransactionData; txDesc: TransactionDescription | null | undefined; + userDoc?: UserDoc | undefined; + devDoc?: DevDoc | undefined; internalOps?: InternalOperation[]; sendsEthToMiner: boolean; ethUSDPrice: BigNumber | undefined; @@ -44,6 +52,8 @@ type DetailsProps = { const Details: React.FC = ({ txData, txDesc, + userDoc, + devDoc, internalOps, sendsEthToMiner, ethUSDPrice, @@ -56,12 +66,28 @@ const Details: React.FC = ({ try { return txData && toUtf8String(txData.data); } catch (err) { - console.error("Error while converting input data to string"); - console.error(err); + console.warn("Error while converting input data to string"); + console.warn(err); return ""; } }, [txData]); + const fourBytes = rawInputTo4Bytes(txData.data); + const fourBytesEntry = use4Bytes(fourBytes); + const fourBytesTxDesc = useMemo(() => { + 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 resolvedTxDesc = txDesc ?? fourBytesTxDesc; + const userMethod = txDesc ? userDoc?.methods[txDesc.signature] : undefined; + const devMethod = txDesc ? devDoc?.methods[txDesc.signature] : undefined; + return ( @@ -187,7 +213,7 @@ const Details: React.FC = ({ key={i} t={t} txData={txData} - tokenMetas={txData.tokenMetas} + tokenMeta={txData.tokenMetas[t.token]} /> ))} @@ -322,15 +348,20 @@ const Details: React.FC = ({ - {txDesc === undefined ? ( + {fourBytes === "0x" ? ( + <>No parameters + ) : resolvedTxDesc === undefined ? ( <>Waiting for data... - ) : txDesc === null ? ( + ) : resolvedTxDesc === null ? ( <>No decoded data ) : ( )} diff --git a/src/transaction/LogEntry.tsx b/src/transaction/LogEntry.tsx index 1d4e85f..e06c558 100644 --- a/src/transaction/LogEntry.tsx +++ b/src/transaction/LogEntry.tsx @@ -6,8 +6,8 @@ import AddressHighlighter from "../components/AddressHighlighter"; import DecoratedAddressLink from "../components/DecoratedAddressLink"; import Copy from "../components/Copy"; import ModeTab from "../components/ModeTab"; -import DecodedParamsTable from "./DecodedParamsTable"; -import DecodedLogSignature from "./DecodedLogSignature"; +import DecodedParamsTable from "./decoder/DecodedParamsTable"; +import DecodedLogSignature from "./decoder/DecodedLogSignature"; import { TransactionData } from "../types"; type LogEntryProps = { diff --git a/src/transaction/decoder/AddressDecoder.tsx b/src/transaction/decoder/AddressDecoder.tsx new file mode 100644 index 0000000..ee6369a --- /dev/null +++ b/src/transaction/decoder/AddressDecoder.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import AddressHighlighter from "../../components/AddressHighlighter"; +import DecoratedAddressLink from "../../components/DecoratedAddressLink"; +import Copy from "../../components/Copy"; +import { TransactionData } from "../../types"; + +type AddressDecoderProps = { + r: any; + txData: TransactionData; +}; + +const AddressDecoder: React.FC = ({ r, txData }) => ( +
+ + + + +
+); + +export default React.memo(AddressDecoder); diff --git a/src/transaction/decoder/BooleanDecoder.tsx b/src/transaction/decoder/BooleanDecoder.tsx new file mode 100644 index 0000000..259f4a9 --- /dev/null +++ b/src/transaction/decoder/BooleanDecoder.tsx @@ -0,0 +1,13 @@ +import React from "react"; + +type BooleanDecoderProps = { + r: any; +}; + +const BooleanDecoder: React.FC = ({ r }) => ( + + {r.toString()} + +); + +export default React.memo(BooleanDecoder); diff --git a/src/transaction/decoder/BytesDecoder.tsx b/src/transaction/decoder/BytesDecoder.tsx new file mode 100644 index 0000000..f7de95f --- /dev/null +++ b/src/transaction/decoder/BytesDecoder.tsx @@ -0,0 +1,17 @@ +import React from "react"; + +type BytesDecoderProps = { + r: any; +}; + +const BytesDecoder: React.FC = ({ r }) => ( + + {r.toString()}{" "} + + {r.toString().length / 2 - 1}{" "} + {r.toString().length / 2 - 1 === 1 ? "byte" : "bytes"} + + +); + +export default React.memo(BytesDecoder); diff --git a/src/transaction/DecodedLogSignature.tsx b/src/transaction/decoder/DecodedLogSignature.tsx similarity index 100% rename from src/transaction/DecodedLogSignature.tsx rename to src/transaction/decoder/DecodedLogSignature.tsx diff --git a/src/transaction/decoder/DecodedParamRow.tsx b/src/transaction/decoder/DecodedParamRow.tsx new file mode 100644 index 0000000..fed9ecb --- /dev/null +++ b/src/transaction/decoder/DecodedParamRow.tsx @@ -0,0 +1,120 @@ +import React, { ReactNode, useState } from "react"; +import { ParamType } from "@ethersproject/abi"; +import { Switch } from "@headlessui/react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faQuestionCircle } from "@fortawesome/free-regular-svg-icons/faQuestionCircle"; +import { faQuestionCircle as faQuestionCircleSolid } from "@fortawesome/free-solid-svg-icons/faQuestionCircle"; +import Uint256Decoder from "./Uint256Decoder"; +import AddressDecoder from "./AddressDecoder"; +import BooleanDecoder from "./BooleanDecoder"; +import BytesDecoder from "./BytesDecoder"; +import { TransactionData } from "../../types"; + +type DecodedParamRowProps = { + prefix?: ReactNode; + i?: number | undefined; + r: any; + paramType: ParamType; + txData: TransactionData; + arrayElem?: number | undefined; + help?: string | undefined; +}; + +const DecodedParamRow: React.FC = ({ + prefix, + i, + r, + paramType, + txData, + arrayElem, + help, +}) => { + const [showHelp, setShowHelp] = useState(false); + + return ( + <> + + +
+ + {prefix && {prefix}} + {arrayElem !== undefined ? ( + + {" "} + [{arrayElem}] + + ) : ( + <> + {paramType.name ?? param_{i}}{" "} + {i !== undefined && ( + ({i}) + )} + + )} + + {help && ( + + + + )} +
+ {help && showHelp &&
{help}
} + + {paramType.type} + + {paramType.baseType === "uint256" ? ( + + ) : paramType.baseType === "address" ? ( + + ) : paramType.baseType === "bool" ? ( + + ) : paramType.baseType === "bytes" ? ( + + ) : paramType.baseType === "tuple" || + paramType.baseType === "array" ? ( + <> + ) : ( + r.toString() + )} + + + {paramType.baseType === "tuple" && + r.map((e: any, idx: number) => ( + param_{i}. + ) + } + i={idx} + r={e} + paramType={paramType.components[idx]} + txData={txData} + /> + ))} + {paramType.baseType === "array" && + r.map((e: any, idx: number) => ( + param_{i}} + r={e} + paramType={paramType.arrayChildren} + txData={txData} + arrayElem={idx} + /> + ))} + + ); +}; + +export default React.memo(DecodedParamRow); diff --git a/src/transaction/DecodedParamsTable.tsx b/src/transaction/decoder/DecodedParamsTable.tsx similarity index 57% rename from src/transaction/DecodedParamsTable.tsx rename to src/transaction/decoder/DecodedParamsTable.tsx index ff439d8..f7daee5 100644 --- a/src/transaction/DecodedParamsTable.tsx +++ b/src/transaction/decoder/DecodedParamsTable.tsx @@ -1,20 +1,26 @@ import React from "react"; import { ParamType, Result } from "@ethersproject/abi"; import DecodedParamRow from "./DecodedParamRow"; -import { TransactionData } from "../types"; +import { TransactionData } from "../../types"; +import { DevMethod, UserMethod } from "../../useSourcify"; type DecodedParamsTableProps = { args: Result; paramTypes: ParamType[]; txData: TransactionData; + hasParamNames?: boolean; + userMethod?: UserMethod | undefined; + devMethod?: DevMethod | undefined; }; const DecodedParamsTable: React.FC = ({ args, paramTypes, txData, + hasParamNames = true, + devMethod, }) => ( - +
+ {!hasParamNames && ( + + + + )} {args.map((r, i) => ( @@ -32,6 +47,7 @@ const DecodedParamsTable: React.FC = ({ r={r} paramType={paramTypes[i]} txData={txData} + help={devMethod?.params?.[paramTypes[i].name]} /> ))} diff --git a/src/transaction/decoder/Uint256Decoder.tsx b/src/transaction/decoder/Uint256Decoder.tsx new file mode 100644 index 0000000..7d4a003 --- /dev/null +++ b/src/transaction/decoder/Uint256Decoder.tsx @@ -0,0 +1,69 @@ +import React, { useState } from "react"; +import { BigNumber } from "@ethersproject/bignumber"; +import { hexlify, hexZeroPad } from "@ethersproject/bytes"; +import { commify, formatEther } from "@ethersproject/units"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faSync } from "@fortawesome/free-solid-svg-icons/faSync"; + +type Uint256DecoderProps = { + r: any; +}; + +enum DisplayMode { + RAW, + EIGHTEEN_DECIMALS, + HEX, + _LAST, +} + +const VERY_BIG_NUMBER = BigNumber.from(10).pow(BigNumber.from(36)); + +const initDisplayMode = (r: any): DisplayMode => { + const n = BigNumber.from(r); + if (n.gte(VERY_BIG_NUMBER)) { + return DisplayMode.HEX; + } + return DisplayMode.RAW; +}; + +const Uint256Decoder: React.FC = ({ r }) => { + const [displayMode, setDisplayMode] = useState( + initDisplayMode(r) + ); + + const toggleModes = () => { + const next = displayMode + 1; + setDisplayMode(next === DisplayMode._LAST ? 0 : next); + }; + + return ( +
+ + + {displayMode === DisplayMode.RAW ? ( + <>{commify(r.toString())} + ) : displayMode === DisplayMode.HEX ? ( + <>{hexZeroPad(hexlify(r), 32)} + ) : ( + <>{commify(formatEther(r))} + )} + +
+ ); +}; + +export default React.memo(Uint256Decoder); diff --git a/src/types.ts b/src/types.ts index 5a5dad9..5904b31 100644 --- a/src/types.ts +++ b/src/types.ts @@ -108,6 +108,4 @@ export type TokenMeta = { decimals: number; }; -export type TokenMetas = { - [tokenAddress: string]: TokenMeta; -}; +export type TokenMetas = Record; diff --git a/src/use4Bytes.ts b/src/use4Bytes.ts index dad9f75..9fe9252 100644 --- a/src/use4Bytes.ts +++ b/src/use4Bytes.ts @@ -2,16 +2,48 @@ import { useState, useEffect, useContext } from "react"; import { RuntimeContext } from "./useRuntime"; import { fourBytesURL } from "./url"; -const cache = new Map(); +export type FourBytesEntry = { + name: string; + signature: string | undefined; +}; + +const simpleTransfer: FourBytesEntry = { + name: "Transfer", + signature: undefined, +}; + +const fullCache = new Map(); + +export const rawInputTo4Bytes = (rawInput: string) => rawInput.slice(0, 10); + +/** + * Extract 4bytes DB info + * + * @param rawFourBytes an hex string containing the 4bytes signature in the "0xXXXXXXXX" format. + */ +export const use4Bytes = ( + rawFourBytes: string +): FourBytesEntry | null | undefined => { + if (rawFourBytes !== "0x") { + if (rawFourBytes.length !== 10 || !rawFourBytes.startsWith("0x")) { + throw new Error( + `rawFourBytes must contain a 4 bytes hex method signature starting with 0x; received value: "${rawFourBytes}"` + ); + } + } -export const use4Bytes = (rawFourBytes: string) => { const runtime = useContext(RuntimeContext); const assetsURLPrefix = runtime.config?.assetsURLPrefix; - const [name, setName] = useState(); - const [fourBytes, setFourBytes] = useState(); + const fourBytes = rawFourBytes.slice(2); + const [entry, setEntry] = useState( + fullCache.get(fourBytes) + ); useEffect(() => { - if (assetsURLPrefix === undefined || fourBytes === undefined) { + if (assetsURLPrefix === undefined) { + return; + } + if (fourBytes === "") { return; } @@ -20,51 +52,47 @@ export const use4Bytes = (rawFourBytes: string) => { .then(async (res) => { if (!res.ok) { console.error(`Signature does not exist in 4bytes DB: ${fourBytes}`); - - // Use the default 4 bytes as name - setName(rawFourBytes); - cache.set(fourBytes, null); + fullCache.set(fourBytes, null); + setEntry(null); return; } - const sig = await res.text(); + // Get only the first occurrence, for now ignore alternative param names + const sigs = await res.text(); + const sig = sigs.split(";")[0]; const cut = sig.indexOf("("); let method = sig.slice(0, cut); method = method.charAt(0).toUpperCase() + method.slice(1); - setName(method); - cache.set(fourBytes, method); - return; + + const entry: FourBytesEntry = { + name: method, + signature: sig, + }; + setEntry(entry); + fullCache.set(fourBytes, entry); }) .catch((err) => { console.error(`Couldn't fetch signature URL ${signatureURL}`, err); - - // Use the default 4 bytes as name - setName(rawFourBytes); + setEntry(null); + fullCache.set(fourBytes, null); }); - }, [rawFourBytes, assetsURLPrefix, fourBytes]); + }, [fourBytes, assetsURLPrefix]); if (rawFourBytes === "0x") { - return "Transfer"; + return simpleTransfer; } if (assetsURLPrefix === undefined) { - return rawFourBytes; + return undefined; } // Try to resolve 4bytes name - const entry = cache.get(rawFourBytes.slice(2)); - if (entry === null) { - return rawFourBytes; - } - if (entry !== undefined) { - // Simulates LRU - cache.delete(entry); - cache.set(rawFourBytes.slice(2), entry); + if (entry === null || entry === undefined) { return entry; } - if (name === undefined && fourBytes === undefined) { - setFourBytes(rawFourBytes.slice(2)); - return ""; - } - return name; + // Simulates LRU + // TODO: implement LRU purging + fullCache.delete(fourBytes); + fullCache.set(fourBytes, entry); + return entry; }; diff --git a/src/useSourcify.ts b/src/useSourcify.ts index b60fde9..0d6ea59 100644 --- a/src/useSourcify.ts +++ b/src/useSourcify.ts @@ -3,6 +3,33 @@ import { Interface } from "@ethersproject/abi"; import { TransactionData } from "./types"; import { sourcifyMetadata, SourcifySource, sourcifySourceFile } from "./url"; +export type UserMethod = { + notice?: string | undefined; +}; + +export type UserEvent = { + notice?: string | undefined; +}; + +export type UserDoc = { + kind: "user"; + version?: number | undefined; + notice?: string | undefined; + methods: Record; + events: Record; +}; + +export type DevMethod = { + params?: Record; + returns?: Record; +}; + +export type DevDoc = { + kind: "dev"; + version?: number | undefined; + methods: Record; +}; + export type Metadata = { version: string; language: string; @@ -33,8 +60,8 @@ export type Metadata = { }; output: { abi: any[]; - userdocs: any[]; - devdoc: any[]; + userdoc?: UserDoc | undefined; + devdoc?: DevDoc | undefined; }; }; diff --git a/trustwallet b/trustwallet index 7bfa06a..d612796 160000 --- a/trustwallet +++ b/trustwallet @@ -1 +1 @@ -Subproject commit 7bfa06acc125a4874d86bc1fa8e4547a46846e31 +Subproject commit d612796060acaa8a621b1dd25c1a41a24452953e
@@ -23,6 +29,15 @@ const DecodedParamsTable: React.FC = ({ type value
+ {paramTypes.length > 0 && paramTypes[0].name !== null + ? "Parameter names are estimated." + : "Parameter names are not available."} +