diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c1b862c7..c1939591 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -16,6 +16,8 @@ jobs: - run: npm ci + - run: npm run lint + - run: npm run prettier:check - run: npm run test diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..a020746b --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,30 @@ +import pluginJs from "@eslint/js"; +import solid from "eslint-plugin-solid"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + { files: ["**/*.{js,mjs,cjs,ts,tsx}"] }, + { languageOptions: { globals: globals.browser } }, + { + ignores: [ + "dist", + "coverage", + "node_modules", + "dnssec-prover", + "jest.config.js", + "babel.config.js", + "vite.config.mjs", + "src/utils/dnssec/dnssec_prover*", + ], + }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + solid.configs["flat/typescript"], + { + rules: { + "no-async-promise-executor": "off", + }, + }, +]; diff --git a/package-lock.json b/package-lock.json index 359a4826..0b39559a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/preset-env": "^7.25.3", "@babel/preset-typescript": "^7.24.7", + "@eslint/js": "^9.13.0", "@playwright/test": "^1.46.0", "@solidjs/testing-library": "^0.8.9", "@testing-library/jest-dom": "^6.4.8", @@ -54,8 +55,11 @@ "babel-plugin-transform-vite-meta-env": "^1.0.3", "babel-preset-jest": "^29.6.3", "babel-preset-solid": "^1.8.19", + "eslint": "^9.13.0", + "eslint-plugin-solid": "^0.14.3", "eventsource": "^2.0.2", "git-cliff": "^2.4.0", + "globals": "^15.11.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jsdom": "^24.1.1", @@ -63,6 +67,7 @@ "sass": "^1.77.8", "solid-jest": "^0.2.0", "typescript": "^5.5.4", + "typescript-eslint": "^8.12.2", "vite": "^5.4.8", "vite-plugin-mkcert": "^1.17.6", "vite-plugin-node-polyfills": "^0.22.0", @@ -153,6 +158,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/core/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/generator": { "version": "7.25.0", "license": "MIT", @@ -208,6 +222,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-compilation-targets": { "version": "7.25.2", "license": "MIT", @@ -332,6 +356,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-member-expression-to-functions/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-module-imports": { "version": "7.24.7", "license": "MIT", @@ -362,6 +395,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-module-imports/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-module-transforms": { "version": "7.25.2", "license": "MIT", @@ -394,6 +436,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-module-transforms/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.24.7", "license": "MIT", @@ -444,6 +495,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-remap-async-to-generator/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-replace-supers": { "version": "7.25.0", "license": "MIT", @@ -475,6 +536,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-replace-supers/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-simple-access": { "version": "7.24.7", "license": "MIT", @@ -505,6 +575,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-simple-access/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.24.7", "license": "MIT", @@ -535,6 +614,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.24.7", "license": "MIT", @@ -596,6 +684,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-wrap-function/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/helpers": { "version": "7.25.0", "license": "MIT", @@ -665,6 +763,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { "version": "7.25.0", "dev": true, @@ -741,6 +849,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "dev": true, @@ -1054,6 +1172,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/plugin-transform-async-generator-functions/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-async-to-generator": { "version": "7.24.7", "dev": true, @@ -1165,6 +1293,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.24.7", "dev": true, @@ -1331,6 +1469,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/plugin-transform-function-name/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-json-strings": { "version": "7.24.7", "dev": true, @@ -1453,6 +1601,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/plugin-transform-modules-systemjs/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-modules-umd": { "version": "7.24.7", "dev": true, @@ -1998,6 +2156,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { "version": "7.25.2", "license": "MIT", @@ -2050,6 +2218,163 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", + "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/js": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", + "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", + "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@ethereumjs/common": { "version": "4.4.0", "license": "MIT", @@ -2792,6 +3117,58 @@ "version": "5.0.22", "license": "OFL-1.1" }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@iframe-resizer/child": { "version": "5.2.4", "license": "GPL-3.0", @@ -3824,6 +4201,44 @@ ], "license": "MIT" }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@octokit/auth-token": { "version": "4.0.0", "dev": true, @@ -5071,6 +5486,13 @@ "parse5": "^7.0.0" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/lodash": { "version": "4.17.12", "license": "MIT" @@ -5135,6 +5557,248 @@ "dev": true, "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.12.2.tgz", + "integrity": "sha512-gQxbxM8mcxBwaEmWdtLCIGLfixBMHhQjBqR8sVWNTPpcj45WlYL2IObS/DNMLH1DBP0n8qz+aiiLTGfopPEebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.12.2", + "@typescript-eslint/type-utils": "8.12.2", + "@typescript-eslint/utils": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.2.tgz", + "integrity": "sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.12.2", + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/typescript-estree": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz", + "integrity": "sha512-gPLpLtrj9aMHOvxJkSbDBmbRuYdtiEbnvO25bCMza3DhMjTQw0u7Y1M+YR5JPbMsXXnSPuCf5hfq0nEkQDL/JQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.12.2.tgz", + "integrity": "sha512-bwuU4TAogPI+1q/IJSKuD4shBLc/d2vGcRT588q+jzayQyjVK2X6v/fbR4InY2U2sgf8MEvVCqEWUzYzgBNcGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.12.2", + "@typescript-eslint/utils": "8.12.2", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.12.2.tgz", + "integrity": "sha512-VwDwMF1SZ7wPBUZwmMdnDJ6sIFk4K4s+ALKLP6aIQsISkPv8jhiw65sAK6SuWODN/ix+m+HgbYDkH+zLjrzvOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.12.2.tgz", + "integrity": "sha512-mME5MDwGe30Pq9zKPvyduyU86PH7aixwqYR2grTglAdB+AN8xXQ1vFGpYaUSJ5o5P/5znsSBeNcs5g5/2aQwow==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/visitor-keys": "8.12.2", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.12.2.tgz", + "integrity": "sha512-UTTuDIX3fkfAz6iSVa5rTuSfWIYZ6ATtEocQ/umkRSyC9O919lbZ8dcH7mysshrCdrAM03skJOEYaBugxN+M6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.12.2", + "@typescript-eslint/types": "8.12.2", + "@typescript-eslint/typescript-estree": "8.12.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.12.2.tgz", + "integrity": "sha512-PChz8UaKQAVNHghsHcPyx1OMHoFRUEA7rJSK/mDhdq85bk+PLsUHUBqTQTFt18VJZbmxBovM65fezlheQRsSDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.12.2", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@vulpemventures/secp256k1-zkp": { "version": "3.2.1", "license": "MIT", @@ -5160,7 +5824,9 @@ "license": "BSD-3-Clause" }, "node_modules/acorn": { - "version": "8.11.3", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", "bin": { @@ -5179,6 +5845,16 @@ "acorn-walk": "^8.0.2" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-walk": { "version": "8.3.2", "dev": true, @@ -5211,6 +5887,23 @@ "node": ">= 8.0.0" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "dev": true, @@ -6519,6 +7212,13 @@ } } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/deepmerge": { "version": "4.3.1", "dev": true, @@ -6871,6 +7571,238 @@ "node": ">=0.10.0" } }, + "node_modules/eslint": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", + "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.7.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.13.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-solid": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-solid/-/eslint-plugin-solid-0.14.3.tgz", + "integrity": "sha512-eDeyPrijSjVGeyb4oKoyidgLlMDZwAg/YdxiY9QvGXl2kLgpcHvLpgpaGK4KJ8xSsg0ym3B2dPRBAIlT7iUrEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^7.13.1 || ^8.0.0", + "estraverse": "^5.3.0", + "is-html": "^2.0.0", + "kebab-case": "^1.0.2", + "known-css-properties": "^0.30.0", + "style-to-object": "^1.0.6" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "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/eslint/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, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/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, + "license": "MIT" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esprima": { "version": "4.0.1", "dev": true, @@ -6883,6 +7815,32 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/estraverse": { "version": "5.3.0", "dev": true, @@ -7046,8 +8004,39 @@ "node": "> 0.1.90" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT" }, @@ -7055,6 +8044,16 @@ "version": "1.0.0", "license": "MIT" }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fb-watchman": { "version": "2.0.2", "dev": true, @@ -7063,6 +8062,19 @@ "bser": "2.1.1" } }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "license": "MIT" @@ -7093,6 +8105,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" + }, "node_modules/follow-redirects": { "version": "1.15.6", "funding": [ @@ -7381,10 +8414,16 @@ } }, "node_modules/globals": { - "version": "11.12.0", + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", + "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/gopd": { @@ -7402,6 +8441,13 @@ "dev": true, "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/has": { "version": "1.0.3", "dev": true, @@ -7523,6 +8569,19 @@ "dev": true, "license": "MIT" }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/http-proxy-agent": { "version": "5.0.0", "dev": true, @@ -7609,6 +8668,16 @@ "url": "https://iframe-resizer.com/pricing/" } }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/immediate": { "version": "3.0.6", "license": "MIT" @@ -7618,6 +8687,33 @@ "dev": true, "license": "MIT" }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/import-local": { "version": "3.1.0", "dev": true, @@ -7724,6 +8820,13 @@ "version": "2.0.4", "license": "ISC" }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "dev": true, + "license": "MIT" + }, "node_modules/int64-buffer": { "version": "1.0.1", "license": "MIT", @@ -7851,6 +8954,19 @@ "node": ">=0.10.0" } }, + "node_modules/is-html": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-html/-/is-html-2.0.0.tgz", + "integrity": "sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "html-tags": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-nan": { "version": "1.3.2", "license": "MIT", @@ -10197,11 +11313,32 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "dev": true, "license": "MIT" }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "license": "ISC" @@ -10244,6 +11381,13 @@ "node": "*" } }, + "node_modules/kebab-case": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.2.tgz", + "integrity": "sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==", + "dev": true, + "license": "MIT" + }, "node_modules/keccak": { "version": "3.0.4", "hasInstallScript": true, @@ -10257,6 +11401,16 @@ "node": ">=10.0.0" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kleur": { "version": "3.0.3", "dev": true, @@ -10265,6 +11419,13 @@ "node": ">=6" } }, + "node_modules/known-css-properties": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.30.0.tgz", + "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==", + "dev": true, + "license": "MIT" + }, "node_modules/leven": { "version": "3.1.0", "dev": true, @@ -10273,6 +11434,20 @@ "node": ">=6" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lie": { "version": "3.1.1", "license": "MIT", @@ -10344,6 +11519,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/loglevel": { "version": "1.9.1", "license": "MIT", @@ -10519,6 +11701,16 @@ "dev": true, "license": "MIT" }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/micromatch": { "version": "4.0.8", "dev": true, @@ -10813,6 +12005,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/os-browserify": { "version": "0.3.0", "dev": true, @@ -10858,6 +12068,19 @@ "dev": true, "license": "(MIT AND Zlib)" }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-asn1": { "version": "5.1.6", "dev": true, @@ -11042,6 +12265,16 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "3.3.3", "dev": true, @@ -11227,6 +12460,27 @@ "dev": true, "license": "MIT" }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/randombytes": { "version": "2.1.0", "license": "MIT", @@ -11425,6 +12679,17 @@ "node": ">=10" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/ripemd160": { "version": "2.0.2", "license": "MIT", @@ -11602,6 +12867,30 @@ "dev": true, "license": "MIT" }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/rxjs": { "version": "7.8.1", "license": "Apache-2.0", @@ -12294,6 +13583,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-to-object": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", + "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, "node_modules/superstruct": { "version": "2.0.2", "license": "MIT", @@ -12351,6 +13650,13 @@ "node_modules/text-encoding-utf-8": { "version": "1.0.2" }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, "node_modules/through": { "version": "2.3.8", "license": "MIT" @@ -12449,6 +13755,19 @@ "node": ">=6" } }, + "node_modules/ts-api-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-mixer": { "version": "6.0.4", "license": "MIT" @@ -12462,6 +13781,19 @@ "dev": true, "license": "MIT" }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "dev": true, @@ -12505,6 +13837,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.12.2", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.12.2.tgz", + "integrity": "sha512-UbuVUWSrHVR03q9CWx+JDHeO6B/Hr9p4U5lRH++5tq/EbFq1faYZe50ZSBePptgfIKLEti0aPQ3hFgnPVcd8ZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.12.2", + "@typescript-eslint/parser": "8.12.2", + "@typescript-eslint/utils": "8.12.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/ua-parser-js": { "version": "1.0.39", "funding": [ @@ -12617,6 +13973,26 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/url": { "version": "0.11.0", "dev": true, @@ -12983,6 +14359,16 @@ "bs58check": "<3.0.0" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "6.2.0", "license": "MIT", diff --git a/package.json b/package.json index aadf147a..81e4a124 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,11 @@ "mainnet": "cp src/configs/mainnet.json public/config.json", "beta": "cp src/configs/beta.json public/config.json", "testnet": "cp src/configs/testnet.json public/config.json", - "prettier": "npx prettier src tests e2e docs *.js *.ts", + "prettier": "npx prettier src tests e2e docs *.js *.ts *.mjs", "prettier:write": "npm run prettier -- --write", "prettier:check": "npm run prettier -- --check", "tsc": "tsc", + "lint": "eslint --max-warnings 0 .", "changelog": "git-cliff -o CHANGELOG.md" }, "devDependencies": { @@ -25,6 +26,7 @@ "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/preset-env": "^7.25.3", "@babel/preset-typescript": "^7.24.7", + "@eslint/js": "^9.13.0", "@playwright/test": "^1.46.0", "@solidjs/testing-library": "^0.8.9", "@testing-library/jest-dom": "^6.4.8", @@ -37,8 +39,11 @@ "babel-plugin-transform-vite-meta-env": "^1.0.3", "babel-preset-jest": "^29.6.3", "babel-preset-solid": "^1.8.19", + "eslint": "^9.13.0", + "eslint-plugin-solid": "^0.14.3", "eventsource": "^2.0.2", "git-cliff": "^2.4.0", + "globals": "^15.11.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jsdom": "^24.1.1", @@ -46,6 +51,7 @@ "sass": "^1.77.8", "solid-jest": "^0.2.0", "typescript": "^5.5.4", + "typescript-eslint": "^8.12.2", "vite": "^5.4.8", "vite-plugin-mkcert": "^1.17.6", "vite-plugin-node-polyfills": "^0.22.0", diff --git a/src/components/AddressInput.tsx b/src/components/AddressInput.tsx index 1d148117..5562e030 100644 --- a/src/components/AddressInput.tsx +++ b/src/components/AddressInput.tsx @@ -1,3 +1,4 @@ +import log from "loglevel"; import { createEffect, on } from "solid-js"; import { LN, RBTC } from "../consts/Assets"; @@ -5,6 +6,7 @@ import { SwapType } from "../consts/Enums"; import { useCreateContext } from "../context/Create"; import { useGlobalContext } from "../context/Global"; import { probeUserInput } from "../utils/compat"; +import { formatError } from "../utils/errors"; import { extractAddress, extractInvoice } from "../utils/invoice"; const AddressInput = () => { @@ -61,6 +63,8 @@ const AddressInput = () => { break; } } catch (e) { + log.debug(`Invalid address input: ${formatError(e)}`); + setAddressValid(false); if (inputValue.length !== 0) { const msg = t("invalid_address", { asset: assetReceive() }); diff --git a/src/components/Asset.tsx b/src/components/Asset.tsx index e89bf27d..8fae596b 100644 --- a/src/components/Asset.tsx +++ b/src/components/Asset.tsx @@ -4,9 +4,9 @@ import { Side } from "../consts/Enums"; import { useCreateContext } from "../context/Create"; import "../style/asset.scss"; -const Asset = ({ side, signal }: { side: Side; signal: Accessor }) => { +const Asset = (props: { side: Side; signal: Accessor }) => { const openSelect = () => { - setAssetSelected(side); + setAssetSelected(props.side); setAssetSelect(true); }; @@ -14,14 +14,14 @@ const Asset = ({ side, signal }: { side: Side; signal: Accessor }) => { return (
-
+
- - - + + +
-
+
); }; diff --git a/src/components/AssetSelect.tsx b/src/components/AssetSelect.tsx index f4b20d06..f1d7f413 100644 --- a/src/components/AssetSelect.tsx +++ b/src/components/AssetSelect.tsx @@ -1,5 +1,5 @@ import { IoClose } from "solid-icons/io"; -import { createEffect } from "solid-js"; +import { For, createEffect } from "solid-js"; import { config } from "../config"; import { LN } from "../consts/Assets"; @@ -79,16 +79,18 @@ const SelectAsset = () => {
- {assets.map((asset) => ( -
changeAsset(asset)}> - - -
- ))} + + {(asset) => ( +
changeAsset(asset)}> + + +
+ )} +
); }; diff --git a/src/components/BlockExplorerLink.tsx b/src/components/BlockExplorerLink.tsx index 6a8b116a..ed694ff6 100644 --- a/src/components/BlockExplorerLink.tsx +++ b/src/components/BlockExplorerLink.tsx @@ -11,70 +11,80 @@ import { } from "../utils/swapCreator"; import BlockExplorer from "./BlockExplorer"; -const BlockExplorerLink = ({ - swap, - swapStatus, -}: { +const ChainSwapLink = (props: { swap: Accessor; swapStatus: Accessor; }) => { - // Showing addresses makes no sense for EVM based chains - if ( - (swap().type !== SwapType.Chain && getRelevantAssetForSwap(swap())) === - RBTC - ) { - return ( - - - - ); - } - - if (swap().type !== SwapType.Chain) { - // Refund transactions are handled in SwapRefunded - return ( - - - - ); - } - const [hasBeenClaimed, setHasBeenClaimed] = createSignal(false); createEffect(() => { - setHasBeenClaimed(swap().claimTx !== undefined); + setHasBeenClaimed(props.swap().claimTx !== undefined); }); return ( ); }; +const BlockExplorerLink = (props: { + swap: Accessor; + swapStatus: Accessor; +}) => { + return ( + + }> + {/* Showing addresses makes no sense for EVM based chains */} + + + + }> + {/* Refund transactions are handled in SwapRefunded */} + + + + + + ); +}; + export default BlockExplorerLink; diff --git a/src/components/ConnectWallet.tsx b/src/components/ConnectWallet.tsx index 681017d6..d688f6c2 100644 --- a/src/components/ConnectWallet.tsx +++ b/src/components/ConnectWallet.tsx @@ -5,8 +5,8 @@ import { For, Setter, Show, - createEffect, createMemo, + createResource, createSignal, } from "solid-js"; @@ -19,11 +19,7 @@ import { formatError } from "../utils/errors"; import { cropString, isMobile } from "../utils/helper"; import HardwareDerivationPaths, { connect } from "./HardwareDerivationPaths"; -const Modal = ({ - show, - setShow, - derivationPath, -}: { +const Modal = (props: { derivationPath: string; show: Accessor; setShow: Setter; @@ -36,18 +32,18 @@ const Modal = ({ const [hardwareProvider, setHardwareProvider] = createSignal(undefined); - const Provider = ({ provider }: { provider: EIP6963ProviderInfo }) => { + const Provider = (providerProps: { provider: EIP6963ProviderInfo }) => { return (
{ - if (provider.disabled) { + if (providerProps.provider.disabled) { notify("error", t("not_supported_in_browser")); return; } - if (provider.isHardware) { - setHardwareProvider(provider); + if (providerProps.provider.isHardware) { + setHardwareProvider(providerProps.provider); setShowDerivationPaths(true); return; } @@ -56,28 +52,28 @@ const Modal = ({ notify, connectProvider, providers, - provider, - derivationPath, + providerProps.provider, + props.derivationPath, ); }}>
- + {`${provider.name} -

{provider.name}

+

{providerProps.provider.name}

); @@ -86,11 +82,11 @@ const Modal = ({ return (
setShow(false)} - style={show() ? "display: block;" : "display: none;"}> + onClick={() => props.setShow(false)} + style={props.show() ? "display: block;" : "display: none;"}>
e.stopPropagation()}>

{t("select_wallet")}

- setShow(false)}> + props.setShow(false)}>
@@ -112,7 +108,7 @@ const Modal = ({ ); }; -const ConnectModal = ({ derivationPath }: { derivationPath: string }) => { +const ConnectModal = (props: { derivationPath: string }) => { const { t, notify } = useGlobalContext(); const { providers, connectProvider } = useWeb3Signer(); @@ -132,7 +128,7 @@ const ConnectModal = ({ derivationPath }: { derivationPath: string }) => { connectProvider, providers, Object.values(providers())[0].info, - derivationPath, + props.derivationPath, ).then(); } }}> @@ -141,16 +137,13 @@ const ConnectModal = ({ derivationPath }: { derivationPath: string }) => { ); }; -const ShowAddress = ({ - address, - addressOverride, -}: { +const ShowAddress = (props: { address: Accessor; addressOverride?: Accessor; }) => { @@ -174,16 +167,14 @@ const ShowAddress = ({ onMouseLeave={() => setText(undefined)} class="btn btn-light"> {text() || - (addressOverride - ? addressOverride() || formatAddress(address()) - : formatAddress(address()))} + (props.addressOverride + ? props.addressOverride() || formatAddress(props.address()) + : formatAddress(props.address()))} ); }; -export const ConnectAddress = ({ - address, -}: { +export const ConnectAddress = (props: { address: { address: string; derivationPath?: string }; }) => { const { t, notify } = useGlobalContext(); @@ -195,12 +186,12 @@ export const ConnectAddress = ({ onClick={async () => { try { await connectProviderForAddress( - address.address, - address.derivationPath, + props.address.address, + props.address.derivationPath, ); } catch (e) { log.error( - `Provider connect for address ${address} failed: ${formatError(e)}`, + `Provider connect for address ${props.address} failed: ${formatError(e)}`, ); notify( "error", @@ -233,10 +224,7 @@ export const SwitchNetwork = () => { ); }; -const ConnectWallet = ({ - derivationPath, - addressOverride, -}: { +const ConnectWallet = (props: { derivationPath?: string; addressOverride?: Accessor; }) => { @@ -247,10 +235,10 @@ const ConnectWallet = ({ const address = createMemo(() => signer()?.address); const [networkValid, setNetworkValid] = createSignal(true); - createEffect(async () => { + createResource(async () => { if ( address() !== undefined && - Number((await signer()?.provider.getNetwork()).chainId) !== + Number((await signer()?.provider.getNetwork())?.chainId || -1) !== getContracts().network.chainId ) { setNetworkValid(false); @@ -274,11 +262,13 @@ const ConnectWallet = ({ }> }> + fallback={ + + }> }> diff --git a/src/components/ContractTransaction.tsx b/src/components/ContractTransaction.tsx index 1249afdc..7e3601a6 100644 --- a/src/components/ContractTransaction.tsx +++ b/src/components/ContractTransaction.tsx @@ -1,5 +1,6 @@ import log from "loglevel"; -import { Show, createEffect, createSignal } from "solid-js"; +import { Show, createResource, createSignal } from "solid-js"; +import type { JSX } from "solid-js"; import { useGlobalContext } from "../context/Global"; import { useWeb3Signer } from "../context/Web3"; @@ -7,17 +8,9 @@ import { formatError } from "../utils/errors"; import ConnectWallet, { ConnectAddress, SwitchNetwork } from "./ConnectWallet"; import LoadingSpinner from "./LoadingSpinner"; -const ContractTransaction = ({ - showHr, - onClick, - address, - children, - promptText, - buttonText, - waitingText, -}: { - onClick: () => Promise; - children?: any; +const ContractTransaction = (props: { + onClick: () => Promise; + children?: JSX.Element; showHr?: boolean; buttonText: string; promptText?: string; @@ -33,29 +26,30 @@ const ContractTransaction = ({ undefined, ); - createEffect(async () => { + createResource(async () => { const network = await signer()?.provider?.getNetwork(); setSignerNetwork(Number(network?.chainId)); }); - const allowAnyAddress = - address === undefined || address.address === undefined; + const allowAnyAddress = () => + props.address === undefined || props.address.address === undefined; return ( }> - + }> - -

{waitingText}

+ +

{props.waitingText}

}> - -

{promptText}

+ +

{props.promptText}

+
+ + {props.children} - {children} - +
diff --git a/src/components/CopyButton.tsx b/src/components/CopyButton.tsx index 3add0660..7331fc20 100644 --- a/src/components/CopyButton.tsx +++ b/src/components/CopyButton.tsx @@ -1,32 +1,41 @@ import { BiRegularCopy } from "solid-icons/bi"; import { IoCheckmark } from "solid-icons/io"; -import { Accessor, Show, createSignal } from "solid-js"; +import { + Accessor, + Show, + createEffect, + createSignal, + mergeProps, +} from "solid-js"; import { useGlobalContext } from "../context/Global"; import type { DictKey } from "../i18n/i18n"; import { clipboard } from "../utils/helper"; -const CopyButton = ({ - data, - label, - btnClass = "btn", -}: { +const CopyButton = (props: { label: DictKey; data: string | Accessor; btnClass?: string; }) => { const { t } = useGlobalContext(); - const [buttonClass, setButtonClass] = createSignal(btnClass); + const merged = mergeProps({ btnClass: "btn" }, props); + + const [buttonClass, setButtonClass] = createSignal(""); const [buttonActive, setButtonActive] = createSignal(false); + createEffect(() => { + setButtonClass(merged.btnClass); + }); + const onClick = () => { - const copyData = typeof data === "string" ? data : data(); + const copyData = + typeof merged.data === "string" ? merged.data : merged.data(); clipboard(copyData.replaceAll(" ", "")); - setButtonClass(`${btnClass} btn-active`); + setButtonClass(`${merged.btnClass} btn-active`); setButtonActive(true); setTimeout(() => { - setButtonClass(btnClass); + setButtonClass(merged.btnClass); setButtonActive(false); }, 600); }; @@ -38,7 +47,7 @@ const CopyButton = ({ fallback={}>
- {t(label)} + {t(merged.label)}
); }; diff --git a/src/components/CreateButton.tsx b/src/components/CreateButton.tsx index 975826a6..ac068f7b 100644 --- a/src/components/CreateButton.tsx +++ b/src/components/CreateButton.tsx @@ -1,7 +1,7 @@ import { useNavigate } from "@solidjs/router"; import BigNumber from "bignumber.js"; import log from "loglevel"; -import { createEffect, createMemo, createSignal, on } from "solid-js"; +import { createEffect, createSignal, on } from "solid-js"; import { RBTC } from "../consts/Assets"; import { SwapType } from "../consts/Enums"; @@ -80,7 +80,7 @@ export const CreateButton = () => { ); }; - createMemo(() => { + createEffect(() => { setButtonClass(!online() ? "btn btn-danger" : "btn"); }); @@ -232,12 +232,13 @@ export const CreateButton = () => { setInvoice(res.invoice); setBolt12Offer(undefined); } catch (e) { - if (typeof e.json === "function") { - e = (await e.json()).error; - } + const err: unknown = + typeof e.json === "function" + ? (await e.json()).error + : e; - notify("error", formatError(e)); - log.warn("Fetching invoice from bol12 failed", e); + notify("error", formatError(err)); + log.warn("Fetching invoice from bol12 failed", err); return; } } diff --git a/src/components/DownloadRefund.tsx b/src/components/DownloadRefund.tsx index 32953ca4..d175601c 100644 --- a/src/components/DownloadRefund.tsx +++ b/src/components/DownloadRefund.tsx @@ -6,7 +6,7 @@ import { usePayContext } from "../context/Pay"; import { download, downloadJson, getRefundFileName } from "../utils/download"; import { isIos, isMobile } from "../utils/helper"; -const downloadRefundJson = (swap: any) => { +const downloadRefundJson = (swap: { id: string } & Record) => { downloadJson(getRefundFileName(swap.id), swap); }; @@ -14,7 +14,9 @@ const DownloadRefund = () => { const { swap } = usePayContext(); const { t } = useGlobalContext(); - const downloadRefundQr = (swap: any) => { + const downloadRefundQr = ( + swap: { id: string } & Record, + ) => { QRCode.toDataURL(JSON.stringify(swap), { width: 1200, errorCorrectionLevel: "L", @@ -42,7 +44,7 @@ const DownloadRefund = () => { return (
diff --git a/src/components/HardwareDerivationPaths.tsx b/src/components/HardwareDerivationPaths.tsx index a3bb536e..16140994 100644 --- a/src/components/HardwareDerivationPaths.tsx +++ b/src/components/HardwareDerivationPaths.tsx @@ -65,12 +65,7 @@ const connectHardware = async ( } }; -const DerivationPath = ({ - name, - path, - provider, - setLoading, -}: { +const DerivationPath = (props: { name: string; path: string; provider: Accessor; @@ -86,25 +81,22 @@ const DerivationPath = ({ await connectHardware( notify, connectProvider, - provider, + props.provider, providers, - path, - setLoading, + props.path, + props.setLoading, ); }}>
-

{name}

- {path} +

{props.name}

+ {props.path}
); }; -const CustomPath = ({ - provider, - setLoading, -}: { +const CustomPath = (props: { provider: Accessor; setLoading: Setter; }) => { @@ -122,7 +114,7 @@ const CustomPath = ({
+ style={{ cursor: "default", "padding-top": "0" }}>

Custom

+ style={{ cursor: "default", "padding-top": "0" }}> - + ); }; diff --git a/src/components/RefundEta.tsx b/src/components/RefundEta.tsx index e36535f5..3d28593b 100644 --- a/src/components/RefundEta.tsx +++ b/src/components/RefundEta.tsx @@ -2,10 +2,7 @@ import { Accessor, Show } from "solid-js"; import { useGlobalContext } from "../context/Global"; -const RefundEta = ({ - timeoutEta, - timeoutBlockHeight, -}: { +const RefundEta = (props: { timeoutEta: Accessor; timeoutBlockHeight: Accessor; }) => { @@ -16,10 +13,11 @@ const RefundEta = ({

{t("refund_explainer")}

- - {t("timeout_eta")}: {getDateString(timeoutEta())}
+ + {t("timeout_eta")}: {getDateString(props.timeoutEta())}{" "} +
- {t("pay_timeout_blockheight")}: {timeoutBlockHeight()} + {t("pay_timeout_blockheight")}: {props.timeoutBlockHeight()}

); diff --git a/src/components/SwapChecker.tsx b/src/components/SwapChecker.tsx index 59392d11..8c741e38 100644 --- a/src/components/SwapChecker.tsx +++ b/src/components/SwapChecker.tsx @@ -11,7 +11,7 @@ import { swapStatusSuccess, } from "../consts/SwapStatus"; import { useGlobalContext } from "../context/Global"; -import { usePayContext } from "../context/Pay"; +import { SwapStatusTransaction, usePayContext } from "../context/Pay"; import { getChainSwapTransactions, getReverseTransaction, @@ -29,6 +29,9 @@ import { type SwapStatus = { id: string; status: string; + + failureReason?: string; + transaction: SwapStatusTransaction; }; const reconnectInterval = 5_000; @@ -37,15 +40,18 @@ class BoltzWebSocket { private readonly swapClaimLock = new Lock(); private ws?: WebSocket; - private reconnectTimeout?: any; + private reconnectTimeout?: ReturnType; private isClosed: boolean = false; constructor( private readonly url: string, private readonly wsFallback: string | undefined, private readonly relevantIds: Set, - private readonly prepareSwap: (id: string, status: any) => void, - private readonly claimSwap: (id: string, status: any) => Promise, + private readonly prepareSwap: (id: string, status: SwapStatus) => void, + private readonly claimSwap: ( + id: string, + status: SwapStatus, + ) => Promise, ) {} public connect = () => { @@ -154,27 +160,27 @@ export const SwapChecker = () => { let ws: BoltzWebSocket | undefined = undefined; - const prepareSwap = async (swapId: string, data: any) => { + const prepareSwap = async (swapId: string, data: SwapStatus) => { const currentSwap = await getSwap(swapId); if (currentSwap === null) { log.warn(`prepareSwap: swap ${swapId} not found`); return; } if (swap() && swap().id === currentSwap.id) { - setSwapStatus(data.status); + setSwapStatus(data.status as string); if (data.transaction) { setSwapStatusTransaction(data.transaction); } if (data.failureReason) { - setFailureReason(data.failureReason); + setFailureReason(data.failureReason as string); } } if (data.status) { - await updateSwapStatus(currentSwap.id, data.status); + await updateSwapStatus(currentSwap.id, data.status as string); } }; - const claimSwap = async (swapId: string, data: any) => { + const claimSwap = async (swapId: string, data: SwapStatus) => { const currentSwap = await getSwap(swapId); if (currentSwap === null) { log.warn(`claimSwap: swap ${swapId} not found`); @@ -207,7 +213,7 @@ export const SwapChecker = () => { swapStatusPending.TransactionConfirmed, swapStatusPending.TransactionMempool, swapStatusSuccess.InvoiceSettled, - ].includes(data.status)) || + ].includes(data.status as string)) || (currentSwap.type === SwapType.Chain && [ swapStatusSuccess.TransactionClaimed, @@ -218,7 +224,7 @@ export const SwapChecker = () => { try { const res = await claim( currentSwap as ReverseSwap | ChainSwap, - data.transaction, + data.transaction as { hex: string }, ); const claimedSwap = (await getSwap(res.id)) as | ReverseSwap diff --git a/src/components/SwapIcons.tsx b/src/components/SwapIcons.tsx index b7d7d9eb..a732cff3 100644 --- a/src/components/SwapIcons.tsx +++ b/src/components/SwapIcons.tsx @@ -4,18 +4,24 @@ import { LN } from "../consts/Assets"; import { SwapType } from "../consts/Enums"; import { SomeSwap } from "../utils/swapCreator"; -export const SwapIcons = ({ swap }: { swap: SomeSwap }) => { +export const SwapIcons = (props: { swap: SomeSwap }) => { return ( + props.swap.type === SwapType.Reverse + ? LN + : props.swap.assetSend + } + /> + props.swap.type === SwapType.Submarine + ? LN + : props.swap.assetReceive + } + /> ); }; diff --git a/src/components/SwapList.tsx b/src/components/SwapList.tsx index 81c3febb..66999e19 100644 --- a/src/components/SwapList.tsx +++ b/src/components/SwapList.tsx @@ -1,28 +1,27 @@ import { useNavigate } from "@solidjs/router"; import { BiRegularTrash } from "solid-icons/bi"; -import { Accessor, For, Show, createMemo, createSignal } from "solid-js"; +import { Accessor, For, Show, createEffect, createSignal } from "solid-js"; import { useGlobalContext } from "../context/Global"; import "../style/swaplist.scss"; import { SomeSwap } from "../utils/swapCreator"; import { SwapIcons } from "./SwapIcons"; -const SwapList = ({ - swapsSignal, - onDelete, -}: { +const SwapList = (props: { swapsSignal: Accessor; - onDelete?: () => Promise; + onDelete?: () => Promise; }) => { const navigate = useNavigate(); const { deleteSwap, t } = useGlobalContext(); const [sortedSwaps, setSortedSwaps] = createSignal([]); const [lastSwap, setLastSwap] = createSignal(); - createMemo(() => { - const sorted = swapsSignal().sort((a: SomeSwap, b: SomeSwap) => - a.date > b.date ? -1 : a.date === b.date ? 0 : 1, - ); + createEffect(() => { + const sorted = props + .swapsSignal() + .sort((a: SomeSwap, b: SomeSwap) => + a.date > b.date ? -1 : a.date === b.date ? 0 : 1, + ); setSortedSwaps(sorted); setLastSwap(sorted[sorted.length - 1]); }); @@ -38,7 +37,7 @@ const SwapList = ({ e.preventDefault(); if (confirm(t("delete_storage_single_swap", { id: swapId }))) { await deleteSwap(swapId); - await onDelete(); + await props.onDelete(); } }; @@ -65,7 +64,7 @@ const SwapList = ({ {formatDate(swap.date)} - + diff --git a/src/components/SwapListLogs.tsx b/src/components/SwapListLogs.tsx index 3ed1dc81..4f346448 100644 --- a/src/components/SwapListLogs.tsx +++ b/src/components/SwapListLogs.tsx @@ -7,18 +7,18 @@ import "../style/swaplist.scss"; import { LogRefundData } from "../utils/contractLogs"; import { cropString } from "../utils/helper"; -const AssetIcon = ({ asset }: { asset: AssetType }) => ( +const AssetIcon = (props: { asset: AssetType }) => ( - + ); -const SwapListLogs = ({ swaps }: { swaps: Accessor }) => { +const SwapListLogs = (props: { swaps: Accessor }) => { const navigate = useNavigate(); const { t } = useGlobalContext(); const sortedSwaps = createMemo(() => { - return swaps().sort((a, b) => { + return props.swaps().sort((a, b) => { return a.blockNumber - b.blockNumber; }); }); diff --git a/src/components/settings/Logs.tsx b/src/components/settings/Logs.tsx index 312966b5..e18c2455 100644 --- a/src/components/settings/Logs.tsx +++ b/src/components/settings/Logs.tsx @@ -3,7 +3,7 @@ import { BiRegularDownload, BiRegularTrash, } from "solid-icons/bi"; -import { Show } from "solid-js/web"; +import { Show } from "solid-js"; import { useGlobalContext } from "../../context/Global"; import { downloadJson } from "../../utils/download"; diff --git a/src/components/settings/SettingsMenu.tsx b/src/components/settings/SettingsMenu.tsx index f984feed..36824170 100644 --- a/src/components/settings/SettingsMenu.tsx +++ b/src/components/settings/SettingsMenu.tsx @@ -1,6 +1,6 @@ import { IoClose } from "solid-icons/io"; -import { JSXElement } from "solid-js"; -import { Show } from "solid-js/web"; +import type { JSXElement } from "solid-js"; +import { Show } from "solid-js"; import { config } from "../../config"; import { useGlobalContext } from "../../context/Global"; @@ -14,22 +14,18 @@ import RecklessModeSetting from "./RecklessModeSetting"; import Separator from "./Separator"; import Tooltip from "./Tooltip"; -const Entry = ({ - label, - tooltipLabel, - settingElement, -}: { +const Entry = (props: { label: DictKey; - tooltipLabel: string; + tooltipLabel: DictKey; settingElement: JSXElement; }) => { const { t } = useGlobalContext(); return ( - - -
- {settingElement} + + +
+ {props.settingElement} ); }; diff --git a/src/components/settings/Tooltip.tsx b/src/components/settings/Tooltip.tsx index 75835a4d..6514e187 100644 --- a/src/components/settings/Tooltip.tsx +++ b/src/components/settings/Tooltip.tsx @@ -1,15 +1,16 @@ import { BiSolidHelpCircle } from "solid-icons/bi"; import { useGlobalContext } from "../../context/Global"; +import type { DictKey } from "../../i18n/i18n"; import "../../style/tooltip.scss"; -const Tooltip = ({ label }) => { +const Tooltip = (props: { label: DictKey }) => { const timeout_delay = 300; const timeout_delay_click = 2500; const { t } = useGlobalContext(); - let timeout: any = null; + let timeout: ReturnType = null; const tooltipClick = (evt: MouseEvent) => { const target = evt.currentTarget as HTMLSpanElement; @@ -40,7 +41,7 @@ const Tooltip = ({ label }) => { onMouseLeave={tooltipLeave}> - {t(label)} + {t(props.label)} ); }; diff --git a/src/config.ts b/src/config.ts index b88832cc..49c0bb33 100644 --- a/src/config.ts +++ b/src/config.ts @@ -27,7 +27,6 @@ const defaults = { }; type Asset = { - network?: any; blockExplorerUrl?: Url; rifRelay?: string; @@ -36,6 +35,15 @@ type Asset = { smartWalletFactory?: string; deployVerifier?: string; }; + network?: { + chainName: string; + rpcUrls: string[]; + nativeCurrency: { + name: string; + symbol: string; + decimals: number; + }; + }; }; type Url = { @@ -62,7 +70,7 @@ const isTor = () => window?.location.hostname.endsWith(".onion"); export const chooseUrl = (url?: Url) => url ? (isTor() && url.tor ? url.tor : url.normal) : undefined; -export const setConfig = (data: any) => { +export const setConfig = (data: Config) => { config = { ...defaults, ...data }; log.setLevel(config.loglevel!); }; diff --git a/src/context/Create.tsx b/src/context/Create.tsx index cb9824b6..41fa54e5 100644 --- a/src/context/Create.tsx +++ b/src/context/Create.tsx @@ -9,6 +9,7 @@ import { createSignal, useContext, } from "solid-js"; +import type { JSX } from "solid-js"; import { config } from "../config"; import { BTC, LBTC, LN, RBTC, assets } from "../consts/Assets"; @@ -32,6 +33,8 @@ const setDestination = ( getNetwork(asset) as LiquidNetwork, ); return true; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { return false; } @@ -171,7 +174,7 @@ export type CreateContextType = { const CreateContext = createContext(); -const CreateProvider = (props: { children: any }) => { +const CreateProvider = (props: { children: JSX.Element }) => { const defaultSelection = Object.keys(config.assets)[0]; const [swapType, setSwapType] = createSignal(SwapType.Submarine); @@ -183,10 +186,12 @@ const CreateProvider = (props: { children: any }) => { const [onchainAddress, setOnchainAddress] = createSignal(""); const [assetReceive, setAssetReceive] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal(defaultSelection), { name: "assetReceive" }, ); + // eslint-disable-next-line solid/reactivity const [assetSend, setAssetSend] = makePersisted(createSignal(LN), { name: "assetSend", }); diff --git a/src/context/Global.tsx b/src/context/Global.tsx index b3751e4e..3bc869f4 100644 --- a/src/context/Global.tsx +++ b/src/context/Global.tsx @@ -7,10 +7,12 @@ import { Accessor, Setter, createContext, + createEffect, createMemo, createSignal, useContext, } from "solid-js"; +import type { JSX } from "solid-js"; import { config } from "../config"; import { Denomination } from "../consts/Enums"; @@ -67,7 +69,7 @@ export type GlobalContextType = { browserNotification: Accessor; setBrowserNotification: Setter; // functions - t: (key: DictKey, values?: Record) => string; + t: (key: DictKey, values?: Record) => string; notify: ( type: string, message: string, @@ -83,11 +85,11 @@ export type GlobalContextType = { isRecklessMode: Accessor; setRecklessMode: Setter; - setSwapStorage: (swap: SomeSwap) => Promise; + setSwapStorage: (swap: SomeSwap) => Promise; getSwap: (id: string) => Promise; getSwaps: () => Promise; deleteSwap: (id: string) => Promise; - clearSwaps: () => Promise; + clearSwaps: () => Promise; updateSwapStatus: (id: string, newStatus: string) => Promise; hardwareDerivationPath: Accessor; @@ -99,13 +101,13 @@ export type GlobalContextType = { // Local storage serializer to support the values created by the deprecated "createStorageSignal" const stringSerializer = { - serialize: (value: any) => value, - deserialize: (value: any) => value, + serialize: (value: never) => value, + deserialize: (value: never) => value, }; const GlobalContext = createContext(); -const GlobalProvider = (props: { children: any }) => { +const GlobalProvider = (props: { children: JSX.Element }) => { const [online, setOnline] = createSignal(true); const [pairs, setPairs] = createSignal(undefined); @@ -129,6 +131,7 @@ const GlobalProvider = (props: { children: any }) => { const [hideHero, setHideHero] = createSignal(false); const [ref, setRef] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal( isMobile() ? "boltz_webapp_mobile" : "boltz_webapp_desktop", ), @@ -139,6 +142,7 @@ const GlobalProvider = (props: { children: any }) => { ); const [i18nConfigured, setI18nConfigured] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal(null), { name: "i18n", @@ -146,6 +150,7 @@ const GlobalProvider = (props: { children: any }) => { }, ); const [i18nUrl, setI18nUrl] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal(null), { name: "i18nUrl", @@ -154,6 +159,7 @@ const GlobalProvider = (props: { children: any }) => { ); const [denomination, setDenomination] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal(Denomination.Sat), { name: "denomination", @@ -164,6 +170,7 @@ const GlobalProvider = (props: { children: any }) => { const [settingsMenu, setSettingsMenu] = createSignal(false); const [audioNotification, setAudioNotification] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal(false), { name: "audioNotification", @@ -172,6 +179,7 @@ const GlobalProvider = (props: { children: any }) => { const localeSeparator = (0.1).toLocaleString().charAt(1); const [separator, setSeparator] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal(localeSeparator), { name: "separator", @@ -226,12 +234,13 @@ const GlobalProvider = (props: { children: any }) => { injectLogWriter(logsForage); - createMemo(() => deleteOldLogs(logsForage)); + // TODO: check still being run + createEffect(() => deleteOldLogs(logsForage)); const getLogs = async () => { const logs: Record = {}; - await logsForage.iterate((logArray, date) => { + await logsForage.iterate((logArray, date) => { logs[date] = logArray; }); @@ -251,8 +260,9 @@ const GlobalProvider = (props: { children: any }) => { log.error("Storage migration failed:", e), ); - const setSwapStorage = (swap: SomeSwap) => - swapsForage.setItem(swap.id, swap); + const setSwapStorage = async (swap: SomeSwap) => { + await swapsForage.setItem(swap.id, swap); + }; const deleteSwap = (id: string) => swapsForage.removeItem(id); @@ -261,7 +271,7 @@ const GlobalProvider = (props: { children: any }) => { const getSwaps = async (): Promise => { const swaps: T[] = []; - await swapsForage.iterate((swap) => { + await swapsForage.iterate((swap) => { swaps.push(swap); }); @@ -310,6 +320,7 @@ const GlobalProvider = (props: { children: any }) => { } const [browserNotification, setBrowserNotification] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal(false), { name: "browserNotification", @@ -317,6 +328,7 @@ const GlobalProvider = (props: { children: any }) => { ); const [isRecklessMode, setRecklessMode] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal(false), { name: "recklessMode", @@ -324,6 +336,7 @@ const GlobalProvider = (props: { children: any }) => { ); const [hardwareDerivationPath, setHardwareDerivationPath] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal(""), { name: "hardwareDerivationPath", @@ -331,14 +344,15 @@ const GlobalProvider = (props: { children: any }) => { ); // i18n - createMemo(() => setI18n(i18nConfigured() || i18nUrl())); + createEffect(() => setI18n(i18nConfigured() || i18nUrl())); const dictLocale = createMemo(() => flatten(dict[i18n() || config.defaultLanguage]), ); + // eslint-disable-next-line solid/reactivity const t = translator(dictLocale, resolveTemplate) as ( key: DictKey, - values?: Record, + values?: Record, ) => string; return ( diff --git a/src/context/Pay.tsx b/src/context/Pay.tsx index 662506d5..38252cc5 100644 --- a/src/context/Pay.tsx +++ b/src/context/Pay.tsx @@ -5,6 +5,7 @@ import { createSignal, useContext, } from "solid-js"; +import type { JSX } from "solid-js"; import { SomeSwap } from "../utils/swapCreator"; @@ -26,7 +27,7 @@ type SwapStatusTransaction = { id?: string; }; -const PayProvider = (props: { children: any }) => { +const PayProvider = (props: { children: JSX.Element }) => { const [failureReason, setFailureReason] = createSignal(""); const [swap, setSwap] = createSignal(null, { // To allow updating properties of the swap object without replacing it completely @@ -61,4 +62,4 @@ const usePayContext = () => { return context; }; -export { usePayContext, PayProvider }; +export { usePayContext, PayProvider, SwapStatusTransaction }; diff --git a/src/context/Web3.tsx b/src/context/Web3.tsx index 383e7ecf..11a4341f 100644 --- a/src/context/Web3.tsx +++ b/src/context/Web3.tsx @@ -9,6 +9,7 @@ import { createContext, createResource, createSignal, + onMount, useContext, } from "solid-js"; @@ -29,11 +30,11 @@ declare global { } interface Navigator { - hid: {}; + hid: object; } interface Window { - ethereum?: any; + ethereum?: EIP1193Provider; } } @@ -111,39 +112,41 @@ const Web3SignerProvider = (props: { EIP1193Provider | undefined >(undefined); - if (window.ethereum !== undefined) { - setProviders({ - ...providers(), - [browserRdns]: { - provider: window.ethereum, - info: { - name: "Browser native", - uuid: browserRdns, - rdns: browserRdns, - disabled: window.ethereum === undefined, + onMount(() => { + if (window.ethereum !== undefined) { + setProviders({ + ...providers(), + [browserRdns]: { + provider: window.ethereum, + info: { + name: "Browser native", + uuid: browserRdns, + rdns: browserRdns, + disabled: window.ethereum === undefined, + }, }, - }, - }); - } + }); + } - window.addEventListener( - "eip6963:announceProvider", - (event: EIP6963AnnounceProviderEvent) => { - log.debug( - `Found EIP-6963 wallet: ${event.detail.info.rdns}: ${event.detail.info.name}`, - ); - const existingProviders = { ...providers() }; + window.addEventListener( + "eip6963:announceProvider", + (event: EIP6963AnnounceProviderEvent) => { + log.debug( + `Found EIP-6963 wallet: ${event.detail.info.rdns}: ${event.detail.info.name}`, + ); + const existingProviders = { ...providers() }; - // We should not show the browser provider when an EIP-6963 provider is found - delete existingProviders[browserRdns]; + // We should not show the browser provider when an EIP-6963 provider is found + delete existingProviders[browserRdns]; - setProviders({ - ...existingProviders, - [event.detail.info.rdns]: event.detail, - }); - }, - ); - window.dispatchEvent(new Event("eip6963:requestProvider")); + setProviders({ + ...existingProviders, + [event.detail.info.rdns]: event.detail, + }); + }, + ); + window.dispatchEvent(new Event("eip6963:requestProvider")); + }); const [contracts] = createResource(async () => { if (props.noFetch || !hasRsk) { diff --git a/src/index.tsx b/src/index.tsx index fd77167f..69a245a8 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,10 +2,10 @@ import "@fontsource/noto-mono"; import "@fontsource/noto-sans"; import "@fontsource/noto-sans/800.css"; -import { Route, Router } from "@solidjs/router"; +import { Route, RouteSectionProps, Router } from "@solidjs/router"; import log from "loglevel"; -import { Match, Switch, createSignal, onMount } from "solid-js"; -import { Show, render } from "solid-js/web"; +import { Match, Show, Switch, createSignal, onMount } from "solid-js"; +import { render } from "solid-js/web"; import Footer from "./components/Footer"; import Nav from "./components/Nav"; @@ -40,7 +40,7 @@ const isEmbedded = () => { return useGlobalContext().embedded(); }; -const App = (props: any) => { +const App = (props: RouteSectionProps) => { const [configError, setConfigError] = createSignal(null); onMount(async () => { diff --git a/src/pages/Create.tsx b/src/pages/Create.tsx index e9278f1a..62b78429 100644 --- a/src/pages/Create.tsx +++ b/src/pages/Create.tsx @@ -1,5 +1,5 @@ import { BigNumber } from "bignumber.js"; -import { Show, createEffect, createMemo, on, onMount } from "solid-js"; +import { Show, createEffect, on, onMount } from "solid-js"; import AddressInput from "../components/AddressInput"; import Asset from "../components/Asset"; @@ -31,8 +31,8 @@ import { isMobile } from "../utils/helper"; import ErrorWasm from "./ErrorWasm"; const Create = () => { - let receiveAmountRef: HTMLInputElement | undefined = undefined; - let sendAmountRef: HTMLInputElement | undefined = undefined; + let receiveAmountRef: HTMLInputElement | undefined; + let sendAmountRef: HTMLInputElement | undefined; const { separator, @@ -141,7 +141,7 @@ const Create = () => { } const hasDot = input.value.includes(".") || input.value.includes(","); const regex = - denomination() == "sat" || hasDot ? /[0-9]/ : /[0-9]|\.|\,/; + denomination() == "sat" || hasDot ? /[0-9]/ : /[0-9]|\.|,/; if (!regex.test(keycode)) { evt.stopPropagation(); evt.preventDefault(); @@ -267,7 +267,7 @@ const Create = () => { ref?.focus(); }); - createMemo(() => { + createEffect(() => { const rAmount = Number(receiveAmount()); if (rAmount > 0) { setReceiveAmountFormatted( @@ -354,8 +354,8 @@ const Create = () => { id="sendAmount" data-testid="sendAmount" value={sendAmountFormatted()} - onpaste={(e) => validatePaste(e)} - onkeypress={(e) => validateInput(e)} + onPaste={(e) => validatePaste(e)} + onKeyPress={(e) => validateInput(e)} onInput={(e) => changeSendAmount(e)} />
@@ -377,8 +377,8 @@ const Create = () => { id="receiveAmount" data-testid="receiveAmount" value={receiveAmountFormatted()} - onpaste={(e) => validatePaste(e)} - onkeypress={(e) => validateInput(e)} + onPaste={(e) => validatePaste(e)} + onKeyPress={(e) => validateInput(e)} onInput={(e) => changeReceiveAmount(e)} />
diff --git a/src/pages/Error.tsx b/src/pages/Error.tsx index 3fd8fca2..c156d0a2 100644 --- a/src/pages/Error.tsx +++ b/src/pages/Error.tsx @@ -1,13 +1,13 @@ import { useGlobalContext } from "../context/Global"; -const Error = ({ error, subline }: { error?: string; subline?: string }) => { +const Error = (props: { error?: string; subline?: string }) => { const { t } = useGlobalContext(); return (
-

⚠️

+

⚠️


-

{error || t("error")}

-

{subline || t("error_subline")}

+

{props.error || t("error")}

+

{props.subline || t("error_subline")}

); }; diff --git a/src/pages/Hero.tsx b/src/pages/Hero.tsx index 28411855..a415fbb9 100644 --- a/src/pages/Hero.tsx +++ b/src/pages/Hero.tsx @@ -54,7 +54,7 @@ export const Hero = () => {
setHideHero(true)}> + onClick={() => setHideHero(true)}>
@@ -62,7 +62,7 @@ export const Hero = () => { {t("headline")} {t("subline")} - navigate("swap")}> + navigate("swap")}> {t("start_swapping")}
@@ -120,25 +120,29 @@ export const Hero = () => { + class="cln" + />
+ class="breez" + />
+ class="lnbits" + />
+ class="rtl" + />
{ + class="fuji" + />
+ class="aqua" + />
+ class="marina" + />
+ class="geyser" + />
+ class="bull-bitcoin" + />
+ class="blitz" + />
+ class="helm" + />
+ class="bancoLibre" + />
+ class="stashPay" + />

{t("partners")}

@@ -209,19 +222,22 @@ export const Hero = () => { + class="blockstream" + />
+ class="diamondhands" + />
+ class="vulpem" + />
diff --git a/src/pages/History.tsx b/src/pages/History.tsx index 03032441..1535f442 100644 --- a/src/pages/History.tsx +++ b/src/pages/History.tsx @@ -21,17 +21,17 @@ type BackupFileType = { version: number; swaps: SomeSwap[] }; // Throws when the file is invalid // Returns the version of the backup file const validateBackupFile = ( - file: BackupFileType | any[] | SomeSwap, + file: BackupFileType | unknown[] | SomeSwap, ): BackupFileType => { - const allSwapsHaveId = (swaps: any[]) => { + const allSwapsHaveId = (swaps: { id: string }[]) => { if (swaps.some((swap) => swap.id === undefined || swap.id === null)) { throw Errors.NotAllElementsHaveAnId; } }; if (file instanceof Array) { - allSwapsHaveId(file); - return { version: 0, swaps: file }; + allSwapsHaveId(file as { id: string }[]); + return { version: 0, swaps: file as SomeSwap[] }; } else if (typeof file === "object") { // A single refund file was uploaded if (["id", "type"].every((key) => key in file)) { @@ -66,7 +66,7 @@ const History = () => { t, } = useGlobalContext(); - const [swaps, setSwaps] = createSignal([]); + const [swaps, setSwaps] = createSignal([]); const deleteLocalStorage = async () => { if (confirm(t("delete_storage"))) { @@ -140,7 +140,7 @@ const History = () => { ref={importRef} required type="file" - style="display: none" + style={{ display: "none" }} accept="application/json" onChange={(e) => importLocalStorage(e)} /> @@ -149,6 +149,7 @@ const History = () => { }> { setSwaps(await getSwaps()); }} diff --git a/src/pages/NotFound.tsx b/src/pages/NotFound.tsx index 9f1d948a..3f52b2c8 100644 --- a/src/pages/NotFound.tsx +++ b/src/pages/NotFound.tsx @@ -12,7 +12,7 @@ const NotFound = () => { {t("not_found")} {t("not_found_subline")} - navigate("/")}> + navigate("/")}> {t("back_to_home")} diff --git a/src/pages/Pay.tsx b/src/pages/Pay.tsx index 48b1ebf0..8bedd40c 100644 --- a/src/pages/Pay.tsx +++ b/src/pages/Pay.tsx @@ -1,6 +1,6 @@ import { useParams } from "@solidjs/router"; import log from "loglevel"; -import { Match, Show, Switch, createEffect, onCleanup } from "solid-js"; +import { Match, Show, Switch, createResource, onCleanup } from "solid-js"; import BlockExplorerLink from "../components/BlockExplorerLink"; import LoadingSpinner from "../components/LoadingSpinner"; @@ -42,8 +42,9 @@ const Pay = () => { setFailureReason, } = usePayContext(); - createEffect(async () => { + createResource(async () => { const currentSwap = await getSwap(params.id); + if (currentSwap) { log.debug("selecting swap", currentSwap); setSwap(currentSwap); diff --git a/src/pages/Refund.tsx b/src/pages/Refund.tsx index 821f143c..3ba6a5a2 100644 --- a/src/pages/Refund.tsx +++ b/src/pages/Refund.tsx @@ -1,7 +1,13 @@ import { useNavigate } from "@solidjs/router"; import log from "loglevel"; import QrScanner from "qr-scanner"; -import { Show, createEffect, createSignal, onCleanup, onMount } from "solid-js"; +import { + Show, + createResource, + createSignal, + onCleanup, + onMount, +} from "solid-js"; import BlockExplorer from "../components/BlockExplorer"; import ConnectWallet from "../components/ConnectWallet"; @@ -35,7 +41,10 @@ const Refund = () => { const [refundJson, setRefundJson] = createSignal(null); const [refundTxId, setRefundTxId] = createSignal(""); - const checkRefundJsonKeys = async (input: HTMLInputElement, json: any) => { + const checkRefundJsonKeys = async ( + input: HTMLInputElement, + json: Record, + ) => { log.debug("checking refund json", json); try { @@ -112,7 +121,7 @@ const Refund = () => { } }); - createEffect(async () => { + createResource(async () => { setLogRefundableSwaps([]); if (refundScanAbort !== undefined) { @@ -172,6 +181,7 @@ const Refund = () => { swapsToRefund.find((found) => found.id === swap.id) === undefined, ) + // eslint-disable-next-line solid/reactivity .map(async (swap) => { try { const res = await getSwapStatus(swap.id); diff --git a/src/pages/RefundStep.tsx b/src/pages/RefundStep.tsx index c20c537f..90e5b735 100644 --- a/src/pages/RefundStep.tsx +++ b/src/pages/RefundStep.tsx @@ -1,6 +1,6 @@ import { useNavigate, useParams } from "@solidjs/router"; import log from "loglevel"; -import { For, createEffect } from "solid-js"; +import { For, createResource } from "solid-js"; import DownloadRefund from "../components/DownloadRefund"; import { useGlobalContext } from "../context/Global"; @@ -13,7 +13,7 @@ const RefundStep = () => { const { setSwap } = usePayContext(); const { getSwap, t } = useGlobalContext(); - createEffect(async () => { + createResource(async () => { const currentSwap = await getSwap(params.id); if (currentSwap) { log.debug("selecting swap", currentSwap); @@ -39,7 +39,7 @@ const RefundStep = () => {
-

⚠️

+

⚠️

{t("backup_refund_skip")}


diff --git a/src/rif/Relay.ts b/src/rif/Relay.ts index 5a871d65..97113780 100644 --- a/src/rif/Relay.ts +++ b/src/rif/Relay.ts @@ -1,5 +1,6 @@ import { config } from "../config"; import { RBTC } from "../consts/Assets"; +import { EnvelopingRequest } from "./types/TypedRequestData"; export type Metadata = { signature?: string; @@ -7,7 +8,7 @@ export type Metadata = { relayHubAddress: string; }; -const sendPostRequest = (url: string, body: any) => +const sendPostRequest = (url: string, body: unknown) => fetch(url, { method: "POST", headers: { @@ -39,7 +40,7 @@ export const getChainInfo = (): Promise<{ }> => fetch(`${config.assets[RBTC].rifRelay}/chain-info`).then(handleResponse); export const estimate = ( - relay: Record, + relay: EnvelopingRequest, metadata: Metadata, ): Promise<{ gasPrice: string; @@ -54,7 +55,7 @@ export const estimate = ( }).then(handleResponse); export const relay = ( - relay: Record, + relay: EnvelopingRequest, metadata: Metadata, ): Promise<{ txHash: string; diff --git a/src/rif/Signer.ts b/src/rif/Signer.ts index 7a6f141f..80db2801 100644 --- a/src/rif/Signer.ts +++ b/src/rif/Signer.ts @@ -26,7 +26,7 @@ const sign = async (signer: Signer, request: EnvelopingRequest) => { const data = getEnvelopingRequestDataV4Field({ chainId: Number(chainId), envelopingRequest: request, - verifier: request.relayData.callForwarder, + verifier: request.relayData.callForwarder as string, requestTypes: isDeployRequest(request) ? deployRequestType : relayRequestType, diff --git a/src/rif/Utils.ts b/src/rif/Utils.ts index 97eaa833..0dbb402f 100644 --- a/src/rif/Utils.ts +++ b/src/rif/Utils.ts @@ -2,7 +2,9 @@ const requestValidSeconds = 172800; const deployOnlyRequestKeys: string[] = ["index"]; -export const isDeployRequest = (request: Record): boolean => { +export const isDeployRequest = (request: { + request: Record; +}): boolean => { return deployOnlyRequestKeys.every((key) => { return key in request.request; }); @@ -11,7 +13,7 @@ export const isDeployRequest = (request: Record): boolean => { export const calculateGasPrice = ( gasPrice: number | string | bigint, minGasPrice: string, -): BigInt => { +): bigint => { const bigGasPrice = BigInt(gasPrice); const bigMinGasPrice = BigInt(minGasPrice); diff --git a/src/rif/types/TypedRequestData.ts b/src/rif/types/TypedRequestData.ts index 7cee87ac..406f8ecb 100644 --- a/src/rif/types/TypedRequestData.ts +++ b/src/rif/types/TypedRequestData.ts @@ -51,8 +51,8 @@ export function getDomainSeparator( } export type EnvelopingRequest = { - request: Record; - relayData: Record; + request: Record; + relayData: Record; }; type GetRequestDataFieldProps = { diff --git a/src/status/InvoiceSet.tsx b/src/status/InvoiceSet.tsx index 1bd10597..eddd2a47 100644 --- a/src/status/InvoiceSet.tsx +++ b/src/status/InvoiceSet.tsx @@ -1,3 +1,5 @@ +import { Show } from "solid-js"; + import LockupEvm from "../components/LockupEvm"; import PayOnchain from "../components/PayOnchain"; import { RBTC } from "../consts/Assets"; @@ -9,26 +11,26 @@ const InvoiceSet = () => { const { swap } = usePayContext(); const submarine = swap() as SubmarineSwap; - if (submarine.assetSend === RBTC) { - return ( - - ); - } - return ( - + + }> + + ); }; diff --git a/src/status/SwapCreated.tsx b/src/status/SwapCreated.tsx index fdac751b..10e80297 100644 --- a/src/status/SwapCreated.tsx +++ b/src/status/SwapCreated.tsx @@ -1,4 +1,5 @@ import { crypto } from "bitcoinjs-lib"; +import { Show } from "solid-js"; import LockupEvm from "../components/LockupEvm"; import PayInvoice from "../components/PayInvoice"; @@ -11,11 +12,28 @@ import { ChainSwap, ReverseSwap } from "../utils/swapCreator"; const SwapCreated = () => { const { swap } = usePayContext(); - if (swap().type === SwapType.Chain) { - const chain = swap() as ChainSwap; + const chain = swap() as ChainSwap; + const reverse = swap() as ReverseSwap; - if (chain.assetSend === RBTC) { - return ( + return ( + + }> + + }> { .sha256(Buffer.from(chain.preimage, "hex")) .toString("hex")} /> - ); - } - - return ( - - ); - } - - const reverse = swap() as ReverseSwap; - return ( - + + ); }; diff --git a/src/status/SwapExpired.tsx b/src/status/SwapExpired.tsx index 66c9148c..a02c45f7 100644 --- a/src/status/SwapExpired.tsx +++ b/src/status/SwapExpired.tsx @@ -1,11 +1,12 @@ import { useNavigate } from "@solidjs/router"; import log from "loglevel"; -import { Accessor, Show, createEffect } from "solid-js"; +import { Accessor, Show, createResource } from "solid-js"; import RefundButton from "../components/RefundButton"; import { useGlobalContext } from "../context/Global"; import { usePayContext } from "../context/Pay"; import { getLockupTransaction } from "../utils/boltzClient"; +import { formatError } from "../utils/errors"; import { ChainSwap, SubmarineSwap } from "../utils/swapCreator"; const SwapExpired = () => { @@ -14,14 +15,16 @@ const SwapExpired = () => { const { t, setTransactionToRefund, transactionToRefund } = useGlobalContext(); - createEffect(async () => { + createResource(async () => { setTransactionToRefund(null); try { const res = await getLockupTransaction(swap().id, swap().type); log.debug(`got swap transaction for ${swap().id}`); setTransactionToRefund(res.hex); - } catch (error: any) { - log.warn(`no swap transaction for: ${swap().id}`, error); + } catch (e) { + log.warn( + `no swap transaction for: ${swap().id}: ${formatError(e)}`, + ); } }); diff --git a/src/status/TransactionConfirmed.tsx b/src/status/TransactionConfirmed.tsx index da185645..b17edb94 100644 --- a/src/status/TransactionConfirmed.tsx +++ b/src/status/TransactionConfirmed.tsx @@ -1,3 +1,5 @@ +import { Show } from "solid-js"; + import ContractTransaction from "../components/ContractTransaction"; import LoadingSpinner from "../components/LoadingSpinner"; import { RBTC } from "../consts/Assets"; @@ -10,17 +12,7 @@ import { prefix0x, satoshiToWei } from "../utils/rootstock"; import { ChainSwap, ReverseSwap } from "../utils/swapCreator"; // TODO: use bignumber for amounts -const ClaimEvm = ({ - useRif, - swapId, - amount, - preimage, - assetReceive, - signerAddress, - refundAddress, - derivationPath, - timeoutBlockHeight, -}: { +const ClaimEvm = (props: { amount: number; swapId: string; useRif: boolean; @@ -37,41 +29,45 @@ const ClaimEvm = ({ return ( { let transactionHash: string; - if (useRif) { + if (props.useRif) { transactionHash = await relayClaimTransaction( signer(), getEtherSwap(), - preimage, - amount, - refundAddress, - timeoutBlockHeight, + props.preimage, + props.amount, + props.refundAddress, + props.timeoutBlockHeight, ); } else { transactionHash = ( await getEtherSwap()[ "claim(bytes32,uint256,address,uint256)" ]( - prefix0x(preimage), - satoshiToWei(amount), - refundAddress, - timeoutBlockHeight, + prefix0x(props.preimage), + satoshiToWei(props.amount), + props.refundAddress, + props.timeoutBlockHeight, ) ).hash; } - const currentSwap = await getSwap(swapId); + const currentSwap = await getSwap(props.swapId); currentSwap.claimTx = transactionHash; setSwap(currentSwap); await setSwapStorage(currentSwap); }} - address={{ derivationPath, address: signerAddress }} + address={{ + address: props.signerAddress, + derivationPath: props.derivationPath, + }} buttonText={t("continue")} promptText={t("transaction_prompt_receive", { button: t("continue"), - asset: assetReceive, + asset: props.assetReceive, })} waitingText={t("tx_ready_to_claim")} /> @@ -82,11 +78,34 @@ const TransactionConfirmed = () => { const { t } = useGlobalContext(); const { swap } = usePayContext(); - if (swap().assetReceive === RBTC) { - if (swap().type === SwapType.Chain) { - const chain = swap() as ChainSwap; + const chain = swap() as ChainSwap; + const reverse = swap() as ReverseSwap; - return ( + return ( + +

{t("tx_confirmed")}

+

{t("tx_ready_to_claim")}

+ +
+ }> + + }> { timeoutBlockHeight={chain.claimDetails.timeoutBlockHeight} assetReceive={chain.assetReceive} /> - ); - } - - const reverse = swap() as ReverseSwap; - - return ( - - ); - } - - return ( -
-

{t("tx_confirmed")}

-

{t("tx_ready_to_claim")}

- -
+
+ ); }; diff --git a/src/utils/boltzClient.ts b/src/utils/boltzClient.ts index b7f4b129..f1c24b46 100644 --- a/src/utils/boltzClient.ts +++ b/src/utils/boltzClient.ts @@ -264,7 +264,7 @@ export const getPartialRefundSignature = async ( index: number, ): Promise => { checkCooperative(); - const res = await fetcher( + const res = await fetcher<{ pubNonce: string; partialSignature: string }>( `/v2/swap/${ type === SwapType.Submarine ? "submarine" : "chain" }/${id}/refund`, @@ -288,12 +288,15 @@ export const getPartialReverseClaimSignature = async ( index: number, ): Promise => { checkCooperative(); - const res = await fetcher(`/v2/swap/reverse/${id}/claim`, { - index, - preimage: preimage.toString("hex"), - pubNonce: pubNonce.toString("hex"), - transaction: transaction.toHex(), - }); + const res = await fetcher<{ pubNonce: string; partialSignature: string }>( + `/v2/swap/reverse/${id}/claim`, + { + index, + preimage: preimage.toString("hex"), + pubNonce: pubNonce.toString("hex"), + transaction: transaction.toHex(), + }, + ); return { pubNonce: Musig.parsePubNonce(res.pubNonce), signature: Buffer.from(res.partialSignature, "hex"), @@ -301,7 +304,11 @@ export const getPartialReverseClaimSignature = async ( }; export const getSubmarineClaimDetails = async (id: string) => { - const res = await fetcher(`/v2/swap/submarine/${id}/claim`); + const res = await fetcher<{ + pubNonce: string; + preimage: string; + transactionHash: string; + }>(`/v2/swap/submarine/${id}/claim`); return { pubNonce: Musig.parsePubNonce(res.pubNonce), preimage: Buffer.from(res.preimage, "hex"), @@ -367,7 +374,7 @@ export const getLockupTransaction = async ( timeoutEta?: number; }>(`/v2/swap/submarine/${id}/transaction`); - case SwapType.Chain: + case SwapType.Chain: { const res = await getChainSwapTransactions(id); return { id: res.userLock.transaction.id, @@ -375,6 +382,7 @@ export const getLockupTransaction = async ( timeoutEta: res.userLock.timeout.eta, timeoutBlockHeight: res.userLock.timeout.blockHeight, }; + } default: throw `cannot get lockup transaction for swap type ${type}`; @@ -433,7 +441,7 @@ export const getChainSwapNewQuote = (id: string) => fetcher<{ amount: number }>(`/v2/swap/chain/${id}/quote`); export const acceptChainSwapNewQuote = (id: string, amount: number) => - fetcher<{}>(`/v2/swap/chain/${id}/quote`, { amount }); + fetcher(`/v2/swap/chain/${id}/quote`, { amount }); export { Pairs, diff --git a/src/utils/compat.ts b/src/utils/compat.ts index b37fd50d..c2c1f8dc 100644 --- a/src/utils/compat.ts +++ b/src/utils/compat.ts @@ -78,7 +78,11 @@ const decodeAddress = (asset: string, addr: string): DecodedAddress => { script, blindingKey: decoded.blindingKey, }; - } catch (e) {} + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (e) { + /* empty */ + } } return { @@ -91,6 +95,8 @@ export const isConfidentialAddress = (addr: string): boolean => { const address = getAddress(LBTC); (address as typeof LiquidAddress).fromConfidential(addr); return true; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { return false; } @@ -105,6 +111,8 @@ const probeUserInputOption = (asset: string, input: string): boolean => { try { decodeAddress(asset, input); return true; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { return false; } @@ -199,7 +207,7 @@ const getConstructRefundTransaction = ( feePerVbyte, (fee) => fn( - refundDetails as any[], + refundDetails as never[], outputScript, timeoutBlockHeight, addOneSatBuffer ? fee + 1 : fee, diff --git a/src/utils/contractLogs.ts b/src/utils/contractLogs.ts index 11bd5da6..cdf48381 100644 --- a/src/utils/contractLogs.ts +++ b/src/utils/contractLogs.ts @@ -1,5 +1,6 @@ import type { EtherSwap } from "boltz-core/typechain/EtherSwap"; import { + BytesLike, Contract, JsonRpcProvider, Result, @@ -135,7 +136,12 @@ async function* scanLogsForPossibleRefunds( const parseLockupEvent = ( etherSwap: EtherSwap, - event: any, + event: { + data: BytesLike; + blockNumber: number; + transactionHash: string; + topics: readonly string[]; + }, ): { data: LogRefundData; decoded: Result; diff --git a/src/utils/denomination.ts b/src/utils/denomination.ts index b89545c7..d0d75265 100644 --- a/src/utils/denomination.ts +++ b/src/utils/denomination.ts @@ -28,7 +28,7 @@ export const formatAmountDenomination = ( fixed: boolean = false, ): string => { switch (denomination) { - case Denomination.Btc: + case Denomination.Btc: { const amountBig = amount.div(satFactor); let amountString = amountBig.toString(); if (fixed) { @@ -49,8 +49,9 @@ export const formatAmountDenomination = ( } return amountString; + } - default: + default: { const chars = amount.toString().split("").reverse(); return chars .reduce( @@ -62,6 +63,7 @@ export const formatAmountDenomination = ( .split("") .reverse() .join(""); + } } }; diff --git a/src/utils/download.ts b/src/utils/download.ts index 54af8e6f..3d961f30 100644 --- a/src/utils/download.ts +++ b/src/utils/download.ts @@ -16,7 +16,7 @@ export const download = (file: string, content: string) => { export const downloadJson = ( file: string, - content: T extends Promise ? never : T, + content: T extends Promise ? never : T, ) => { download( `${file}.json`, diff --git a/src/utils/errors.ts b/src/utils/errors.ts index d46f7753..53cdb02b 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -4,11 +4,13 @@ export const formatError = (message: unknown): string => { } if (typeof message === "object") { - const msgObj = message as Record; + const msgObj = message as Record; if (typeof msgObj.error === "object") { - if (typeof msgObj.error.message === "string") { - return msgObj.error.message; + const err = msgObj.error as Record; + + if (typeof err.message === "string") { + return err.message; } } diff --git a/src/utils/hardware/LedgerSigner.ts b/src/utils/hardware/LedgerSigner.ts index ae2c2e4f..3ac01386 100644 --- a/src/utils/hardware/LedgerSigner.ts +++ b/src/utils/hardware/LedgerSigner.ts @@ -26,7 +26,7 @@ class LedgerSigner implements EIP1193Provider, HardwareSigner { constructor( private readonly t: ( key: DictKey, - values?: Record, + values?: Record, ) => string, ) { this.provider = new JsonRpcProvider( @@ -87,7 +87,7 @@ class LedgerSigner implements EIP1193Provider, HardwareSigner { from: undefined, chainId: network.chainId, gasPrice: feeData.gasPrice, - gasLimit: (txParams as any).gas, + gasLimit: (txParams as unknown as { gas: number }).gas, }); const eth = new Eth(this.transport); diff --git a/src/utils/hardware/TrezorSigner.ts b/src/utils/hardware/TrezorSigner.ts index daa85f19..5876f427 100644 --- a/src/utils/hardware/TrezorSigner.ts +++ b/src/utils/hardware/TrezorSigner.ts @@ -17,6 +17,8 @@ import { config } from "../../config"; import { EIP1193Provider } from "../../consts/Types"; import { HardwareSigner, derivationPaths } from "./HadwareSigner"; +/* eslint-disable @typescript-eslint/no-explicit-any */ + class TrezorSigner implements EIP1193Provider, HardwareSigner { private readonly provider: JsonRpcProvider; diff --git a/src/utils/helper.ts b/src/utils/helper.ts index 1fcfd6b8..dcabd5ac 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -77,9 +77,9 @@ export const getPair = < return pairAssetReceive as T; }; -export const fetcher = async ( +export const fetcher = async ( url: string, - params?: Record, + params?: Record, ): Promise => { let opts = {}; if (params) { @@ -102,6 +102,8 @@ export const fetcher = async ( export const parsePrivateKey = (privateKey: string): ECPairInterface => { try { return ECPair.fromPrivateKey(Buffer.from(privateKey, "hex")); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { // When the private key is not HEX, we try to decode it as WIF return ECPair.fromWIF(privateKey); diff --git a/src/utils/http.ts b/src/utils/http.ts index 2649a603..dc7cfd4d 100644 --- a/src/utils/http.ts +++ b/src/utils/http.ts @@ -1,4 +1,4 @@ -export const checkResponse = (response: Response): Promise => { +export const checkResponse = (response: Response): Promise => { if (!response.ok) { return Promise.reject(response); } diff --git a/src/utils/invoice.ts b/src/utils/invoice.ts index 643b5d3b..8bba59df 100644 --- a/src/utils/invoice.ts +++ b/src/utils/invoice.ts @@ -64,6 +64,8 @@ export const decodeInvoice = ( (tag) => tag.tagName === "payment_hash", ).data as string, }; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { try { const decoded = new Invoice(invoice); @@ -74,6 +76,8 @@ export const decodeInvoice = ( decoded.free(); return res; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { throw new Error("invalid_invoice"); } @@ -224,13 +228,14 @@ const isValidBech32 = (data: string) => { try { bech32.decodeToBytes(data); return true; + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { return false; } }; const emailRegex = - /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; export const isLnurl = (data: string) => { data = data.toLowerCase().replace(invoicePrefix, ""); @@ -244,6 +249,8 @@ export const isBolt12Offer = (offer: string) => { try { new Offer(offer); return true; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { return false; } diff --git a/src/utils/logs.ts b/src/utils/logs.ts index f871cc2b..a4d98de0 100644 --- a/src/utils/logs.ts +++ b/src/utils/logs.ts @@ -24,7 +24,7 @@ export const parseDate = (date: string): Date => { export const deleteOldLogs = async (logsForage: LocalForage) => { const currentDate = new Date(); - await logsForage.iterate((_, date) => { + await logsForage.iterate((_, date) => { const logDate = parseDate(date); // Delete logs older than logDeletionTime @@ -40,9 +40,9 @@ export const deleteOldLogs = async (logsForage: LocalForage) => { }); }; -export const formatLogLine = (message: any[]) => +export const formatLogLine = (message: unknown[]) => message - .map((entry: any) => { + .map((entry: unknown) => { if (entry instanceof Error) { return entry; } @@ -66,7 +66,7 @@ export const injectLogWriter = (logsForage: LocalForage) => { loggerName, ); - return (...message: any[]) => { + return (...message: unknown[]) => { rawLogMethod(...message); const currentDate = getDate(); diff --git a/src/utils/migration.ts b/src/utils/migration.ts index 21ab6e9a..51852759 100644 --- a/src/utils/migration.ts +++ b/src/utils/migration.ts @@ -4,6 +4,7 @@ import { createSignal } from "solid-js"; import { LN } from "../consts/Assets"; import { SwapType } from "../consts/Enums"; +import { SomeSwap } from "./swapCreator"; export const latestStorageVersion = 1; @@ -11,6 +12,7 @@ const storageVersionKey = "version"; const migrateSwapsFromLocalStorage = async (swapsForage: LocalForage) => { const [localStorageSwaps, setLocalStorageSwaps] = makePersisted( + // eslint-disable-next-line solid/reactivity createSignal([], { // Because arrays are the same object when changed, // we have to override the equality checker @@ -31,7 +33,9 @@ const migrateSwapsFromLocalStorage = async (swapsForage: LocalForage) => { return migratedSwapCount; }; -export const migrateSwapToChainSwapFormat = (swap: any): any => { +export const migrateSwapToChainSwapFormat = ( + swap: Record, +): SomeSwap => { if (swap.reverse) { return { ...swap, @@ -39,7 +43,7 @@ export const migrateSwapToChainSwapFormat = (swap: any): any => { type: SwapType.Reverse, assetReceive: swap.asset, claimPrivateKey: swap.privateKey, - }; + } as SomeSwap; } else { return { ...swap, @@ -47,7 +51,7 @@ export const migrateSwapToChainSwapFormat = (swap: any): any => { assetSend: swap.asset, type: SwapType.Submarine, refundPrivateKey: swap.privateKey, - }; + } as SomeSwap; } }; @@ -55,7 +59,7 @@ const migrateStorageToChainSwaps = async (swapsForage: LocalForage) => { const swaps = await swapsForage.keys(); for (const swapId of swaps) { - const swap = await swapsForage.getItem(swapId); + const swap = await swapsForage.getItem>(swapId); await swapsForage.setItem(swapId, migrateSwapToChainSwapFormat(swap)); } @@ -87,13 +91,16 @@ const migrateLocalForage = async ( } }; -export const migrateBackupFile = (version: number, swaps: any[]): any[] => { +export const migrateBackupFile = ( + version: number, + swaps: Record[], +): SomeSwap[] => { switch (version) { case latestStorageVersion: log.debug( `Backup file already at latest version: ${latestStorageVersion}`, ); - return swaps; + return swaps as SomeSwap[]; case 0: { log.debug( diff --git a/src/utils/pairs.ts b/src/utils/pairs.ts index 1fa7e4b5..c32c9993 100644 --- a/src/utils/pairs.ts +++ b/src/utils/pairs.ts @@ -20,6 +20,8 @@ export const isPairValid = ( } else { return pairs[SwapType.Chain][assetSend][assetReceive] !== undefined; } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (e) { return false; } diff --git a/src/utils/patches.ts b/src/utils/patches.ts index f25555f0..fd4b51c8 100644 --- a/src/utils/patches.ts +++ b/src/utils/patches.ts @@ -1,8 +1,13 @@ import { Buffer } from "buffer"; // liquidjs-lib node buffer patch for writeBigUInt64BE -// @ts-ignore -Uint8Array.prototype.writeBigUInt64BE = function (int64: any, offset: any) { + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-expect-error +Uint8Array.prototype.writeBigUInt64BE = function ( + int64: number, + offset: number | undefined, +) { if (typeof int64 !== "number") { int64 = Number(int64); } @@ -23,7 +28,8 @@ Uint8Array.prototype.writeBigUInt64BE = function (int64: any, offset: any) { } }; -// @ts-ignore +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-expect-error Buffer.isBuffer = function (b) { return ( b != null && diff --git a/src/utils/refund.ts b/src/utils/refund.ts index bb32d85d..17954887 100644 --- a/src/utils/refund.ts +++ b/src/utils/refund.ts @@ -219,7 +219,10 @@ export const refund = async ( cooperative, ); } else { - const redeemScript = Buffer.from((swap as any).redeemScript, "hex"); + const redeemScript = Buffer.from( + (swap as unknown as { redeemScript: string }).redeemScript, + "hex", + ); log.debug("redeemScript", redeemScript); const swapOutput = detectSwap(redeemScript, lockupTransaction); log.debug("swapOutput", swapOutput); diff --git a/src/utils/refundFile.ts b/src/utils/refundFile.ts index 5cb544fd..d783e31e 100644 --- a/src/utils/refundFile.ts +++ b/src/utils/refundFile.ts @@ -37,8 +37,8 @@ const getRequiredKeys = ( }; export const validateRefundFile = ( - data: Record, -): { id: string } & Record => { + data: Record, +): { id: string } & Record => { // Compatibility with ancient refund files if (data.asset === undefined && data.currency !== undefined) { data.asset = data.currency; @@ -47,8 +47,8 @@ export const validateRefundFile = ( const isLegacy = "asset" in data; const requiredKeys = getRequiredKeys( isLegacy, - data.asset || data.assetSend, - data.type, + (data.asset || data.assetSend) as string, + data.type as SwapType, ); if (!requiredKeys.every((key) => key in data)) { @@ -62,5 +62,5 @@ export const validateRefundFile = ( }); } - return data as { id: string } & Record; + return data as { id: string } & Record; }; diff --git a/src/utils/validation.ts b/src/utils/validation.ts index ee385ee6..e08d3241 100644 --- a/src/utils/validation.ts +++ b/src/utils/validation.ts @@ -28,6 +28,7 @@ import { createMusig, tweakMusig } from "./taproot/musig"; type ContractGetter = () => BaseContract; +// eslint-disable-next-line @typescript-eslint/no-unused-vars const validateContract = async (getEtherSwap: ContractGetter) => { /* const code = await (await getEtherSwap()).getDeployedCode(); @@ -154,7 +155,7 @@ const validateReverse = async ( const validateSubmarine = async ( swap: SubmarineSwap, getEtherSwap: ContractGetter, - buffer: any, + buffer: typeof BufferBrowser.Buffer, ) => { // Amounts if (swap.expectedAmount !== swap.sendAmount) { @@ -285,7 +286,7 @@ const validateChainSwap = async ( export const validateResponse = async ( swap: SomeSwap, getEtherSwap: ContractGetter, - buffer: any = BufferBrowser, + buffer: typeof BufferBrowser.Buffer = BufferBrowser as never, ): Promise => { try { switch (swap.type) { @@ -321,7 +322,7 @@ export const validateResponse = async ( export const validateInvoice = (inputValue: string) => { const isInputInvoice = isInvoice(inputValue); if (isLnurl(inputValue) || isInputInvoice) { - // set receive/send when invoice differs from the amounts + // set receive/send when the invoice differs from the amounts if (isInputInvoice) { const decoded = decodeInvoice(inputValue); if (decoded.satoshis === 0) { diff --git a/src/utils/wasmSupport.ts b/src/utils/wasmSupport.ts index 8f4bba54..758d449d 100644 --- a/src/utils/wasmSupport.ts +++ b/src/utils/wasmSupport.ts @@ -1,3 +1,7 @@ +import log from "loglevel"; + +import { formatError } from "./errors"; + const checkWasmSupported = () => { try { if ( @@ -13,7 +17,9 @@ const checkWasmSupported = () => { WebAssembly.Instance ); } - } catch (e) {} + } catch (e) { + log.error(`WASM support check failed: ${formatError(e)}`); + } return false; }; diff --git a/tests/components/BlockExplorer.spec.tsx b/tests/components/BlockExplorer.spec.tsx index 2adc0874..9d1a77a1 100644 --- a/tests/components/BlockExplorer.spec.tsx +++ b/tests/components/BlockExplorer.spec.tsx @@ -24,7 +24,9 @@ describe("BlockExplorer", () => { const baseLink = config.assets[asset].blockExplorerUrl.normal; expect(baseLink).toBeDefined(); expect(button).not.toBeUndefined(); - expect((button as any).href).toEqual(`${baseLink}/address/${address}`); + expect((button as HTMLAnchorElement).href).toEqual( + `${baseLink}/address/${address}`, + ); }); test.each` @@ -45,6 +47,8 @@ describe("BlockExplorer", () => { const baseLink = config.assets[asset].blockExplorerUrl.normal; expect(baseLink).toBeDefined(); expect(button).not.toBeUndefined(); - expect((button as any).href).toEqual(`${baseLink}/tx/${txId}`); + expect((button as HTMLAnchorElement).href).toEqual( + `${baseLink}/tx/${txId}`, + ); }); }); diff --git a/tests/components/BlockExplorerLink.spec.tsx b/tests/components/BlockExplorerLink.spec.tsx index 93058359..cfe95d4a 100644 --- a/tests/components/BlockExplorerLink.spec.tsx +++ b/tests/components/BlockExplorerLink.spec.tsx @@ -78,7 +78,7 @@ describe("BlockExplorerLink", () => { lockupDetails: { lockupAddress: "bc1", }, - } as any); + } as ChainSwap); render( () => ""} />, @@ -90,6 +90,7 @@ describe("BlockExplorerLink", () => { )) as HTMLAnchorElement; expect(button.href).toEqual( + // eslint-disable-next-line solid/reactivity `${config.assets[LBTC].blockExplorerUrl.normal}/address/${swap().lockupDetails.lockupAddress}`, ); }); @@ -102,7 +103,7 @@ describe("BlockExplorerLink", () => { lockupDetails: { lockupAddress: "bc1", }, - } as any); + } as ChainSwap); render( () => ""} />, @@ -114,12 +115,15 @@ describe("BlockExplorerLink", () => { )) as HTMLAnchorElement; expect(button.href).toEqual( + // eslint-disable-next-line solid/reactivity `${config.assets[LBTC].blockExplorerUrl.normal}/address/${swap().lockupDetails.lockupAddress}`, ); + // eslint-disable-next-line solid/reactivity setSwap({ ...swap(), claimTx: "123" }); expect(button.href).toEqual( + // eslint-disable-next-line solid/reactivity `${config.assets[BTC].blockExplorerUrl.normal}/tx/${swap().claimTx}`, ); }); diff --git a/tests/components/CopyButton.spec.tsx b/tests/components/CopyButton.spec.tsx index f4640d15..858c13d7 100644 --- a/tests/components/CopyButton.spec.tsx +++ b/tests/components/CopyButton.spec.tsx @@ -53,7 +53,7 @@ describe("CopyButton", () => { test("should copy from a function", async () => { const textToCopy = "50000"; - const [signal, _] = createSignal(textToCopy); + const [signal] = createSignal(textToCopy); const { container: { firstChild: button }, diff --git a/tests/components/PayOnchain.spec.tsx b/tests/components/PayOnchain.spec.tsx index f33b65a6..c304f4a8 100644 --- a/tests/components/PayOnchain.spec.tsx +++ b/tests/components/PayOnchain.spec.tsx @@ -26,10 +26,11 @@ describe("PayOnchain", () => { }, ); - // @ts-ignore + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error navigator.clipboard = { writeText: jest.fn(), - } as any; + } as unknown; const buttons = (await screen.findByTestId( "pay-onchain-buttons", diff --git a/tests/components/RefundButton.spec.tsx b/tests/components/RefundButton.spec.tsx index 75837995..3577a73e 100644 --- a/tests/components/RefundButton.spec.tsx +++ b/tests/components/RefundButton.spec.tsx @@ -5,6 +5,7 @@ import { createSignal } from "solid-js"; import RefundButton from "../../src/components/RefundButton"; import { BTC, LN } from "../../src/consts/Assets"; import { SwapType } from "../../src/consts/Enums"; +import { ChainSwap, SubmarineSwap } from "../../src/utils/swapCreator"; import { contextWrapper } from "../helper"; jest.mock("../../src/utils/boltzClient", () => { @@ -28,14 +29,14 @@ describe("RefundButton", () => { }); test("button should be active after pasting valid address", async () => { - const [swap] = createSignal({ + const [swap] = createSignal({ version: OutputType.Taproot, id: "swap", assetSend: BTC, assetReceive: LN, type: SwapType.Submarine, - }); - render(() => , { + } as SubmarineSwap); + render(() => , { wrapper: contextWrapper, }); const input = (await screen.findByTestId( @@ -57,7 +58,7 @@ describe("RefundButton", () => { test("button should be inactive after pasting the lock address", async () => { const lockupAddress = "2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp"; - const [swap] = createSignal({ + const [swap] = createSignal({ version: 1, date: 1620000000, id: "swap", @@ -69,8 +70,8 @@ describe("RefundButton", () => { address: lockupAddress, bip21: `bitcoin:${lockupAddress}?amount=0.0001`, swapTree: {}, - }); - render(() => , { + } as SubmarineSwap); + render(() => , { wrapper: contextWrapper, }); const input = (await screen.findByTestId( @@ -91,14 +92,14 @@ describe("RefundButton", () => { }); test("button should be inactive after pasting an invalid address", async () => { - const [swap] = createSignal({ + const [swap] = createSignal({ version: OutputType.Taproot, id: "swap", assetSend: BTC, assetReceive: LN, type: SwapType.Submarine, - }); - render(() => , { + } as SubmarineSwap); + render(() => , { wrapper: contextWrapper, }); const input = (await screen.findByTestId( diff --git a/tests/components/SwapList.spec.tsx b/tests/components/SwapList.spec.tsx index 2bb38102..93ec4eea 100644 --- a/tests/components/SwapList.spec.tsx +++ b/tests/components/SwapList.spec.tsx @@ -1,16 +1,17 @@ import { render } from "@solidjs/testing-library"; import SwapList from "../../src/components/SwapList"; +import { SomeSwap } from "../../src/utils/swapCreator"; import { contextWrapper } from "../helper"; describe("SwapList", () => { it("should sort correctly", async () => { - const swapsSorted = [ - { id: "first", date: new Date().getTime() }, - { id: "second", date: 1454533445545 }, - { id: "third", date: 1 }, + const swapsSorted: SomeSwap[] = [ + { id: "first", date: new Date().getTime() } as SomeSwap, + { id: "second", date: 1454533445545 } as SomeSwap, + { id: "third", date: 1 } as SomeSwap, ]; - const swapsSignal = (): any[] => [ + const swapsSignal = (): SomeSwap[] => [ swapsSorted[2], swapsSorted[0], swapsSorted[1], diff --git a/tests/helper.tsx b/tests/helper.tsx index ffb35b04..e3e5923c 100644 --- a/tests/helper.tsx +++ b/tests/helper.tsx @@ -24,7 +24,7 @@ export const TestComponent = () => { return ""; }; -export const contextWrapper = (props: any) => { +export const contextWrapper = (props: { children: Element }) => { return ( diff --git a/tests/mocks/StylesMock.tsx b/tests/mocks/StylesMock.tsx index 816aae29..ee51aa30 100644 --- a/tests/mocks/StylesMock.tsx +++ b/tests/mocks/StylesMock.tsx @@ -1,5 +1,5 @@ const StylesMock = () => { - return
; + return
; }; export default StylesMock; diff --git a/tests/mocks/SvgMock.tsx b/tests/mocks/SvgMock.tsx index fed9821b..71fd2e38 100644 --- a/tests/mocks/SvgMock.tsx +++ b/tests/mocks/SvgMock.tsx @@ -1,5 +1,5 @@ const SvgMock = () => { - return
; + return
; }; export default SvgMock; diff --git a/tests/pages/History.spec.tsx b/tests/pages/History.spec.tsx index fe447d8c..5fbe4fd3 100644 --- a/tests/pages/History.spec.tsx +++ b/tests/pages/History.spec.tsx @@ -1,6 +1,7 @@ import { SwapType } from "../../src/consts/Enums"; import { Errors, validateBackupFile } from "../../src/pages/History"; import { latestStorageVersion } from "../../src/utils/migration"; +import { SomeSwap } from "../../src/utils/swapCreator"; describe("History", () => { test.each` @@ -25,7 +26,7 @@ describe("History", () => { test("should validate single swap refund files", () => { const file = { id: "asdf", type: SwapType.Chain }; - expect(validateBackupFile(file as any)).toEqual({ + expect(validateBackupFile(file as SomeSwap)).toEqual({ version: latestStorageVersion, swaps: [file], }); diff --git a/tests/pages/Refund.spec.tsx b/tests/pages/Refund.spec.tsx index 9ad4c173..a206cfcc 100644 --- a/tests/pages/Refund.spec.tsx +++ b/tests/pages/Refund.spec.tsx @@ -5,6 +5,8 @@ import i18n from "../../src/i18n/i18n"; import Refund from "../../src/pages/Refund"; import { TestComponent, contextWrapper, globalSignals } from "../helper"; +/* eslint-disable @typescript-eslint/no-explicit-any */ + jest.mock("../../src/utils/boltzClient", () => { const originalModule = jest.requireActual("../../src/utils/boltzClient"); diff --git a/tests/setup.ts b/tests/setup.ts index 101b1ce9..9bc2d49b 100644 --- a/tests/setup.ts +++ b/tests/setup.ts @@ -4,7 +4,7 @@ import { setConfig } from "../src/config"; import regtest from "../src/configs/regtest.json"; regtest.loglevel = "error"; -setConfig(regtest); +setConfig(regtest as never); global.TextEncoder = TextEncoder; diff --git a/tests/status/TransactionLockupFailed.spec.tsx b/tests/status/TransactionLockupFailed.spec.tsx index eb1b0406..ab938d1a 100644 --- a/tests/status/TransactionLockupFailed.spec.tsx +++ b/tests/status/TransactionLockupFailed.spec.tsx @@ -4,6 +4,7 @@ import { OutputType } from "boltz-core"; import { BTC, RBTC } from "../../src/consts/Assets"; import i18n from "../../src/i18n/i18n"; import TransactionLockupFailed from "../../src/status/TransactionLockupFailed"; +import { SomeSwap } from "../../src/utils/swapCreator"; import { TestComponent, contextWrapper, payContext } from "../helper"; jest.mock("../../src/utils/boltzClient", () => { @@ -36,7 +37,10 @@ describe("TransactionLockupFailed", () => { wrapper: contextWrapper, }, ); - payContext.setSwap({ assetReceive: BTC, version: type } as any); + payContext.setSwap({ + assetReceive: BTC, + version: type, + } as SomeSwap); await expect( screen.findByText(i18n.en.refund_explainer), @@ -59,7 +63,7 @@ describe("TransactionLockupFailed", () => { payContext.setSwap({ assetReceive: BTC, version: OutputType.Taproot, - } as any); + } as SomeSwap); await expect( screen.findByText(i18n.en.refund), @@ -78,7 +82,7 @@ describe("TransactionLockupFailed", () => { wrapper: contextWrapper, }, ); - payContext.setSwap({ assetReceive: RBTC } as any); + payContext.setSwap({ assetReceive: RBTC } as SomeSwap); await expect( screen.findByText(i18n.en.refund), diff --git a/tests/utils/denomination.spec.ts b/tests/utils/denomination.spec.ts index ef0d993c..f6197d30 100644 --- a/tests/utils/denomination.spec.ts +++ b/tests/utils/denomination.spec.ts @@ -90,7 +90,7 @@ describe("denomination utils", () => { ${"0.123123131"} | ${false} ${"0,123"} | ${true} `("validating regex for $amount", ({ amount, valid }) => { - let regex = getValidationRegex(max); + const regex = getValidationRegex(max); expect(regex.test(amount)).toEqual(valid); }); }); diff --git a/tests/utils/helper.spec.ts b/tests/utils/helper.spec.ts index b073f259..4f308e51 100644 --- a/tests/utils/helper.spec.ts +++ b/tests/utils/helper.spec.ts @@ -1,3 +1,4 @@ +import { Pairs } from "../../src/utils/boltzClient"; import { getPair } from "../../src/utils/helper"; describe("helper", () => { @@ -36,7 +37,7 @@ describe("helper", () => { }, }, }, - } as any; + } as unknown as Pairs; expect(getPair(config, swapType, assetSend, assetReceive)).toEqual( expected, diff --git a/tests/utils/invoice.spec.ts b/tests/utils/invoice.spec.ts index 5e5248c6..dba863ec 100644 --- a/tests/utils/invoice.spec.ts +++ b/tests/utils/invoice.spec.ts @@ -144,7 +144,7 @@ describe("invoice", () => { `( "should detect $invoice as invoice", ({ expected, network, invoice }) => { - setConfig({ network }); + setConfig({ network } as never); expect(isInvoice(invoice)).toEqual(expected); }, ); diff --git a/tests/utils/validation.spec.ts b/tests/utils/validation.spec.ts index ec09a382..043116c0 100644 --- a/tests/utils/validation.spec.ts +++ b/tests/utils/validation.spec.ts @@ -11,7 +11,7 @@ describe("validate responses", () => { const getDeployedCode = jest.fn().mockResolvedValue(code); return jest.fn(() => ({ getDeployedCode, - })) as any; + })) as unknown as () => Contract; }; beforeAll(async () => { diff --git a/tests/utils/webln.spec.ts b/tests/utils/webln.spec.ts index bbf4ca1f..b13913fc 100644 --- a/tests/utils/webln.spec.ts +++ b/tests/utils/webln.spec.ts @@ -2,6 +2,8 @@ import log from "loglevel"; import { detectWebLNProvider, enableWebln } from "../../src/utils/webln"; +/* eslint-disable @typescript-eslint/no-explicit-any */ + describe("WebLN", () => { beforeEach(() => { log.error = jest.fn(); @@ -22,7 +24,6 @@ describe("WebLN", () => { }); test("should call WebLN callback if enable call succeeds", async () => { - // @ts-ignore window.webln = { enable: jest.fn().mockResolvedValue(undefined), } as any; @@ -30,9 +31,7 @@ describe("WebLN", () => { expect(await enableWebln(cb)); - // @ts-ignore expect(window.webln.enable).toHaveBeenCalledTimes(1); - // @ts-ignore expect(window.webln.enable).toHaveBeenCalledWith(); expect(cb).toHaveBeenCalledTimes(1); @@ -40,7 +39,6 @@ describe("WebLN", () => { }); test("should not call WebLN callback if enable call fails", async () => { - // @ts-ignore window.webln = { enable: jest.fn().mockRejectedValue("unauthorized"), } as any; @@ -48,9 +46,7 @@ describe("WebLN", () => { expect(await enableWebln(cb)); - // @ts-ignore expect(window.webln.enable).toHaveBeenCalledTimes(1); - // @ts-ignore expect(window.webln.enable).toHaveBeenCalledWith(); expect(cb).toHaveBeenCalledTimes(0);