diff --git a/examples/contract-verification/package.json b/examples/contract-verification/package.json index e50457d2..cb054eb9 100644 --- a/examples/contract-verification/package.json +++ b/examples/contract-verification/package.json @@ -54,7 +54,7 @@ }, "dependencies": { "@nomiclabs/hardhat-ethers": "^2.1.0", - "@tenderly/hardhat-tenderly": "^1.3.0", + "@tenderly/hardhat-tenderly": "^1.3.2", "dotenv": "^16.0.1", "hardhat": "^2.10.2" } diff --git a/examples/contract-verification/yarn.lock b/examples/contract-verification/yarn.lock index d13ef323..975f8085 100644 --- a/examples/contract-verification/yarn.lock +++ b/examples/contract-verification/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -778,10 +783,10 @@ "@sentry/types" "5.30.0" tslib "^1.9.3" -"@tenderly/hardhat-tenderly@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.3.0.tgz#7bc3b3a9541b8f255c88ec5018d2e53e20e16368" - integrity sha512-cQ1hiubv7z6A1ZpYBJwCDzmyG6d5Eh/lpcsT+e8QEBZewSUsEmb82BploBRHXGV5d/pRvzWN4xhGKLP6HB38VA== +"@tenderly/hardhat-tenderly@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.3.2.tgz#9ee69ba1fb8650d18160c637e8e487d938f6dcea" + integrity sha512-0kE0gv8RIu0N5JXKCCfYcydsMgGgj8z3qCvbeD/ynBKwOBvbFB+NZFRyTHNopbeaUKO7Q3bGFau8vS1B0EWS0g== dependencies: "@ethersproject/bignumber" "^5.7.0" "@nomiclabs/hardhat-ethers" "^2.1.1" @@ -791,6 +796,7 @@ hardhat "^2.10.2" hardhat-deploy "^0.11.14" js-yaml "^4.1.0" + tenderly "^0.0.3" "@tsconfig/node10@^1.0.7": version "1.0.9" @@ -1015,6 +1021,14 @@ abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: module-error "^1.0.1" queue-microtask "^1.2.3" +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -1139,6 +1153,11 @@ array-back@^4.0.1, array-back@^4.0.2: resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + array-includes@^3.1.4: version "3.1.6" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" @@ -1273,6 +1292,24 @@ bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1490,6 +1527,15 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-table3@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -1560,11 +1606,38 @@ commander@3.0.2: resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== +commander@^9.4.0: + version "9.4.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" + integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + cookie@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" @@ -1612,6 +1685,13 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +debug@2.6.9, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -1619,13 +1699,6 @@ debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, de dependencies: ms "2.1.2" -debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -1655,6 +1728,11 @@ deep-is@^0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" @@ -1673,6 +1751,11 @@ depd@2.0.0: resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + diff@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" @@ -1709,6 +1792,11 @@ dotenv@^16.0.1: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" @@ -1732,6 +1820,11 @@ encode-utf8@^1.0.2: resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + enquirer@^2.3.0, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -1795,6 +1888,11 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -1967,6 +2065,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" @@ -2087,6 +2190,43 @@ evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" +express@^4.18.1: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -2139,6 +2279,19 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + find-replace@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" @@ -2200,6 +2353,11 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + fp-ts@1.19.3: version "1.19.3" resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" @@ -2210,6 +2368,11 @@ fp-ts@^1.0.0: resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + fs-extra@^0.30.0: version "0.30.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" @@ -2556,6 +2719,11 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +hyperlinker@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" + integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== + iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -2630,6 +2798,11 @@ io-ts@1.10.4: dependencies: fp-ts "^1.0.0" +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -2676,6 +2849,11 @@ is-date-object@^1.0.1: dependencies: has-tostringtag "^1.0.0" +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -2766,6 +2944,13 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -2849,6 +3034,11 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + level-supports@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-4.0.1.tgz#431546f9d81f10ff0fea0e74533a0e875c08c66a" @@ -2971,6 +3161,11 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + memory-level@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/memory-level/-/memory-level-1.0.0.tgz#7323c3fd368f9af2f71c3cd76ba403a17ac41692" @@ -2985,11 +3180,21 @@ memorystream@^0.3.1: resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" integrity sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw== +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + micromatch@^4.0.4: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" @@ -3003,13 +3208,18 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12: +mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -3127,6 +3337,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + node-addon-api@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" @@ -3181,6 +3396,13 @@ obliterator@^2.0.0: resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.4.tgz#fa650e019b2d075d745e44f1effeb13a2adbe816" integrity sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ== +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -3188,6 +3410,15 @@ once@^1.3.0: dependencies: wrappy "1" +open@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" + integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -3257,6 +3488,11 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -3282,6 +3518,11 @@ path-parse@^1.0.6, path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -3325,12 +3566,28 @@ prettier@^2.3.1, prettier@^2.7.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== +prompts@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -qs@^6.7.0, qs@^6.9.4: +qs@6.11.0, qs@^6.7.0, qs@^6.9.4: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== @@ -3349,7 +3606,12 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" -raw-body@^2.4.1: +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1, raw-body@^2.4.1: version "2.5.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== @@ -3478,7 +3740,7 @@ rustbn.js@~0.2.0: resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -3528,6 +3790,25 @@ semver@^7.3.7: dependencies: lru-cache "^6.0.0" +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -3535,6 +3816,16 @@ serialize-javascript@6.0.0: dependencies: randombytes "^2.1.0" +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -3574,6 +3865,11 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -3743,6 +4039,20 @@ table@^6.8.0: string-width "^4.2.3" strip-ansi "^6.0.1" +tenderly@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tenderly/-/tenderly-0.0.3.tgz#8c85e287e080073502420d5c6f13f4762d0f59cd" + integrity sha512-dVf2uxrIOeLDRNDEXcQlV2xJt50TIx8zGQKlNj1deYTV3FYu2L0zheHBHaDU12GqAff2iiGYk+fKqFkK0bB0+w== + dependencies: + axios "^0.27.2" + cli-table3 "^0.6.2" + commander "^9.4.0" + express "^4.18.1" + hyperlinker "^1.0.0" + js-yaml "^4.1.0" + open "^8.4.0" + prompts "^2.4.2" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -3865,6 +4175,14 @@ type-fest@^0.7.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + typechain@^8.1.0: version "8.1.1" resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.1.1.tgz#9c2e8012c2c4c586536fc18402dcd7034c4ff0bd" @@ -3923,7 +4241,7 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== -unpipe@1.0.0: +unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== @@ -3940,6 +4258,11 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -3950,6 +4273,11 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" diff --git a/packages/tenderly-core/CHANGELOG.md b/packages/tenderly-core/CHANGELOG.md index 88343160..98b40d0e 100644 --- a/packages/tenderly-core/CHANGELOG.md +++ b/packages/tenderly-core/CHANGELOG.md @@ -1,5 +1,11 @@ # tenderly +## 0.0.3 + +### Patch Changes + +- [#88](https://github.com/Tenderly/hardhat-tenderly/pull/88) [`913aad5`](https://github.com/Tenderly/hardhat-tenderly/commit/913aad5b23e3c3c170a600b7153dfe085be34919) Thanks [@Riphal](https://github.com/Riphal)! - Remove got package, start using axios. + ## 0.0.2 ### Patch Changes diff --git a/packages/tenderly-core/package.json b/packages/tenderly-core/package.json index d2a18fc7..71bb5d78 100644 --- a/packages/tenderly-core/package.json +++ b/packages/tenderly-core/package.json @@ -4,7 +4,7 @@ "license": "MIT", "homepage": "https://tenderly.co", "description": "", - "version": "0.0.2", + "version": "0.0.3", "main": "internal/lib/tenderly-lib.js", "types": "internal/lib/tenderly-lib.d.ts", "repository": { @@ -55,7 +55,8 @@ "hyperlinker": "^1.0.0", "js-yaml": "^4.1.0", "open": "^8.4.0", - "prompts": "^2.4.2" + "prompts": "^2.4.2", + "tslog": "^4.4.0" }, "peerDependencies": { "ts-node": "*", @@ -69,4 +70,4 @@ "optional": true } } -} \ No newline at end of file +} diff --git a/packages/tenderly-core/src/internal/cli/commands/LoginCommand.ts b/packages/tenderly-core/src/internal/cli/commands/LoginCommand.ts index 04bae70e..764f0d2a 100644 --- a/packages/tenderly-core/src/internal/cli/commands/LoginCommand.ts +++ b/packages/tenderly-core/src/internal/cli/commands/LoginCommand.ts @@ -2,32 +2,43 @@ import open from "open"; import axios from "axios"; import prompts from "prompts"; import commander from "commander"; +import { logger } from "../../../utils/logger"; import { isAccessTokenSet, setAccessToken } from "../../../utils/config"; import { TENDERLY_API_BASE_URL, TENDERLY_DASHBOARD_BASE_URL } from "../../../common/constants"; export const LoginCommand = new commander.Command("login").description("login to Tenderly").action(async () => { + logger.info("Trying to login to Tenderly."); + if (isAccessTokenSet()) { + logger.debug("Access token is already set. Checking if access token overwrite is needed."); const response = await prompts({ type: "confirm", name: "overwrite", message: "Access token already set. Would you like to overwrite it?", }); if (!response.overwrite) { + logger.debug("Access token overwrite skipped. Trying to login with the existing token."); return; } } + logger.info("Access token not set."); const accessToken = await promptAccessToken(); + logger.debug("Access token accepted. Trying to log in."); setAccessToken(accessToken); - console.log("Successfully logged in."); + + console.log("Successfully logged in to Tenderly."); + logger.info("Successfully logged in to Tenderly."); }); async function promptAccessToken(): Promise { - console.log(`Redirecting to ${TENDERLY_DASHBOARD_BASE_URL}/account/authorization`); + console.log(`Redirecting to ${TENDERLY_DASHBOARD_BASE_URL}/account/authorization`) + logger.debug(`Redirecting to ${TENDERLY_DASHBOARD_BASE_URL}/account/authorization`); await open(`${TENDERLY_DASHBOARD_BASE_URL}/account/authorization`); + logger.info("Requesting access token."); const response = await prompts({ type: "text", name: "accessToken", @@ -35,6 +46,7 @@ async function promptAccessToken(): Promise { validate: validator, }); + logger.info("Access token accepted."); return response.accessToken; } @@ -53,14 +65,18 @@ const validator = async function (value: string) { async function canAuthenticate(accessToken: string): Promise { try { + logger.debug("Checking if access token is valid."); const response = await axios.get(`${TENDERLY_API_BASE_URL}/api/v1/user`, { headers: { "x-access-key": accessToken }, }); - if (response.data.user !== undefined) { - return true; + if (response.data.user === undefined || response.data.user === null) { + logger.error("Access token is invalid."); + return false; } - return false; + logger.debug("Access token is valid."); + return true; } catch (err) { + logger.error("Authentication error."); return false; } } diff --git a/packages/tenderly-core/src/internal/cli/commands/NetworksCommand.ts b/packages/tenderly-core/src/internal/cli/commands/NetworksCommand.ts index b1c68f00..4562a1cd 100644 --- a/packages/tenderly-core/src/internal/cli/commands/NetworksCommand.ts +++ b/packages/tenderly-core/src/internal/cli/commands/NetworksCommand.ts @@ -1,9 +1,11 @@ import Table from "cli-table3"; import commander from "commander"; +import { logger } from "../../../utils/logger"; import { PLUGIN_NAME } from "../../../common/constants"; import { TenderlyService } from "../../core/services"; import { TenderlyNetwork } from "../../core/types"; +import { convertToLogCompliantNetworks } from "../../../utils/log-compliance"; const tenderlyService = new TenderlyService(PLUGIN_NAME); @@ -22,6 +24,9 @@ export const NetworksCommand = new commander.Command("networks") const filteredNetworks = networks.filter(isNotExcluded); filteredNetworks.sort((a, b) => a.sort_order - b.sort_order); + const logCompliantNetworks = convertToLogCompliantNetworks(filteredNetworks); + logger.silly("Obtained filtered public networks:", logCompliantNetworks); + const table = new Table({ style: { head: ["magenta"] }, head: headers, @@ -39,6 +44,7 @@ export const NetworksCommand = new commander.Command("networks") }) )) ); + logger.silly("Networks table:", table); console.log(table.toString()); }); diff --git a/packages/tenderly-core/src/internal/core/common/logger.ts b/packages/tenderly-core/src/internal/core/common/logger.ts deleted file mode 100644 index ecae80a4..00000000 --- a/packages/tenderly-core/src/internal/core/common/logger.ts +++ /dev/null @@ -1,23 +0,0 @@ -const API_ERR_MSG = "Unexpected error occurred. \n Error reason %s %s. \n Error context: %s"; - -export function logApiError(err: any) { - // api error - if ("response" in err) { - const code = err?.response?.status; - const codeText = err?.response?.statusText; - let message = "No message"; - if (err.response?.data?.error?.message) { - message = err.response.data.error.message; - } else if (err.response?.data) { - message = err.response.data; - } - - console.log(API_ERR_MSG, code, codeText, message); - return; - } - - // general error - if (err instanceof Error) { - console.log(err.message); - } -} diff --git a/packages/tenderly-core/src/internal/core/services/TenderlyApiService.ts b/packages/tenderly-core/src/internal/core/services/TenderlyApiService.ts index 667b981b..51ee3ee2 100644 --- a/packages/tenderly-core/src/internal/core/services/TenderlyApiService.ts +++ b/packages/tenderly-core/src/internal/core/services/TenderlyApiService.ts @@ -1,32 +1,59 @@ import * as axios from "axios"; +import { logger } from "../../../utils/logger"; import { getConfig, isAccessTokenSet } from "../../../utils/config"; import { TENDERLY_API_BASE_URL, TENDERLY_JSON_RPC_BASE_URL } from "../../../common/constants"; export class TenderlyApiService { public static configureInstance(): axios.AxiosInstance { + logger.debug("Configuring instance."); + const tdlyConfig = getConfig(); - return axios.default.create({ + const params = { baseURL: TENDERLY_API_BASE_URL, headers: { "x-access-key": tdlyConfig.access_key }, + }; + + logger.debug("Configured instance with parameters:", { + baseURL: TENDERLY_API_BASE_URL, + access_key: + tdlyConfig.access_key !== undefined && tdlyConfig.access_key !== null && tdlyConfig.access_key !== "" + ? "super secret access_key is set in 'access_key' field" + : "undefined or null or empty string", }); + + return axios.default.create(params); } public static configureAnonymousInstance(): axios.AxiosInstance { + logger.debug("Configured anonymous instance towards tenderly api."); + return axios.default.create({ baseURL: TENDERLY_API_BASE_URL, }); } public static configureTenderlyRPCInstance(): axios.AxiosInstance { + logger.debug("Configuring tenderly RPC instance."); + const tdlyConfig = getConfig(); - return axios.default.create({ + const params = { baseURL: TENDERLY_JSON_RPC_BASE_URL, headers: { "x-access-key": tdlyConfig.access_key, Head: tdlyConfig.head !== undefined ? tdlyConfig.head : "", }, + }; + + logger.debug("Configured tenderly rpc instance with parameters:", { + baseURL: TENDERLY_API_BASE_URL, + access_key: + tdlyConfig.access_key !== undefined && tdlyConfig.access_key !== null && tdlyConfig.access_key !== "" + ? "super secret access_key is set in 'access_key' field" + : "undefined or null or empty string", }); + + return axios.default.create(params); } public static isAuthenticated(): boolean { diff --git a/packages/tenderly-core/src/internal/core/services/TenderlyService.ts b/packages/tenderly-core/src/internal/core/services/TenderlyService.ts index 743a0a98..a76fb884 100644 --- a/packages/tenderly-core/src/internal/core/services/TenderlyService.ts +++ b/packages/tenderly-core/src/internal/core/services/TenderlyService.ts @@ -1,5 +1,4 @@ import { TENDERLY_DASHBOARD_BASE_URL, CHAIN_ID_NETWORK_NAME_MAP } from "../../../common/constants"; -import { logApiError } from "../common/logger"; import { API_VERIFICATION_REQUEST_ERR_MSG, BYTECODE_MISMATCH_ERR_MSG, @@ -19,7 +18,14 @@ import { TenderlyContractUploadRequest, TenderlyForkContractUploadRequest, } from "../types"; +import { logger } from "../../../utils/logger"; import { TenderlyApiService } from "./TenderlyApiService"; +import { + convertToLogCompliantApiError, + convertToLogCompliantNetworks, + convertToLogCompliantProjects, + convertToLogCompliantVerificationResponse +} from "../../../utils/log-compliance"; export class TenderlyService { private pluginName: string; @@ -29,6 +35,8 @@ export class TenderlyService { } public async getNetworks(): Promise { + logger.debug("Obtaining public networks."); + let tenderlyApi = TenderlyApiService.configureAnonymousInstance(); if (TenderlyApiService.isAuthenticated()) { tenderlyApi = TenderlyApiService.configureInstance(); @@ -36,15 +44,25 @@ export class TenderlyService { try { const res = await tenderlyApi.get("/api/v1/public-networks"); + if (res.data === undefined || res.data === null) { + logger.error("There was an error while obtaining public networks from Tenderly. Obtained response is invalid."); + return []; + } + const logCompliantNetworks = convertToLogCompliantNetworks(res.data); + logger.silly("Obtained public networks:", logCompliantNetworks); + return res.data; } catch (err) { - logApiError(err); + const logCompliantApiErr = convertToLogCompliantApiError(err); + logger.error(logCompliantApiErr); console.log(`Error in ${this.pluginName}: ${NETWORK_FETCH_FAILED_ERR_MSG}`); } return []; } public async getLatestBlockNumber(networkId: string): Promise { + logger.debug("Getting latest block number."); + let tenderlyApi = TenderlyApiService.configureAnonymousInstance(); if (TenderlyApiService.isAuthenticated()) { tenderlyApi = TenderlyApiService.configureInstance(); @@ -52,15 +70,26 @@ export class TenderlyService { try { const res = await tenderlyApi.get(`/api/v1/network/${networkId}/block-number`); + if (res.data === undefined || res.data === null) { + logger.error( + "There was an error while obtaining latest block number from Tenderly. Obtained response is invalid." + ); + return null; + } + logger.trace(`Api successfully returned: ${res.data.block_number}`); + return res.data.block_number; } catch (err) { - logApiError(err); - console.log(`Error in ${this.pluginName}: ${LATEST_BLOCK_NUMBER_FETCH_FAILED_ERR_MSG}`); + const logCompliantApiErr = convertToLogCompliantApiError(err); + logger.error(logCompliantApiErr); + logger.error(`Error in ${this.pluginName}: ${LATEST_BLOCK_NUMBER_FETCH_FAILED_ERR_MSG}`); } return null; } public async verifyContracts(request: TenderlyContractUploadRequest): Promise { + logger.debug("Verifying contracts publicly."); + let tenderlyApi = TenderlyApiService.configureAnonymousInstance(); if (TenderlyApiService.isAuthenticated()) { tenderlyApi = TenderlyApiService.configureInstance(); @@ -68,15 +97,28 @@ export class TenderlyService { try { if (request.contracts.length === 0) { - console.log(NO_VERIFIABLE_CONTRACTS_ERR_MSG); + logger.error(NO_VERIFIABLE_CONTRACTS_ERR_MSG); return; } const res = await tenderlyApi.post("/api/v1/public/verify-contracts", { ...request }); + if (res.data === undefined || res.data === null) { + logger.error( + "There was an error while publicly verifying contracts on Tenderly. Obtained response is invalid." + ); + return; + } + const logCompliantVerificationResponse = convertToLogCompliantVerificationResponse(res.data); + logger.trace("Verification response:", logCompliantVerificationResponse); const responseData: ContractResponse = res.data; if (responseData.bytecode_mismatch_errors !== null) { - console.log(`Error in ${this.pluginName}: ${BYTECODE_MISMATCH_ERR_MSG}`); + logger.error(`Error in ${this.pluginName}: ${BYTECODE_MISMATCH_ERR_MSG}`); + return; + } + + if (responseData.contracts === undefined || responseData.contracts === null) { + logger.error("There was an error during public verification. There are no returned contracts."); return; } @@ -86,7 +128,7 @@ export class TenderlyService { addresses += `${cont.contractName}, `; } - console.log(`Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, addresses); + logger.error(`Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, addresses); return; } @@ -101,8 +143,9 @@ export class TenderlyService { } console.groupEnd(); } catch (err) { - logApiError(err); - console.log(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); + const logCompliantApiError = convertToLogCompliantApiError(err); + logger.error(logCompliantApiError); + logger.error(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); } } @@ -111,8 +154,9 @@ export class TenderlyService { tenderlyProject: string, username: string ): Promise { + logger.debug("Pushing contracts onto Tenderly."); if (!TenderlyApiService.isAuthenticated()) { - console.log(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); return; } @@ -121,10 +165,16 @@ export class TenderlyService { const res = await tenderlyApi.post(`/api/v1/account/${username}/project/${tenderlyProject}/contracts`, { ...request, }); + if (res.data === undefined || res.data === null) { + logger.error("There was an error while pushing contracts to Tenderly. Obtained response is invalid."); + return; + } + const logCompliantVerificationResponse = convertToLogCompliantVerificationResponse(res.data); + logger.trace("Verification response:", logCompliantVerificationResponse); const responseData: ContractResponse = res.data; if (responseData.bytecode_mismatch_errors !== null) { - console.log(`Error in ${this.pluginName}: ${BYTECODE_MISMATCH_ERR_MSG}`); + logger.error(`Error in ${this.pluginName}: ${BYTECODE_MISMATCH_ERR_MSG}`); return; } @@ -134,7 +184,7 @@ export class TenderlyService { addresses += `${cont.contractName}, `; } - console.log(`Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, addresses); + logger.error(`Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, addresses); return; } @@ -143,8 +193,9 @@ export class TenderlyService { `Successfully privately verified Smart Contracts for project ${tenderlyProject}. You can view your contracts at ${dashLink}` ); } catch (err) { - logApiError(err); - console.log(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); + const logCompliantApiError = convertToLogCompliantApiError(err); + logger.error(logCompliantApiError); + logger.error(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); } } @@ -154,8 +205,10 @@ export class TenderlyService { username: string, fork: string ): Promise { + logger.info("Verifying contracts on fork."); + if (!TenderlyApiService.isAuthenticated()) { - console.log(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); return; } @@ -164,10 +217,15 @@ export class TenderlyService { const res = await tenderlyApi.post(`/account/${username}/project/${tenderlyProject}/fork/${fork}/verify`, { ...request, }); + if (res.data === undefined || res.data === null) { + logger.error("There was an error while verifying contracts on fork. Obtained response is invalid."); + } + const logCompliantVerificationResponse = convertToLogCompliantVerificationResponse(res.data); + logger.trace("Verification response:", logCompliantVerificationResponse); const responseData: ContractResponse = res.data; if (responseData.bytecode_mismatch_errors !== null) { - console.log(BYTECODE_MISMATCH_ERR_MSG); + logger.error(BYTECODE_MISMATCH_ERR_MSG); return; } @@ -177,7 +235,7 @@ export class TenderlyService { addresses += `${cont.contractName}, `; } - console.log(`Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, addresses); + logger.error(`Error in ${this.pluginName}: ${NO_NEW_CONTRACTS_VERIFIED_ERR_MSG}`, addresses); return; } @@ -187,44 +245,62 @@ export class TenderlyService { } console.groupEnd(); } catch (err) { - logApiError(err); - console.log(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); + const logCompliantApiError = convertToLogCompliantApiError(err); + logger.error(logCompliantApiError); + logger.error(`Error in ${this.pluginName}: ${API_VERIFICATION_REQUEST_ERR_MSG}`); } } public async getPrincipal(): Promise { + logger.debug("Getting principal."); + if (!TenderlyApiService.isAuthenticated()) { - console.log(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); return null; } const tenderlyApi = TenderlyApiService.configureInstance(); try { const res = await tenderlyApi.get("/api/v1/user"); + if (res.data === undefined || res.data === null) { + logger.error("There was an error while obtaining principal from Tenderly. Obtained response is invalid."); + } + logger.trace("Retrieved data:", { id: res.data.user.id }); + return { id: res.data.user.id, username: res.data.user.username, }; } catch (err) { - logApiError(err); - console.log(`Error in ${this.pluginName}: ${PRINCIPAL_FETCH_FAILED_ERR_MSG}`); + const logCompliantApiError = convertToLogCompliantApiError(err); + logger.error(logCompliantApiError); + logger.error(`Error in ${this.pluginName}: ${PRINCIPAL_FETCH_FAILED_ERR_MSG}`); } return null; } public async getProjectSlugs(principalId: string): Promise { + logger.debug("Getting project slugs."); + if (!TenderlyApiService.isAuthenticated()) { - console.log(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); + logger.error(`Error in ${this.pluginName}: ${ACCESS_TOKEN_NOT_PROVIDED_ERR_MSG}`); return []; } const tenderlyApi = TenderlyApiService.configureInstance(); try { const res = await tenderlyApi.get(`/api/v1/account/${principalId}/projects`); + if (res.data === undefined || res.data === null) { + logger.error("There was an error while obtaining project slug from Tenderly. Obtained response is invalid."); + } + const logCompliantProjects = convertToLogCompliantProjects(res.data.projects); + logger.trace("Obtained projects:", logCompliantProjects); + return res.data.projects; } catch (err) { - logApiError(err); - console.log(`Error in ${this.pluginName}: ${PROJECTS_FETCH_FAILED_ERR_MSG}`); + const logCompliantApiError = convertToLogCompliantApiError(err); + logger.error(logCompliantApiError); + logger.error(`Error in ${this.pluginName}: ${PROJECTS_FETCH_FAILED_ERR_MSG}`); } return []; } diff --git a/packages/tenderly-core/src/internal/core/types/Contract.ts b/packages/tenderly-core/src/internal/core/types/Contract.ts index f04599b4..2b4f9362 100644 --- a/packages/tenderly-core/src/internal/core/types/Contract.ts +++ b/packages/tenderly-core/src/internal/core/types/Contract.ts @@ -39,12 +39,37 @@ export interface ContractNetwork { } export interface ApiContract { - address: string; + id: string; + contract_id: string; + balance: string; network_id: string; + public: boolean; + export: boolean; + verification_date: string; + address: string; + contract_name: string; + ens_domain: string[]; + type: string; + evm_version: string; + compiler_version: string; + optimizations_used: boolean; + optimization_runs: number; + libraries: Record; + data: object; + creation_block: number; + creation_tx: string; + creator_address: string; + created_at: string; + number_of_watches: number; + language: string; + in_project: boolean; + number_of_files: number; } export interface BytecodeMismatchError { contract_id: string; expected: string; got: string; + similarity: number; + assumed_reason: string; } diff --git a/packages/tenderly-core/src/utils/config.ts b/packages/tenderly-core/src/utils/config.ts index 5ae171ed..28387af6 100644 --- a/packages/tenderly-core/src/utils/config.ts +++ b/packages/tenderly-core/src/utils/config.ts @@ -2,17 +2,28 @@ import fs from "fs"; import os from "os"; import path from "path"; import * as yaml from "js-yaml"; - import { TenderlyConfig } from "../types"; +import { logger } from "./logger"; +import { convertToLogCompliantTenderlyConfig } from "./log-compliance"; const configDir = `${os.homedir() + path.sep}.tenderly`; export const configFilePath = `${configDir + path.sep}config.yaml`; export function getConfig(): TenderlyConfig { + logger.trace("Getting tenderly config."); + if (configExists()) { const fileData = fs.readFileSync(configFilePath); - return yaml.load(fileData.toString()) as TenderlyConfig; + + const tenderlyConfig = yaml.load(fileData.toString()) as TenderlyConfig; + + const logCompliantTenderlyConfig = convertToLogCompliantTenderlyConfig(tenderlyConfig); + logger.trace("Checking config:", logCompliantTenderlyConfig); + + return tenderlyConfig; } + + logger.warn("Tenderly config doesn't exist, empty string values are returned instead."); return { access_key: "", access_key_id: "", @@ -24,27 +35,45 @@ export function getConfig(): TenderlyConfig { } export function writeConfig(config: TenderlyConfig): void { + logger.trace(`Writing tenderly config to a file @ ${configDir}/${configFilePath}`); + + const logCompliantTenderlyConfig = convertToLogCompliantTenderlyConfig(config); + logger.trace("Checking config:", logCompliantTenderlyConfig); + fs.mkdirSync(configDir, { recursive: true }); fs.writeFileSync(configFilePath, yaml.dump(config), "utf8"); } export function configExists(): boolean { - return fs.existsSync(configFilePath); + logger.trace("Checking if tenderly config exists."); + const exists = fs.existsSync(configFilePath); + logger.trace(exists ? "Tenderly config exists." : "Tenderly config doesn't exist."); + + return exists; } export function isAccessTokenSet(): boolean { + logger.trace("Determining if access token in tenderly config file is set."); const config = getConfig(); - return config.access_key !== undefined || config.access_key !== ""; + + const isSet = config.access_key !== undefined && config.access_key !== null && config.access_key !== ""; + logger.trace(isSet ? "Access key is set." : "Access key is not set."); + + return isSet; } export function getAccessToken(): string { + logger.trace("Getting access token."); if (!isAccessTokenSet()) { + logger.warn("Access key is not set, returning empty string value."); return ""; } + return getConfig().access_key; } export function setAccessToken(accessToken: string): void { + logger.trace("Setting access key."); const config = getConfig(); config.access_key = accessToken; writeConfig(config); diff --git a/packages/tenderly-core/src/utils/log-compliance.ts b/packages/tenderly-core/src/utils/log-compliance.ts new file mode 100644 index 00000000..d6d71795 --- /dev/null +++ b/packages/tenderly-core/src/utils/log-compliance.ts @@ -0,0 +1,177 @@ +import { + ApiContract, + BytecodeMismatchError, + ContractResponse, +} from "../internal/core/types"; +import { TenderlyConfig } from "../types"; + +export function convertToLogCompliantApiError(err: any) { + // api error + if ("response" in err) { + const code = err?.response?.status; + const codeText = err?.response?.statusText; + let message = "No message"; + if (err.response?.data?.error?.message) { + message = err.response.data.error.message; + } else if (err.response?.data) { + message = err.response.data; + } + return `Unexpected error occurred. \n Error reason ${code} ${codeText}. \n Error context: ${message}`; + } + + // general error + if (err instanceof Error) { + return err.message; + } +} + +export function convertToLogCompliantVerificationResponse(res: ContractResponse) { + const logCompliantContracts = convertToLogCompliantContracts(res.contracts); + const logCompliantBytecodeMismatchErrors = convertToLogCompliantBytecodeMismatchErrors(res.bytecode_mismatch_errors); + + return { + contracts: logCompliantContracts, + bytecode_mismatch_errors: logCompliantBytecodeMismatchErrors, + } +} + +export function convertToLogCompliantContracts(contracts: ApiContract[]) { + if (contracts === undefined || contracts === null) { + return undefined; + } + + const logCompliantContracts = []; + for (const contract of contracts) { + logCompliantContracts.push({ + id: contract.id, + contract_id: contract.contract_id, + balance: contract.balance, + network_id: contract.network_id, + public: contract.public, + export: contract.export, + verification_date: contract.verification_date, + address: contract.address, + contract_name: contract.contract_name, + ens_domain: contract.ens_domain, + type: contract.type, + evm_version: contract.evm_version, + compiler_version: contract.compiler_version, + optimizations_used: contract.optimizations_used, + optimization_runs: contract.optimization_runs, + libraries: contract.libraries, + data: contract.data, + creation_block: contract.creation_block, + creation_tx: contract.creation_tx, + creator_address: contract.creator_address, + created_at: contract.created_at, + number_of_watches: contract.number_of_watches, + language: contract.language, + in_project: contract.in_project, + number_of_files: contract.number_of_files, + }); + } + return logCompliantContracts; +} + +export function convertToLogCompliantBytecodeMismatchErrors(bytecodeMismatchErrors: BytecodeMismatchError[]) { + if (bytecodeMismatchErrors === undefined || bytecodeMismatchErrors === null) { + return undefined; + } + + const logCompliantBytecodeMismatchErrors = []; + for (const err of bytecodeMismatchErrors) { + logCompliantBytecodeMismatchErrors.push({ + contract_id: err.contract_id, + expected: err.expected, + got: err.got, + similarity: err.similarity, + assumed_reason: err.assumed_reason, + }); + } + return logCompliantBytecodeMismatchErrors; +} + +export function convertToLogCompliantProjects(projects: any[]) { + if (projects === undefined || projects === null) { + return undefined; + } + + const logCompliantProjects = []; + for (const project of projects) { + logCompliantProjects.push({ + project_id: project.id, + project_name: project.name, + project_slug: project.slug, + high_volume: project.high_volume, + in_transfer: project.in_transfer, + is_module: project.is_module, + created_at: project.created_at, + last_push_at: project.last_push_at, + number_of_users: project.number_of_users, + options: project.options, + owner_principal_id: project.owner_id, + owner_principal_type: project.owner.type, + owner_permissions_for_project: project.permissions, + }); + } + return logCompliantProjects; +} + +export function convertToLogCompliantNetworks(networks: any[]) { + if (networks === undefined || networks === null) { + return undefined; + } + + const logCompliantNetworks = []; + for (const network of networks) { + logCompliantNetworks.push({ + id: network.id, + name: network.name, + ethereum_network_id: network.ethereum_network_id, + slug: network.slug, + metadata: { + color: network.metadata.color, + explorer_base_url: network.metadata.explorer_base_url, + icon: network.metadata.icon, + label: network.metadata.label, + native_currency: network.metadata.native_currency, + secondary_slugs: network.metadata.secondary_slugs, + short_identifier: network.metadata.short_identifier, + slug: network.metadata.slug, + }, + chain_config: network.chain_config, + sort_order: network.sort_order, + }); + } + return logCompliantNetworks; +} + +export function convertToLogCompliantForkInitializeResponse(res: any) { + return { + fork_id: res.simulation_fork.id, + root_transaction: res.root_transaction.id, + project_id: res.simulation_fork.project_id, + }; +} + +export function convertToLogCompliantTenderlyConfig(config: TenderlyConfig) { + return { + email: + config.email !== undefined && config.email !== null && config.email !== "" + ? "set in 'email' field" + : "undefined or null or empty string", + account_id: config.account_id, + username: + config.username !== undefined && config.username !== null && config.username !== "" + ? "set in 'username' field" + : "undefined or null or empty string", + access_key: + config.access_key !== undefined && config.access_key !== null && config.access_key !== "" + ? "super secret access_key is set in 'access_key' field" + : "undefined or null or empty string", + access_key_id: + config.access_key_id !== undefined && config.access_key_id !== null && config.access_key_id !== "" + ? "super secret access_key_id is set in 'access_key' field" + : "undefined or null or empty string", + }; +} diff --git a/packages/tenderly-core/src/utils/logger.ts b/packages/tenderly-core/src/utils/logger.ts new file mode 100644 index 00000000..a31459d5 --- /dev/null +++ b/packages/tenderly-core/src/utils/logger.ts @@ -0,0 +1,6 @@ +import { Logger } from "tslog"; + +export const logger = new Logger({ + prettyLogTemplate: "{{dateIsoStr}} {{logLevelName}} {{name}} =>", + name: "Service", +}); diff --git a/packages/tenderly-hardhat/.changeset/README.md b/packages/tenderly-hardhat/.changeset/README.md new file mode 100644 index 00000000..e5b6d8d6 --- /dev/null +++ b/packages/tenderly-hardhat/.changeset/README.md @@ -0,0 +1,8 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works +with multi-package repos, or single-package repos to help you version and publish your code. You can +find the full documentation for it [in our repository](https://github.com/changesets/changesets) + +We have a quick list of common questions to get you started engaging with this project in +[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/packages/tenderly-hardhat/.changeset/config.json b/packages/tenderly-hardhat/.changeset/config.json new file mode 100644 index 00000000..16879c3e --- /dev/null +++ b/packages/tenderly-hardhat/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@2.2.0/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "restricted", + "baseBranch": "master", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/packages/tenderly-hardhat/.changeset/sixty-trainers-occur.md b/packages/tenderly-hardhat/.changeset/sixty-trainers-occur.md new file mode 100644 index 00000000..e963262b --- /dev/null +++ b/packages/tenderly-hardhat/.changeset/sixty-trainers-occur.md @@ -0,0 +1,5 @@ +--- +"@tenderly/hardhat-tenderly": patch +--- + +Patch that fixed wrong extraction of compiler configuration from contract source files. diff --git a/packages/tenderly-hardhat/README.md b/packages/tenderly-hardhat/README.md index 6d815e9a..0318c310 100644 --- a/packages/tenderly-hardhat/README.md +++ b/packages/tenderly-hardhat/README.md @@ -159,6 +159,11 @@ module.exports = { }; ``` +If you are having trouble with the plugin and want to contact support, you can run the deploy script with the following ```--verbose``` flag as so: +```bash +npx hardhat run scripts/{your_deploy_script_here.js} --network {network_name} --verbose > tenderly.log 2>&1 +``` +This will create a ```tenderly.log``` file that you can send to our customer support engineers for investigation. ## Usage For this plugin to function you need to create a `config.yaml` file at `$HOME/.tenderly/config.yaml` or `%HOMEPATH%\.tenderly\config.yaml` and add an `access_key` field to it: diff --git a/packages/tenderly-hardhat/package.json b/packages/tenderly-hardhat/package.json index e895f6c9..0a70d539 100644 --- a/packages/tenderly-hardhat/package.json +++ b/packages/tenderly-hardhat/package.json @@ -56,10 +56,11 @@ "hardhat": "^2.10.2", "hardhat-deploy": "^0.11.14", "js-yaml": "^4.1.0", - "tenderly": "^0.0.2" + "tenderly": "^0.0.3", + "tslog": "^4.3.1" }, "peerDependencies": { "hardhat": "^2.10.2", - "tenderly": "^0.0.2" + "tenderly": "^0.0.3" } } diff --git a/packages/tenderly-hardhat/src/Tenderly.ts b/packages/tenderly-hardhat/src/Tenderly.ts index 4fdd3088..39864ea3 100644 --- a/packages/tenderly-hardhat/src/Tenderly.ts +++ b/packages/tenderly-hardhat/src/Tenderly.ts @@ -5,6 +5,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { TenderlyService } from "tenderly"; import { TenderlyArtifact, TenderlyContractUploadRequest, TenderlyForkContractUploadRequest } from "tenderly/types"; import { NETWORK_NAME_CHAIN_ID_MAP } from "tenderly/common/constants"; +import { logger } from "./utils/logger"; import { ContractByName, Metadata } from "./tenderly/types"; import { CONTRACTS_NOT_DETECTED, NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG } from "./tenderly/errors"; @@ -19,17 +20,27 @@ export class Tenderly { private tenderlyService = new TenderlyService(PLUGIN_NAME); constructor(hre: HardhatRuntimeEnvironment) { + logger.debug("Creating Tenderly plugin."); + this.env = hre; this.tenderlyNetwork = new TenderlyNetwork(hre); + + logger.debug("Created Tenderly plugin."); } public async verify(...contracts: any[]): Promise { + logger.info("Invoked public verification."); + const priv = this.env.config.tenderly?.privateVerification; if (priv !== undefined && priv && this.env.network.name !== "tenderly") { + logger.info( + "Private verification flag is set to TRUE in tenderly configuration. Redirecting to private verification." + ); return this.push(...contracts); } if (this.env.network.name === "tenderly") { + logger.info("Network parameter is set to 'tenderly', redirecting to fork verification."); return this.tenderlyNetwork.verify(contracts); } @@ -38,7 +49,7 @@ export class Tenderly { const requestData = await this._filterContracts(flatContracts); if (requestData === null) { - console.log("Verification failed"); + logger.error("Verification failed due to bad processing of the data in /artifacts directory."); return; } @@ -46,9 +57,11 @@ export class Tenderly { } public async verifyAPI(request: TenderlyContractUploadRequest): Promise { + logger.info("Invoked public verification through API request."); + if (this.env.network.name === "tenderly") { - console.log( - `Error in ${PLUGIN_NAME}: .verifyAPI() is not available for fork deployments, please use verifyForkAPI().` + logger.error( + `Error in ${PLUGIN_NAME}: Network parameter is set to 'tenderly' and verifyAPI() is not available for fork deployments, please use verifyForkAPI().` ); return; } @@ -62,9 +75,10 @@ export class Tenderly { username: string, forkID: string ): Promise { + logger.info("Invoked fork verification through API request."); if (this.env.network.name !== "tenderly") { - console.log( - `Error in ${PLUGIN_NAME}: .verifyForkAPI() is only available for tenderly fork deployments, please use --network tenderly.` + logger.error( + `Error in ${PLUGIN_NAME}: Network parameter is not set to 'tenderly' and verifyForkAPI() is only available for tenderly fork deployments, please use --network tenderly.` ); return; } @@ -78,12 +92,19 @@ export class Tenderly { public setNetwork(network: TenderlyNetwork): TenderlyNetwork { this.tenderlyNetwork = network; + logger.trace("Network is set to 'tenderly'.", network); + return this.tenderlyNetwork; } public async push(...contracts: any[]): Promise { + logger.info("Invoked pushing onto Tenderly."); + const priv = this.env.config.tenderly?.privateVerification; if (priv !== undefined && !priv) { + logger.info( + "Private verification flag is set to FALSE in tenderly configuration. Redirecting to public verification." + ); return this.verify(...contracts); } @@ -92,21 +113,21 @@ export class Tenderly { const requestData = await this._filterContracts(flatContracts); if (this.env.config.tenderly.project === undefined) { - console.log( + logger.error( `Error in ${PLUGIN_NAME}: Please provide the project field in the tenderly object in hardhat.config.js` ); return; } if (this.env.config.tenderly.username === undefined) { - console.log( + logger.error( `Error in ${PLUGIN_NAME}: Please provide the username field in the tenderly object in hardhat.config.js` ); return; } if (requestData === null) { - console.log("Push failed"); + logger.error("Pushing failed due to bad processing of the data in /artifacts directory."); return; } @@ -122,9 +143,11 @@ export class Tenderly { tenderlyProject: string, username: string ): Promise { + logger.info("Invoked pushing contracts through API."); + if (this.env.network.name === "tenderly") { - console.log( - `Error in ${PLUGIN_NAME}: .pushAPI() is not available for fork deployments, please use verifyForkAPI().` + logger.error( + `Error in ${PLUGIN_NAME}: Network parameter is set to 'tenderly' and pushAPI() is not available for fork deployments, please use verifyForkAPI().` ); return; } @@ -133,7 +156,9 @@ export class Tenderly { } public async persistArtifacts(...contracts: ContractByName[]) { + logger.info("Invoked persisting artifacts."); if (contracts.length === 0) { + logger.error("No contracts were provided during artifact persisting."); return; } @@ -150,10 +175,15 @@ export class Tenderly { data._resolvedFiles.forEach((resolvedFile: any, _: any) => { const sourcePath: string = resolvedFile.sourceName; + logger.trace("Currently processing file:", sourcePath); + const name = sourcePath.split("/").slice(-1)[0].split(".")[0]; + logger.trace("Obtained name from source file:", name); for (contract of contracts) { if (contract.name === name) { + logger.trace("Found contract:", contract.name); + const network = this.env.hardhatArguments.network !== "hardhat" ? this.env.hardhatArguments.network ?? contract.network @@ -201,6 +231,8 @@ export class Tenderly { abi: contractData.abi, }; + logger.trace("Processed artifact: ", artifact); + fs.outputFileSync(`${destPath}${name}.json`, JSON.stringify(artifact)); } } @@ -208,11 +240,15 @@ export class Tenderly { } private async _filterContracts(flatContracts: ContractByName[]): Promise { + logger.info("Processing data needed for verification."); + let contract: ContractByName; let requestData: TenderlyContractUploadRequest; try { requestData = await this._getContractData(flatContracts); + logger.silly("Processed request data:", requestData); } catch (e) { + logger.error("Error caught while trying to process contracts by name: ", e); return null; } @@ -222,26 +258,29 @@ export class Tenderly { ? this.env.hardhatArguments.network ?? contract.network : contract.network; if (network === undefined) { - console.log( + logger.error( `Error in ${PLUGIN_NAME}: Please provide a network via the hardhat --network argument or directly in the contract` ); return null; } + logger.trace("Found network is:", network); const index = requestData.contracts.findIndex( (requestContract) => requestContract.contractName === contract.name ); if (index === -1) { + logger.error(`Contract '${contract.name}' was not found among the contracts in /artifacts.`); continue; } let chainID: string = NETWORK_NAME_CHAIN_ID_MAP[network!.toLowerCase()]; if (this.env.config.networks[network!].chainId !== undefined) { chainID = this.env.config.networks[network!].chainId!.toString(); } + logger.trace(`ChainID for network '${network}' is ${chainID}`); if (chainID === undefined) { - console.log( - `Error in ${PLUGIN_NAME}: Couldn't identify network. Please provide a chainID in the network config object` + logger.error( + `Error in ${PLUGIN_NAME}: Couldn't identify network. Please provide a chainId in the network config object` ); return null; } @@ -253,6 +292,8 @@ export class Tenderly { }; } + logger.debug("Processed request data from _filterContracts:", requestData); + return requestData; } @@ -261,7 +302,7 @@ export class Tenderly { const config = getCompilerDataFromContracts(contracts, flatContracts, this.env.config); if (config === undefined) { - console.log(NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG); + logger.error(NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG); } return { diff --git a/packages/tenderly-hardhat/src/TenderlyNetwork.ts b/packages/tenderly-hardhat/src/TenderlyNetwork.ts index a3d4b69a..57bcd4a1 100644 --- a/packages/tenderly-hardhat/src/TenderlyNetwork.ts +++ b/packages/tenderly-hardhat/src/TenderlyNetwork.ts @@ -9,7 +9,9 @@ import { TENDERLY_JSON_RPC_BASE_URL } from "tenderly/common/constants"; import { PLUGIN_NAME } from "./constants"; import { ContractByName } from "./tenderly/types"; import { NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG } from "./tenderly/errors"; -import { getCompilerDataFromContracts, getContracts } from "./utils/util"; +import {getCompilerDataFromContracts, getCompilerDataFromHardhat, getContracts} from "./utils/util"; +import { logger } from "./utils/logger"; +import { convertToLogCompliantForkInitializeResponse } from "tenderly/utils/log-compliance"; export class TenderlyNetwork { public host: string; @@ -24,10 +26,13 @@ export class TenderlyNetwork { private tenderlyService = new TenderlyService(PLUGIN_NAME); constructor(hre: HardhatRuntimeEnvironment) { + logger.debug("Making an interface towards tenderly network."); + this.env = hre; this.connected = true; const tdlyGlobalConfig = getConfig(); + this.accessKey = tdlyGlobalConfig?.access_key; this.tenderlyJsonRpc = this._configureTenderlyRPCInstance(); @@ -35,6 +40,7 @@ export class TenderlyNetwork { if (hre.network.name === "tenderly" && "url" in hre.network.config && hre.network.config.url !== undefined) { this.forkID = hre.network.config.url.split("/").pop(); + logger.info("Fork ID is:", this.forkID); } } @@ -85,20 +91,26 @@ export class TenderlyNetwork { } public async verify(...contracts: any[]) { + logger.info("Invoked fork verification."); if (!this._checkNetwork()) { return; } if (this.head === undefined && this.forkID === undefined) { + logger.warn("Head or fork are not initialized."); await this.initializeFork(); } const flatContracts: ContractByName[] = contracts.reduce((accumulator, value) => accumulator.concat(value), []); const requestData = await this._filterContracts(flatContracts); if (requestData === null) { + logger.error("Fork verification failed due to bad processing of data in /artifacts directory."); return; } + logger.silly("Processed request data:", requestData); + if (requestData?.contracts.length === 0) { + logger.error("Filtering contracts did not succeed. The length of the contracts is 0."); return; } @@ -116,6 +128,7 @@ export class TenderlyNetwork { username: string, forkID: string ) { + logger.info("Invoked fork verification via API."); await this.tenderlyService.verifyForkContracts(request, tenderlyProject, username, forkID); } @@ -149,23 +162,34 @@ export class TenderlyNetwork { } public async initializeFork() { + logger.debug("Initializing tenderly fork."); + if (!this._checkNetwork()) { return; } if (this.env.config.tenderly?.forkNetwork === undefined) { + logger.error("There is no information about the fork network. Fork won't be initialized"); return; } const username: string = this.env.config.tenderly.username; const projectID: string = this.env.config.tenderly.project; + logger.trace("ProjectID obtained from tenderly configuration:", { projectID }); + try { const resp = await this.tenderlyJsonRpc.post(`/account/${username}/project/${projectID}/fork`, { network_id: this.env.config.tenderly.forkNetwork, }); + const logCompliantInitializeForkResponse = convertToLogCompliantForkInitializeResponse(resp); + logger.trace("Initialized fork:", logCompliantInitializeForkResponse); + this.head = resp.data.root_transaction.id; this.accounts = resp.data.simulation_fork.accounts; this.forkID = resp.data.simulation_fork.id; + + logger.debug("Successfully initialized tenderly fork."); } catch (err) { + logger.error("Error was caught while calling fork initialization:", err); throw err; } } @@ -177,11 +201,15 @@ export class TenderlyNetwork { } private async _filterContracts(flatContracts: ContractByName[]): Promise { + logger.info("Processing data needed for fork verification."); + let contract: ContractByName; let requestData: TenderlyForkContractUploadRequest; try { requestData = await this._getForkContractData(flatContracts); + logger.silly("Obtained request data needed for fork verification:", requestData); } catch (e) { + logger.error("Caught and error while trying to obtain data needed for fork verification", e); return null; } @@ -190,29 +218,36 @@ export class TenderlyNetwork { (requestContract) => requestContract.contractName === contract.name ); if (index === -1) { + logger.error(`Couldn't find a contract '${contract.name}' among the obtained request data.`); continue; } + + logger.trace("Currently processing contract:", contract.name); requestData.contracts[index].networks = { [this.forkID!]: { address: contract.address, links: contract.libraries, }, }; + logger.trace(`Contract ${contract.name} has been processed,`); } return requestData; } private async _getForkContractData(flatContracts: ContractByName[]): Promise { + logger.trace("Getting contract data needed for fork verification."); + const contracts = await getContracts(this.env, flatContracts); if (contracts.length === 0) { - throw new Error("Failed to get contracts"); + throw new Error("Fork verification failed due to bad processing of data in /artifacts folder."); } - const solcConfig = getCompilerDataFromContracts(contracts, flatContracts, this.env.config); - + // const solcConfig = await getCompilerDataFromHardhat(this.env, contracts[0].contractName); + const solcConfig = await getCompilerDataFromContracts(contracts, flatContracts, this.env.config); + if (solcConfig === undefined) { - console.log(NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG); + logger.error(NO_COMPILER_FOUND_FOR_CONTRACT_ERR_MSG); } return { @@ -224,7 +259,7 @@ export class TenderlyNetwork { private _checkNetwork(): boolean { if (this.env.network.name !== "tenderly") { - console.log( + logger.error( `Warning in ${PLUGIN_NAME}: Network is not set to tenderly. Please call the task again with --network tenderly` ); return false; diff --git a/packages/tenderly-hardhat/src/tasks/common/index.ts b/packages/tenderly-hardhat/src/tasks/common/index.ts index 2a826a65..61a92df0 100644 --- a/packages/tenderly-hardhat/src/tasks/common/index.ts +++ b/packages/tenderly-hardhat/src/tasks/common/index.ts @@ -3,6 +3,7 @@ import { RunTaskFunction, HardhatConfig } from "hardhat/types"; import { TenderlyContract } from "tenderly/types"; import { NETWORK_NAME_CHAIN_ID_MAP } from "tenderly/common/constants"; +import { logger } from "../../utils/logger"; import { PLUGIN_NAME } from "../../constants"; import { Metadata } from "../../tenderly/types"; import { CONTRACTS_NOT_DETECTED } from "../../tenderly/errors"; @@ -14,6 +15,8 @@ export async function extractContractData( config: HardhatConfig, run: RunTaskFunction ): Promise { + logger.info("Extracting contract data."); + let contract: string; const requestContracts: TenderlyContract[] = []; @@ -63,6 +66,7 @@ export async function extractContractData( for (const [key, value] of Object.entries(metadata.sources)) { const name = key.split("/").slice(-1)[0].split(".")[0]; + logger.trace("Currently processing contract:", name); const contractToPush: TenderlyContract = { contractName: name, source: value.content, @@ -82,7 +86,7 @@ export async function extractContractData( chainID = config.networks[network!].chainId!.toString(); } if (chainID === undefined) { - console.log( + logger.error( `Error in ${PLUGIN_NAME}: Couldn't identify network. Please provide a chainID in the network config object` ); return []; @@ -94,6 +98,8 @@ export async function extractContractData( }; } } + logger.silly(`Processed contract ${name}:`, contractToPush); + requestContracts.push(contractToPush); } return requestContracts; diff --git a/packages/tenderly-hardhat/src/tasks/push.ts b/packages/tenderly-hardhat/src/tasks/push.ts index 9888dfaf..e3aae4ad 100644 --- a/packages/tenderly-hardhat/src/tasks/push.ts +++ b/packages/tenderly-hardhat/src/tasks/push.ts @@ -2,6 +2,7 @@ import { HardhatPluginError } from "hardhat/plugins"; import { task } from "hardhat/config"; import { TenderlyService } from "tenderly"; +import { logger } from "../utils/logger"; import { PLUGIN_NAME } from "../constants"; import { newCompilerConfig } from "../utils/util"; import { extractContractData } from "./common"; @@ -16,6 +17,8 @@ task("tenderly:push", "Privately pushes contracts to Tenderly") .setAction(pushContracts); async function pushContracts({ contracts }: any, { config, hardhatArguments, run }: any) { + logger.info("Private verification hardhat task has been invoked."); + if (contracts === undefined) { throw new HardhatPluginError(PLUGIN_NAME, `At least one contract must be provided (ContractName=Address)`); } diff --git a/packages/tenderly-hardhat/src/tasks/verify.ts b/packages/tenderly-hardhat/src/tasks/verify.ts index 6f921b80..38cccc01 100644 --- a/packages/tenderly-hardhat/src/tasks/verify.ts +++ b/packages/tenderly-hardhat/src/tasks/verify.ts @@ -2,6 +2,7 @@ import { task } from "hardhat/config"; import { HardhatPluginError } from "hardhat/plugins"; import { TenderlyService } from "tenderly"; +import { logger } from "../utils/logger"; import { PLUGIN_NAME } from "../constants"; import { newCompilerConfig } from "../utils/util"; import { extractContractData } from "./common"; @@ -16,6 +17,7 @@ task("tenderly:verify", "Verifies contracts on Tenderly") .setAction(verifyContract); async function verifyContract({ contracts }: any, { config, hardhatArguments, run }: any) { + logger.info("Public verification hardhat task has been invoked."); if (contracts === undefined) { throw new HardhatPluginError( PLUGIN_NAME, diff --git a/packages/tenderly-hardhat/src/tenderly/extender.ts b/packages/tenderly-hardhat/src/tenderly/extender.ts index bc545279..1929bb10 100644 --- a/packages/tenderly-hardhat/src/tenderly/extender.ts +++ b/packages/tenderly-hardhat/src/tenderly/extender.ts @@ -4,6 +4,7 @@ import { extendConfig, extendEnvironment } from "hardhat/config"; import { HardhatRuntimeEnvironment, HttpNetworkConfig, HardhatConfig } from "hardhat/types"; import { HardhatEthersHelpers } from "@nomiclabs/hardhat-ethers/types"; import { TenderlyService } from "tenderly"; +import { logger as serviceLogger } from "tenderly/utils/logger"; import { TenderlyNetwork as TenderlyNetworkInterface } from "tenderly/types"; import { CHAIN_ID_NETWORK_NAME_MAP, @@ -11,6 +12,7 @@ import { TENDERLY_JSON_RPC_BASE_URL, } from "tenderly/common/constants"; +import { logger } from "../utils/logger"; import { Tenderly } from "../Tenderly"; import { TenderlyNetwork } from "../TenderlyNetwork"; import { PLUGIN_NAME } from "../constants"; @@ -20,14 +22,44 @@ import { wrapHHDeployments } from "./hardhat-deploy"; const tenderlyService = new TenderlyService(PLUGIN_NAME); export function setup() { + // set to loggers to error level by default + logger.settings.minLevel = 1; + serviceLogger.settings.minLevel = 1; + extendEnvironment((hre: HardhatRuntimeEnvironment) => { hre.tenderly = lazyObject(() => new Tenderly(hre)); + + if (hre.hardhatArguments.verbose) { + logger.settings.minLevel = 1; // trace level + serviceLogger.settings.minLevel = 1; // trace level + } + logger.info( + `Setting up hardhat-tenderly plugin. Log level of hardhat tenderly plugin set to: ${logger.settings.minLevel}` + ); + // serviceLogger is used here just for initialization, nothing else, it will be used in TenderlyService.ts + serviceLogger.info(`Log level of tenderly service set to: ${serviceLogger.settings.minLevel}`); + + const pjson = require("../../package.json"); + logger.info("@tenderly/hardhat-tenderly version:", pjson.version); + + logger.info("Tenderly running configuration: ", { + username: hre.config.tenderly?.username, + project: hre.config.tenderly?.project, + automaticVerification: process.env.AUTOMATIC_VERIFICATION_ENABLED, + privateVerification: hre.config.tenderly?.privateVerification, + networkName: hre.network.name, + }); + extendProvider(hre); populateNetworks(); if (process.env.AUTOMATIC_VERIFICATION_ENABLED === "true") { + logger.debug("Automatic verification is enabled, proceeding to extend ethers library."); extendEthers(hre); extendHardhatDeploy(hre); + logger.debug("Wrapping ethers library finished."); } + + logger.debug("Setup finished."); }); } @@ -45,12 +77,14 @@ extendConfig((resolvedConfig: HardhatConfig) => { const extendProvider = (hre: HardhatRuntimeEnvironment): void => { if (hre.network.name !== "tenderly") { + logger.info("Used network is not 'tenderly' so there is no extending of the provider."); return; } if ("url" in hre.network.config && hre.network.config.url !== undefined) { const forkID = hre.network.config.url.split("/").pop(); hre.tenderly.network().setFork(forkID); + logger.info(`There is a fork url in the 'tenderly' network`, { forkID }); return; } @@ -64,7 +98,7 @@ const extendProvider = (hre: HardhatRuntimeEnvironment): void => { hre.ethers.provider = new hre.ethers.providers.Web3Provider(hre.tenderly.network()); }) .catch((_) => { - console.log(`Error in ${PLUGIN_NAME}: Initializing fork, check your tenderly configuration`); + logger.error(`Error happened while trying to initialize fork ${PLUGIN_NAME}. Check your tenderly configuration`); }); }; @@ -87,9 +121,10 @@ const populateNetworks = (): void => { NETWORK_NAME_CHAIN_ID_MAP[slug] = network.ethereum_network_id; } } + logger.silly("Obtained supported public networks: ", NETWORK_NAME_CHAIN_ID_MAP); }) .catch((_) => { - console.log("Error encountered while fetching public networks"); + logger.error("Error encountered while fetching public networks"); }); }; diff --git a/packages/tenderly-hardhat/src/utils/logger.ts b/packages/tenderly-hardhat/src/utils/logger.ts new file mode 100644 index 00000000..59638f45 --- /dev/null +++ b/packages/tenderly-hardhat/src/utils/logger.ts @@ -0,0 +1,6 @@ +import { Logger } from "tslog"; + +export const logger = new Logger({ + prettyLogTemplate: "{{dateIsoStr}} {{logLevelName}} {{name}} =>", + name: "Hardhat", +}); diff --git a/packages/tenderly-hardhat/src/utils/util.ts b/packages/tenderly-hardhat/src/utils/util.ts index 5ba9612e..056e8bc9 100644 --- a/packages/tenderly-hardhat/src/utils/util.ts +++ b/packages/tenderly-hardhat/src/utils/util.ts @@ -1,17 +1,20 @@ import { HardhatPluginError } from "hardhat/plugins"; import { HardhatConfig } from "hardhat/src/types/config"; -import { HardhatRuntimeEnvironment, SolcConfig } from "hardhat/types"; +import { CompilationJob, DependencyGraph, HardhatRuntimeEnvironment, SolcConfig } from "hardhat/types"; import { TenderlyContract, TenderlyContractConfig } from "tenderly/types"; import { PLUGIN_NAME } from "../constants"; import { CONTRACTS_NOT_DETECTED } from "../tenderly/errors"; import { ContractByName, Metadata } from "../tenderly/types"; +import { logger } from "./logger"; export const getCompilerDataFromContracts = ( contracts: TenderlyContract[], flatContracts: ContractByName[], hhConfig: HardhatConfig ): TenderlyContractConfig | undefined => { + logger.debug("Obtaining compiler data from contracts."); + let contract: TenderlyContract; let mainContract: ContractByName; let config: TenderlyContractConfig | undefined; @@ -20,16 +23,19 @@ export const getCompilerDataFromContracts = ( if (mainContract.name !== contract.contractName) { continue; } + logger.trace("Obtaining compiler data from contract:", mainContract.name); const contractConfig = newCompilerConfig(hhConfig, contract.sourcePath, contract.compiler?.version); if (config !== null && config !== undefined && !compareConfigs(contractConfig, config)) { - console.log(`Error in ${PLUGIN_NAME}: Different compiler versions provided in same request`); + logger.error(`Error in ${PLUGIN_NAME}: Different compiler versions provided in same request`); throw new Error("Compiler version mismatch"); } else { config = contractConfig; } } } + logger.debug("Compiler data has been obtained."); + logger.silly("Obtained compiler configuration is:", config); return config; }; @@ -38,6 +44,8 @@ export const getContracts = async ( hre: HardhatRuntimeEnvironment, flatContracts: ContractByName[] ): Promise => { + logger.debug("Processing contracts from the artifacts/ directory."); + const sourcePaths = await hre.run("compile:solidity:get-source-paths"); const sourceNames = await hre.run("compile:solidity:get-source-names", { sourcePaths, @@ -57,20 +65,41 @@ export const getContracts = async ( }, sources: {}, }; + logger.trace("Extracted compiler version is:", metadata.defaultCompiler.version); data._resolvedFiles.forEach((resolvedFile: any, _: any) => { const sourcePath: string = resolvedFile.sourceName; + logger.trace("Processing file:", sourcePath); + const name = sourcePath.split("/").slice(-1)[0].split(".")[0]; + logger.trace("Obtained name from source file:", name); for (contract of flatContracts) { if (contract.name !== name) { continue; } + logger.trace("Found contract:", contract.name); metadata.sources[sourcePath] = { content: resolvedFile.content.rawContent, versionPragma: resolvedFile.content.versionPragmas[0], }; + + if ( + metadata.sources[sourcePath].content === undefined || + metadata.sources[sourcePath].content === null || + metadata.sources[sourcePath].content === "" + ) { + logger.error("Metadata source content is empty!"); + } + if ( + metadata.sources[sourcePath].versionPragma === undefined || + metadata.sources[sourcePath].versionPragma === null || + metadata.sources[sourcePath].versionPragma === "" + ) { + logger.error("Metadata source version pragma is empty!"); + } + const visited: Record = {}; resolveDependencies(data, sourcePath, metadata, visited); } @@ -90,6 +119,9 @@ export const getContracts = async ( }; requestContracts.push(contractToPush); } + + logger.silly("Finished processing contracts from the artifacts/ folder:", requestContracts); + return requestContracts; }; @@ -130,12 +162,55 @@ export const compareConfigs = (originalConfig: TenderlyContractConfig, newConfig return true; }; +export const getCompilerDataFromHardhat = async ( + hre: HardhatRuntimeEnvironment, + contractName: string, +): Promise => { + const dependencyGraph: DependencyGraph = await _getDependencyGraph(hre); + const file = dependencyGraph.getResolvedFiles().find((resolvedFile) => { + const name = resolvedFile.sourceName.split("/").slice(-1)[0].split(".")[0]; + return name === contractName; + }); + const job: CompilationJob = await hre.run("compile:solidity:get-compilation-job-for-file", { + dependencyGraph, + file + }); + + const hhConfig: SolcConfig = job.getSolcConfig(); + + const tenderlyConfig: TenderlyContractConfig = { + compiler_version: hhConfig?.version, + optimizations_used: hhConfig?.settings?.optimizer?.enabled, + optimizations_count: hhConfig?.settings?.optimizer?.runs, + evm_version: hhConfig?.settings?.evmVersion, + } + if (hhConfig?.settings?.debug?.revertStrings) { + tenderlyConfig.debug = { + revertStrings: hhConfig.settings.debug.revertStrings + } + } + + return tenderlyConfig; +} + +async function _getDependencyGraph(hre: HardhatRuntimeEnvironment): Promise { + const sourcePaths = await hre.run("compile:solidity:get-source-paths"); + const sourceNames: string[] = await hre.run("compile:solidity:get-source-names", { + sourcePaths, + }); + return hre.run("compile:solidity:get-dependency-graph", { + sourceNames, + }); +} + export const newCompilerConfig = ( config: HardhatConfig, sourcePath?: string, contractCompiler?: string ): TenderlyContractConfig => { if (sourcePath !== undefined && config.solidity.overrides[sourcePath] !== undefined) { + logger.trace("There is a compiler config override for:", sourcePath); + return { compiler_version: config.solidity.overrides[sourcePath].version, optimizations_used: config.solidity.overrides[sourcePath].settings.optimizer.enabled, @@ -144,10 +219,14 @@ export const newCompilerConfig = ( debug: config.solidity.overrides[sourcePath].settings.debug, }; } + if (contractCompiler !== undefined) { + logger.trace("There is a provided compiler configuration, determining it."); return determineCompilerConfig(config.solidity.compilers, contractCompiler); } + logger.trace("Returning the first compiler in the configuration"); + return { compiler_version: config.solidity.compilers[0].version, optimizations_used: config.solidity.compilers[0].settings.optimizer.enabled, @@ -175,6 +254,8 @@ export const extractCompilerVersion = (config: HardhatConfig, sourcePath?: strin const determineCompilerConfig = (compilers: SolcConfig[], contractCompiler: string): TenderlyContractConfig => { for (const compiler of compilers) { if (compareVersions(compiler.version, contractCompiler)) { + logger.trace("Provided compiler matched the version: ", compiler.version); + return { compiler_version: compiler.version, optimizations_used: compiler.settings.optimizer.enabled, @@ -185,6 +266,10 @@ const determineCompilerConfig = (compilers: SolcConfig[], contractCompiler: stri } } + logger.trace( + "Couldn't find the provided compiler among compilers in the configuration, returning the configuration of the first one" + ); + return { compiler_version: compilers[0].version, optimizations_used: compilers[0].settings.optimizer.enabled, diff --git a/yarn.lock b/yarn.lock index 53c83aeb..c6e57e0a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -258,10 +258,10 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@eslint/eslintrc@^1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.1.tgz#de0807bfeffc37b964a7d0400e0c348ce5a2543d" - integrity sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ== +"@eslint/eslintrc@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.3.tgz#2b044ab39fdfa75b4688184f9e573ce3c5b0ff95" + integrity sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -615,19 +615,14 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@humanwhocodes/config-array@^0.10.4": - version "0.10.4" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.4.tgz#01e7366e57d2ad104feea63e72248f22015c520c" - integrity sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw== +"@humanwhocodes/config-array@^0.11.6": + version "0.11.7" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.7.tgz#38aec044c6c828f6ed51d5d7ae3d9b9faf6dbb0f" + integrity sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw== dependencies: "@humanwhocodes/object-schema" "^1.2.1" debug "^4.1.1" - minimatch "^3.0.4" - -"@humanwhocodes/gitignore-to-minimatch@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d" - integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA== + minimatch "^3.0.5" "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" @@ -722,7 +717,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3": +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -2455,14 +2450,14 @@ eslint-visitor-keys@^3.3.0: integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== eslint@^8.23.0: - version "8.23.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.0.tgz#a184918d288820179c6041bb3ddcc99ce6eea040" - integrity sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA== + version "8.29.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.29.0.tgz#d74a88a20fb44d59c51851625bc4ee8d0ec43f87" + integrity sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg== dependencies: - "@eslint/eslintrc" "^1.3.1" - "@humanwhocodes/config-array" "^0.10.4" - "@humanwhocodes/gitignore-to-minimatch" "^1.0.2" + "@eslint/eslintrc" "^1.3.3" + "@humanwhocodes/config-array" "^0.11.6" "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" ajv "^6.10.0" chalk "^4.0.0" cross-spawn "^7.0.2" @@ -2478,15 +2473,15 @@ eslint@^8.23.0: fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" find-up "^5.0.0" - functional-red-black-tree "^1.0.1" - glob-parent "^6.0.1" + glob-parent "^6.0.2" globals "^13.15.0" - globby "^11.1.0" grapheme-splitter "^1.0.4" ignore "^5.2.0" import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-sdsl "^4.1.4" js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" @@ -2998,7 +2993,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.1: +glob-parent@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== @@ -3460,6 +3455,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -3549,6 +3549,11 @@ jest-changed-files@^24.9.0: execa "^1.0.0" throat "^4.0.0" +js-sdsl@^4.1.4: + version "4.2.0" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.2.0.tgz#278e98b7bea589b8baaf048c20aeb19eb7ad09d0" + integrity sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ== + js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" @@ -3933,7 +3938,7 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -5087,6 +5092,11 @@ tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslog@^4.3.1, tslog@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/tslog/-/tslog-4.4.0.tgz#ac3f47959cdb7c12e9daad085e6d3517d26f93b9" + integrity sha512-7HrI6Yb3oeg3uZA7nWI2Z2z3W8kb7hTYoljpWOuPxc44Q7Qn1Ski/j6t/CDjJdn9rqFc/Aali+gMpG+S+StPuw== + tsort@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786"