diff --git a/.gitignore b/.gitignore index 632f2b292..b84a92e49 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ .vscode .idea coverage +coverage-ts dist node_modules npm-debug.log diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ec50c5ea9..9f915e625 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -103,6 +103,7 @@ For major changes that markedly transform the existing API or significantly alte - We’re using [Prettier](https://github.com/prettier/prettier) to format code, so don’t worry much about code formatting. - Don’t commit generated files, like minified JavaScript. - Don’t change the version number or changelog. +- Use `npm run ts:coverage` to check the global type coverage rate and `npm run ts:coverage:report` to generate a complete report (summary displayed in the console, full HTML report available in the `coverage-ts` folder by launching `./coverage-ts/index.html` in your browser) and find files having low coverage. ## Need help? diff --git a/package-lock.json b/package-lock.json index 17aa7a8b3..d09dd21f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,8 +58,10 @@ "prettier-plugin-import-sort": "^0.0.7", "semantic-release": "^23.0.5", "tsup": "^8.0.2", + "type-coverage": "^2.28.2", "typedoc": "^0.25.7", - "typescript": "~5.4.0" + "typescript": "~5.4.0", + "typescript-coverage-report": "^1.0.0" } }, "../starknet-types": { @@ -3205,6 +3207,20 @@ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, + "node_modules/@hypnosphi/create-react-context": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@hypnosphi/create-react-context/-/create-react-context-0.3.1.tgz", + "integrity": "sha512-V1klUed202XahrWJLLOT3EXNeCpFHCcJntdFGI15ntCwau+jfT386w7OFTMaCqOgXUH1fa0w/I1oZs+i/Rfr0A==", + "dev": true, + "dependencies": { + "gud": "^1.0.0", + "warning": "^4.0.3" + }, + "peerDependencies": { + "prop-types": "^15.0.0", + "react": ">=0.14.0" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -5114,6 +5130,20 @@ "semantic-release": ">=20.1.0" } }, + "node_modules/@semantic-ui-react/event-stack": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@semantic-ui-react/event-stack/-/event-stack-3.1.3.tgz", + "integrity": "sha512-FdTmJyWvJaYinHrKRsMLDrz4tTMGdFfds299Qory53hBugiDvGC0tEJf+cHsi5igDwWb/CLOgOiChInHwq8URQ==", + "dev": true, + "dependencies": { + "exenv": "^1.2.2", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -6589,6 +6619,12 @@ "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "dev": true + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -7471,6 +7507,26 @@ } } }, + "node_modules/deep-equal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "dev": true, + "dependencies": { + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.5.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -8579,6 +8635,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==", + "dev": true + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -9215,6 +9277,12 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==", + "dev": true + }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -9788,6 +9856,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -12290,6 +12374,12 @@ "node": "*" } }, + "node_modules/keyboard-key": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keyboard-key/-/keyboard-key-1.1.0.tgz", + "integrity": "sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ==", + "dev": true + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -12799,6 +12889,18 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lossless-json": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-4.0.1.tgz", @@ -13073,6 +13175,15 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "dev": true, + "bin": { + "ncp": "bin/ncp" + } + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -16056,6 +16167,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -16604,6 +16731,17 @@ "node": ">=8" } }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -16744,6 +16882,23 @@ "node": ">= 6" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -16828,6 +16983,33 @@ "node": ">=0.10.0" } }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", @@ -17286,6 +17468,16 @@ "node": ">=v12.22.7" } }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/semantic-release": { "version": "23.0.6", "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-23.0.6.tgz", @@ -17584,6 +17776,82 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/semantic-ui-react": { + "version": "0.88.2", + "resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-0.88.2.tgz", + "integrity": "sha512-+02kN2z8PuA/cMdvDUsHhbJmBzxxgOXVHMFr9XK7zGb0wkW9A6OPQMFokWz7ozlVtKjN6r7zsb+Qvjk/qq1OWw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.1.2", + "@semantic-ui-react/event-stack": "^3.1.0", + "@stardust-ui/react-component-event-listener": "~0.38.0", + "@stardust-ui/react-component-ref": "~0.38.0", + "classnames": "^2.2.6", + "keyboard-key": "^1.0.4", + "lodash": "^4.17.15", + "prop-types": "^15.7.2", + "react-is": "^16.8.6", + "react-popper": "^1.3.4", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.8.0", + "react-dom": "^16.8.0" + } + }, + "node_modules/semantic-ui-react/node_modules/@stardust-ui/react-component-event-listener": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@stardust-ui/react-component-event-listener/-/react-component-event-listener-0.38.0.tgz", + "integrity": "sha512-sIP/e0dyOrrlb8K7KWumfMxj/gAifswTBC4o68Aa+C/GA73ccRp/6W1VlHvF/dlOR4KLsA+5SKnhjH36xzPsWg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.1.2", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "^16.8.0", + "react-dom": "^16.8.0" + } + }, + "node_modules/semantic-ui-react/node_modules/@stardust-ui/react-component-ref": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@stardust-ui/react-component-ref/-/react-component-ref-0.38.0.tgz", + "integrity": "sha512-xjs6WnvJVueSIXMWw0C3oWIgAPpcD03qw43oGOjUXqFktvpNkB73JoKIhS4sCrtQxBdct75qqr4ZL6JiyPcESw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.1.2", + "prop-types": "^15.7.2", + "react-is": "^16.6.3" + }, + "peerDependencies": { + "react": "^16.8.0", + "react-dom": "^16.8.0" + } + }, + "node_modules/semantic-ui-react/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/semantic-ui-react/node_modules/react-popper": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.11.tgz", + "integrity": "sha512-VSA/bS+pSndSF2fiasHK/PTEEAyOpX60+H5EPAjoArr8JGm+oihu4UbrqcEBpQibJxBVCpYyjAX7abJ+7DoYVg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.1.2", + "@hypnosphi/create-react-context": "^0.3.1", + "deep-equal": "^1.1.1", + "popper.js": "^1.14.4", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.7", + "warning": "^4.0.2" + }, + "peerDependencies": { + "react": "0.14.x || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -17690,6 +17958,12 @@ "node": ">= 0.4" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "dev": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -18641,6 +18915,27 @@ "webidl-conversions": "^4.0.2" } }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -18653,6 +18948,35 @@ "node": ">= 0.8.0" } }, + "node_modules/type-coverage": { + "version": "2.28.2", + "resolved": "https://registry.npmjs.org/type-coverage/-/type-coverage-2.28.2.tgz", + "integrity": "sha512-mTANnzAeuH7ldrg0fzPnhh+aCCSVAO7V7hlBoVg4XxuUtQyD3ogir/R7Z6Q7W0H1JREtDIY4I91SGHAgEPi6Bw==", + "dev": true, + "dependencies": { + "minimist": "1", + "type-coverage-core": "^2.28.1" + }, + "bin": { + "type-coverage": "bin/type-coverage" + } + }, + "node_modules/type-coverage-core": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/type-coverage-core/-/type-coverage-core-2.28.1.tgz", + "integrity": "sha512-NniLJtLiDg0+dhrf/9ACGwi3OAhIfvd20f1CB0yxIUBMECwmJp7e7me3lM8djkrDBJtqSY+uXA6PRs+yv3HTnA==", + "dev": true, + "dependencies": { + "fast-glob": "3", + "minimatch": "6 || 7 || 8 || 9", + "normalize-path": "3", + "tslib": "1 || 2", + "tsutils": "3" + }, + "peerDependencies": { + "typescript": "2 || 3 || 4 || 5" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -18747,6 +19071,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typed-styles": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz", + "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==", + "dev": true + }, "node_modules/typedoc": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.12.tgz", @@ -18793,6 +19123,108 @@ "node": ">=14.17" } }, + "node_modules/typescript-coverage-report": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typescript-coverage-report/-/typescript-coverage-report-1.0.0.tgz", + "integrity": "sha512-ys/DG6eaO0XaHZIPZobJQLj9lUPSOIa1xt5Pz6tvr7QAWRt3OSCuMLiPduWtg7oTeZcOHqG90owA/zOeyZdq3g==", + "dev": true, + "dependencies": { + "chalk": "4.1.2", + "cli-table3": "^0.6.1", + "commander": "^5.0.0", + "ncp": "^2.0.0", + "rimraf": "^3.0.2", + "semantic-ui-react": "^0.88.2", + "type-coverage-core": "^2.23.0" + }, + "bin": { + "typescript-coverage-report": "dist/bin/typescript-coverage-report.js" + }, + "peerDependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "typescript": "2 || 3 || 4 || 5" + } + }, + "node_modules/typescript-coverage-report/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/typescript-coverage-report/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/typescript-coverage-report/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/typescript-coverage-report/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/typescript-coverage-report/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/typescript-coverage-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/typescript-coverage-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", @@ -19033,6 +19465,15 @@ "makeerror": "1.0.12" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", diff --git a/package.json b/package.json index f3f8b697e..0c67828f1 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,9 @@ "info:version": "npm pkg get version | xargs", "format": "prettier --log-level log --write \"**/*.{ts,js,md,yml,json}\"", "lint": "eslint . --cache --fix --ext .ts", - "ts:check": "tsc --noEmit --resolveJsonModule --project tsconfig.eslint.json" + "ts:check": "tsc --noEmit --resolveJsonModule --project tsconfig.eslint.json", + "ts:coverage": "type-coverage --at-least 95", + "ts:coverage:report": "typescript-coverage-report" }, "keywords": [ "starknet", @@ -86,8 +88,10 @@ "prettier-plugin-import-sort": "^0.0.7", "semantic-release": "^23.0.5", "tsup": "^8.0.2", + "type-coverage": "^2.28.2", "typedoc": "^0.25.7", - "typescript": "~5.4.0" + "typescript": "~5.4.0", + "typescript-coverage-report": "^1.0.0" }, "dependencies": { "@noble/curves": "~1.4.0", @@ -98,9 +102,9 @@ "isomorphic-fetch": "^3.0.0", "lossless-json": "^4.0.1", "pako": "^2.0.4", + "starknet-types-07": "npm:starknet-types@^0.7.2", "ts-mixer": "^6.0.3", - "url-join": "^4.0.1", - "starknet-types-07": "npm:starknet-types@^0.7.2" + "url-join": "^4.0.1" }, "lint-staged": { "*.ts": "eslint --cache --fix", diff --git a/src/types/lib/contract/abi.ts b/src/types/lib/contract/abi.ts index 6583165dd..1b23e1b47 100644 --- a/src/types/lib/contract/abi.ts +++ b/src/types/lib/contract/abi.ts @@ -1,5 +1,5 @@ /** ABI */ -export type Abi = ReadonlyArray; +export type Abi = ReadonlyArray; // Basic elements export type AbiEntry = { name: string; type: 'felt' | 'felt*' | string }; @@ -31,6 +31,13 @@ export type StructAbi = { type: 'struct'; }; +export type AbiInterfaces = { [name: string]: InterfaceAbi }; +export type InterfaceAbi = { + items: FunctionAbi[]; + name: string; + type: 'interface'; +}; + export type AbiEnums = { [name: string]: EnumAbi }; export type EnumAbi = { variants: (AbiEntry & { offset: number })[]; diff --git a/src/utils/assert.ts b/src/utils/assert.ts index 4d0830ebb..ef35545a3 100644 --- a/src/utils/assert.ts +++ b/src/utils/assert.ts @@ -4,7 +4,7 @@ * @param {string} [message] - The optional message to include in the error. * @throws {Error} Throws an error if the condition is false. */ -export default function assert(condition: any, message?: string): asserts condition { +export default function assert(condition: boolean, message?: string): asserts condition { if (!condition) { throw new Error(message || 'Assertion failure'); } diff --git a/src/utils/calldata/formatter.ts b/src/utils/calldata/formatter.ts index a0adc3a68..260299d0c 100644 --- a/src/utils/calldata/formatter.ts +++ b/src/utils/calldata/formatter.ts @@ -2,7 +2,7 @@ import { isBigInt } from '../num'; import { decodeShortString } from '../shortString'; const guard = { - isBN: (data: any, type: any, key: any) => { + isBN: (data: Record, type: Record, key: string) => { if (!isBigInt(data[key])) throw new Error( `Data and formatter mismatch on ${key}:${type[key]}, expected response data ${key}:${ @@ -10,7 +10,7 @@ const guard = { } to be BN instead it is ${typeof data[key]}` ); }, - unknown: (data: any, type: any, key: any) => { + unknown: (data: Record, type: Record, key: string) => { throw new Error(`Unhandled formatter type on ${key}:${type[key]} for data ${key}:${data[key]}`); }, }; @@ -23,51 +23,58 @@ const guard = { * @param {any} [sameType] - The same type definition to be used (optional). * @returns - The formatted data. */ -export default function formatter(data: any, type: any, sameType?: any) { +export default function formatter( + data: Record, + type: Record, + sameType?: any +) { // match data element with type element - return Object.entries(data).reduce((acc, [key, value]: [any, any]) => { - const elType = sameType ?? type[key]; + return Object.entries(data).reduce( + (acc, [key, value]: [any, any]) => { + const elType = sameType ?? type[key]; - if (!(key in type) && !sameType) { - // no type definition for element return original element - acc[key] = value; - return acc; - } + if (!(key in type) && !sameType) { + // no type definition for element return original element + acc[key] = value; + return acc; + } - if (elType === 'string') { - if (Array.isArray(data[key])) { - // long string (felt*) - const arrayStr = formatter( - data[key], - data[key].map((_: any) => elType) - ); - acc[key] = Object.values(arrayStr).join(''); + if (elType === 'string') { + if (Array.isArray(data[key])) { + // long string (felt*) + const arrayStr = formatter( + data[key], + data[key].map((_: any) => elType) + ); + acc[key] = Object.values(arrayStr).join(''); + return acc; + } + guard.isBN(data, type, key); + acc[key] = decodeShortString(value); + return acc; + } + if (elType === 'number') { + guard.isBN(data, type, key); + acc[key] = Number(value); + return acc; + } + if (typeof elType === 'function') { + acc[key] = elType(value); + return acc; + } + if (Array.isArray(elType)) { + const arrayObj = formatter(data[key], elType, elType[0]); + acc[key] = Object.values(arrayObj); + return acc; + } + if (typeof elType === 'object') { + acc[key] = formatter(data[key], elType); return acc; } - guard.isBN(data, type, key); - acc[key] = decodeShortString(value); - return acc; - } - if (elType === 'number') { - guard.isBN(data, type, key); - acc[key] = Number(value); - return acc; - } - if (typeof elType === 'function') { - acc[key] = elType(value); - return acc; - } - if (Array.isArray(elType)) { - const arrayObj = formatter(data[key], elType, elType[0]); - acc[key] = Object.values(arrayObj); - return acc; - } - if (typeof elType === 'object') { - acc[key] = formatter(data[key], elType); - return acc; - } - guard.unknown(data, type, key); - return acc; - }, {} as any); + guard.unknown(data, type, key); + return acc; + }, + {} as Record + ); } diff --git a/src/utils/calldata/index.ts b/src/utils/calldata/index.ts index e9765c806..904e99506 100644 --- a/src/utils/calldata/index.ts +++ b/src/utils/calldata/index.ts @@ -271,7 +271,7 @@ export class CallData { */ public format(method: string, response: string[], format: object): Result { const parsed = this.parse(method, response); - return formatter(parsed, format); + return formatter(parsed as Record, format); } /** diff --git a/src/utils/calldata/parser/parser-2.0.0.ts b/src/utils/calldata/parser/parser-2.0.0.ts index 6c9d7b2ba..94e6a83bc 100644 --- a/src/utils/calldata/parser/parser-2.0.0.ts +++ b/src/utils/calldata/parser/parser-2.0.0.ts @@ -1,4 +1,4 @@ -import { Abi, FunctionAbi } from '../../../types'; +import { Abi, FunctionAbi, EventAbi, StructAbi, InterfaceAbi } from '../../../types'; import { AbiParserInterface } from './interface'; export class AbiParser2 implements AbiParserInterface { @@ -23,8 +23,10 @@ export class AbiParser2 implements AbiParserInterface { * @returns FunctionAbi | undefined */ public getMethod(name: string): FunctionAbi | undefined { - const intf = this.abi.find((it) => it.type === 'interface'); - return intf.items.find((it: any) => it.name === name); + const intf = this.abi.find( + (it: FunctionAbi | EventAbi | StructAbi | InterfaceAbi) => it.type === 'interface' + ) as InterfaceAbi; + return intf.items.find((it) => it.name === name); } /** @@ -32,7 +34,7 @@ export class AbiParser2 implements AbiParserInterface { * @returns Abi */ public getLegacyFormat(): Abi { - return this.abi.flatMap((e) => { + return this.abi.flatMap((e: FunctionAbi | EventAbi | StructAbi | InterfaceAbi) => { if (e.type === 'interface') { return e.items; } diff --git a/src/utils/eth.ts b/src/utils/eth.ts index d8c2a7536..21c1f60d2 100644 --- a/src/utils/eth.ts +++ b/src/utils/eth.ts @@ -32,6 +32,6 @@ export function ethRandomPrivateKey(): string { export function validateAndParseEthAddress(address: BigNumberish): string { assertInRange(address, ZERO, 2n ** 160n - 1n, 'Ethereum Address '); const result = addHexPrefix(removeHexPrefix(toHex(address)).padStart(40, '0')); - assert(result.match(/^(0x)?[0-9a-f]{40}$/), 'Invalid Ethereum Address Format'); + assert(Boolean(result.match(/^(0x)?[0-9a-f]{40}$/)), 'Invalid Ethereum Address Format'); return result; } diff --git a/src/utils/responseParser/index.ts b/src/utils/responseParser/index.ts index 9161fc124..9605da691 100644 --- a/src/utils/responseParser/index.ts +++ b/src/utils/responseParser/index.ts @@ -1,4 +1,6 @@ import { + BlockWithTxHashes, + FeeEstimate, CallContractResponse, DeclareContractResponse, DeployContractResponse, @@ -11,13 +13,13 @@ import { import type { GetTransactionReceiptResponse } from '../transactionReceipt'; export abstract class ResponseParser { - abstract parseGetBlockResponse(res: any): GetBlockResponse; + abstract parseGetBlockResponse(res: BlockWithTxHashes): GetBlockResponse; abstract parseGetTransactionResponse(res: any): GetTransactionResponse; abstract parseGetTransactionReceiptResponse(res: any): GetTransactionReceiptResponse; - abstract parseFeeEstimateResponse(res: any): EstimateFeeResponse; + abstract parseFeeEstimateResponse(res: FeeEstimate[]): EstimateFeeResponse; abstract parseCallContractResponse(res: any): CallContractResponse;