diff --git a/package.json b/package.json index 61aa1ea67e8..e6e1213c098 100644 --- a/package.json +++ b/package.json @@ -360,6 +360,7 @@ "ts-node": "10.9.2", "ts-unused-exports": "10.0.1", "tsconfig-paths-webpack-plugin": "4.1.0", + "type-fest": "4.30.2", "typescript": "5.4.5", "vitest": "2.0.5", "vm-browserify": "1.1.2", @@ -370,8 +371,7 @@ "webpack-cli": "5.1.4", "webpack-dev-server": "4.15.1", "webpack-hot-middleware": "2.26.1", - "webpack-shell-plugin": "0.5.0", - "type-fest": "4.30.2" + "webpack-shell-plugin": "0.5.0" }, "resolutions": { "cross-spawn": "7.0.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86a7d775492..269198be63d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -163,7 +163,7 @@ importers: version: 1.2.8(react@18.3.1) '@storybook/addon-styling-webpack': specifier: 1.0.1 - version: 1.0.1(storybook@8.4.4(prettier@3.3.3))(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 1.0.1(storybook@8.4.4(prettier@3.3.3))(webpack@5.94.0) '@styled-system/theme-get': specifier: 5.1.2 version: 5.1.2 @@ -238,7 +238,7 @@ importers: version: 4.0.0(encoding@0.1.13) css-loader: specifier: 7.1.2 - version: 7.1.2(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 7.1.2(webpack@5.94.0) dayjs: specifier: 1.11.8 version: 1.11.8 @@ -358,7 +358,7 @@ importers: version: 0.3.1(encoding@0.1.13) style-loader: specifier: 3.3.4 - version: 3.3.4(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 3.3.4(webpack@5.94.0) ts-debounce: specifier: 4.0.0 version: 4.0.0 @@ -422,7 +422,7 @@ importers: version: 2.2.3 '@mdx-js/loader': specifier: 3.0.0 - version: 3.0.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 3.0.0(webpack@5.94.0) '@pandacss/dev': specifier: 0.46.1 version: 0.46.1(jsdom@22.1.0)(typescript@5.4.5) @@ -431,7 +431,7 @@ importers: version: 1.48.2 '@pmmmwh/react-refresh-webpack-plugin': specifier: 0.5.13 - version: 0.5.13(@types/webpack@5.28.5(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))(react-refresh@0.14.2)(type-fest@4.30.2)(webpack-dev-server@4.15.1(webpack-cli@5.1.4)(webpack@5.94.0))(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 0.5.13(@types/webpack@5.28.5(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4))(react-refresh@0.14.2)(type-fest@4.30.2)(webpack-dev-server@4.15.1)(webpack-hot-middleware@2.26.1)(webpack@5.94.0) '@redux-devtools/cli': specifier: 4.0.0 version: 4.0.0(@babel/core@7.26.0)(@reduxjs/toolkit@2.2.7(react-redux@9.1.2(@types/react@18.3.10)(react@18.3.1)(redux@5.0.1))(react@18.3.1))(@types/react-dom@18.3.0)(@types/styled-components@5.1.34)(encoding@0.1.13)(react-native@0.74.1(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(@types/react@18.3.10)(encoding@0.1.13)(react@18.2.0)) @@ -446,7 +446,7 @@ importers: version: 8.26.0(react@18.3.1) '@sentry/webpack-plugin': specifier: 2.17.0 - version: 2.17.0(encoding@0.1.13)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 2.17.0(encoding@0.1.13)(webpack@5.94.0) '@stacks/connect-react': specifier: 22.2.0 version: 22.2.0(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -470,7 +470,7 @@ importers: version: 8.4.4(react@18.3.1)(storybook@8.4.4(prettier@3.3.3)) '@storybook/addon-webpack5-compiler-swc': specifier: 1.0.5 - version: 1.0.5(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 1.0.5(webpack@5.94.0) '@storybook/blocks': specifier: 8.4.4 version: 8.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3)) @@ -479,7 +479,7 @@ importers: version: 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5) '@storybook/react-webpack5': specifier: 8.4.4 - version: 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(@swc/core@1.7.18)(esbuild@0.24.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + version: 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(@swc/core@1.7.18)(esbuild@0.24.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4) '@storybook/test': specifier: 8.4.4 version: 8.4.4(storybook@8.4.4(prettier@3.3.3)) @@ -554,7 +554,7 @@ importers: version: 0.10.4 '@types/webpack': specifier: 5.28.5 - version: 5.28.5(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + version: 5.28.5(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) '@types/zxcvbn': specifier: 4.4.5 version: 4.4.5 @@ -587,7 +587,7 @@ importers: version: 2.2.2 clean-webpack-plugin: specifier: 4.0.0 - version: 4.0.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 4.0.0(webpack@5.94.0) concurrently: specifier: 8.2.2 version: 8.2.2 @@ -596,7 +596,7 @@ importers: version: 7.0.2 copy-webpack-plugin: specifier: 12.0.2 - version: 12.0.2(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 12.0.2(webpack@5.94.0) cross-env: specifier: 7.0.3 version: 7.0.3 @@ -611,13 +611,13 @@ importers: version: 16.4.2 dotenv-webpack: specifier: 8.1.0 - version: 8.1.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 8.1.0(webpack@5.94.0) esbuild: specifier: 0.24.0 version: 0.24.0 esbuild-loader: specifier: 4.2.2 - version: 4.2.2(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 4.2.2(webpack@5.94.0) eslint-plugin-deprecation: specifier: 2.0.0 version: 2.0.0(eslint@8.56.0)(typescript@5.4.5) @@ -635,13 +635,13 @@ importers: version: 0.11.1(eslint@8.56.0)(typescript@5.4.5) file-loader: specifier: 6.2.0 - version: 6.2.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 6.2.0(webpack@5.94.0) generate-json-webpack-plugin: specifier: 2.0.0 version: 2.0.0 html-webpack-plugin: specifier: 5.6.0 - version: 5.6.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 5.6.0(webpack@5.94.0) jsdom: specifier: 22.1.0 version: 22.1.0 @@ -650,7 +650,7 @@ importers: version: 8.4.47 postcss-loader: specifier: 8.1.1 - version: 8.1.1(postcss@8.4.47)(typescript@5.4.5)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 8.1.1(postcss@8.4.47)(typescript@5.4.5)(webpack@5.94.0) prettier: specifier: 3.3.3 version: 3.3.3 @@ -659,16 +659,16 @@ importers: version: 0.11.10 progress-bar-webpack-plugin: specifier: 2.1.0 - version: 2.1.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 2.1.0(webpack@5.94.0) react-dev-utils: specifier: 12.0.1 - version: 12.0.1(eslint@8.56.0)(typescript@5.4.5)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 12.0.1(eslint@8.56.0)(typescript@5.4.5)(webpack@5.94.0) schema-inspector: specifier: 2.0.2 version: 2.0.2 speed-measure-webpack-plugin: specifier: 1.5.0 - version: 1.5.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + version: 1.5.0(webpack@5.94.0) storybook: specifier: 8.4.4 version: 8.4.4(prettier@3.3.3) @@ -704,7 +704,7 @@ importers: version: 7.8.0(body-parser@1.20.3) webpack: specifier: 5.94.0 - version: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + version: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) webpack-bundle-analyzer: specifier: 4.10.2 version: 4.10.2 @@ -19438,11 +19438,11 @@ snapshots: '@mdn/browser-compat-data@5.3.14': {} - '@mdx-js/loader@3.0.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))': + '@mdx-js/loader@3.0.0(webpack@5.94.0)': dependencies: '@mdx-js/mdx': 3.0.1 source-map: 0.7.4 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) transitivePeerDependencies: - supports-color @@ -19747,7 +19747,7 @@ snapshots: dependencies: playwright: 1.48.2 - '@pmmmwh/react-refresh-webpack-plugin@0.5.13(@types/webpack@5.28.5(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))(react-refresh@0.14.2)(type-fest@4.30.2)(webpack-dev-server@4.15.1(webpack-cli@5.1.4)(webpack@5.94.0))(webpack-hot-middleware@2.26.1)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.13(@types/webpack@5.28.5(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4))(react-refresh@0.14.2)(type-fest@4.30.2)(webpack-dev-server@4.15.1)(webpack-hot-middleware@2.26.1)(webpack@5.94.0)': dependencies: ansi-html-community: 0.0.8 core-js-pure: 3.38.1 @@ -19757,9 +19757,9 @@ snapshots: react-refresh: 0.14.2 schema-utils: 3.3.0 source-map: 0.7.4 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) optionalDependencies: - '@types/webpack': 5.28.5(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + '@types/webpack': 5.28.5(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) type-fest: 4.30.2 webpack-dev-server: 4.15.1(webpack-cli@5.1.4)(webpack@5.94.0) webpack-hot-middleware: 2.26.1 @@ -22350,12 +22350,12 @@ snapshots: dependencies: '@sentry/types': 8.26.0 - '@sentry/webpack-plugin@2.17.0(encoding@0.1.13)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))': + '@sentry/webpack-plugin@2.17.0(encoding@0.1.13)(webpack@5.94.0)': dependencies: '@sentry/bundler-plugin-core': 2.17.0(encoding@0.1.13) unplugin: 1.0.1 uuid: 9.0.1 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) transitivePeerDependencies: - encoding - supports-color @@ -23330,10 +23330,10 @@ snapshots: storybook: 8.4.4(prettier@3.3.3) ts-dedent: 2.2.0 - '@storybook/addon-styling-webpack@1.0.1(storybook@8.4.4(prettier@3.3.3))(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))': + '@storybook/addon-styling-webpack@1.0.1(storybook@8.4.4(prettier@3.3.3))(webpack@5.94.0)': dependencies: '@storybook/node-logger': 8.2.9(storybook@8.4.4(prettier@3.3.3)) - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) transitivePeerDependencies: - storybook @@ -23346,10 +23346,10 @@ snapshots: memoizerific: 1.11.3 storybook: 8.4.4(prettier@3.3.3) - '@storybook/addon-webpack5-compiler-swc@1.0.5(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))': + '@storybook/addon-webpack5-compiler-swc@1.0.5(webpack@5.94.0)': dependencies: '@swc/core': 1.7.18 - swc-loader: 0.2.6(@swc/core@1.7.18)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + swc-loader: 0.2.6(@swc/core@1.7.18)(webpack@5.94.0) transitivePeerDependencies: - '@swc/helpers' - webpack @@ -23364,7 +23364,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/builder-webpack5@8.4.4(@swc/core@1.7.18)(esbuild@0.24.0)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))': + '@storybook/builder-webpack5@8.4.4(@swc/core@1.7.18)(esbuild@0.24.0)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4)': dependencies: '@storybook/core-webpack': 8.4.4(storybook@8.4.4(prettier@3.3.3)) '@types/node': 22.9.0 @@ -23373,23 +23373,23 @@ snapshots: case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.3.1 constants-browserify: 1.0.0 - css-loader: 6.11.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + css-loader: 6.11.0(webpack@5.94.0) es-module-lexer: 1.5.4 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.4.5)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) - html-webpack-plugin: 5.6.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.4.5)(webpack@5.94.0) + html-webpack-plugin: 5.6.0(webpack@5.94.0) magic-string: 0.30.13 path-browserify: 1.0.1 process: 0.11.10 semver: 7.6.3 storybook: 8.4.4(prettier@3.3.3) - style-loader: 3.3.4(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) - terser-webpack-plugin: 5.3.10(@swc/core@1.7.18)(esbuild@0.24.0)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + style-loader: 3.3.4(webpack@5.94.0) + terser-webpack-plugin: 5.3.10(@swc/core@1.7.18)(esbuild@0.24.0)(webpack@5.94.0) ts-dedent: 2.2.0 url: 0.11.3 util: 0.12.5 util-deprecate: 1.0.2 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) - webpack-dev-middleware: 5.3.4(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) + webpack-dev-middleware: 5.3.4(webpack@5.94.0) webpack-hot-middleware: 2.26.1 webpack-virtual-modules: 0.6.2 optionalDependencies: @@ -23461,11 +23461,11 @@ snapshots: dependencies: storybook: 8.4.4(prettier@3.3.3) - '@storybook/preset-react-webpack@8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(@swc/core@1.7.18)(esbuild@0.24.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))': + '@storybook/preset-react-webpack@8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(@swc/core@1.7.18)(esbuild@0.24.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4)': dependencies: '@storybook/core-webpack': 8.4.4(storybook@8.4.4(prettier@3.3.3)) '@storybook/react': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.4.5)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.4.5)(webpack@5.94.0) '@types/node': 22.9.0 '@types/semver': 7.5.8 find-up: 5.0.0 @@ -23477,7 +23477,7 @@ snapshots: semver: 7.6.3 storybook: 8.4.4(prettier@3.3.3) tsconfig-paths: 4.2.0 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: @@ -23492,7 +23492,7 @@ snapshots: dependencies: storybook: 8.4.4(prettier@3.3.3) - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.4.5)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.4.5)(webpack@5.94.0)': dependencies: debug: 4.3.7 endent: 2.1.0 @@ -23502,7 +23502,7 @@ snapshots: react-docgen-typescript: 2.2.2(typescript@5.4.5) tslib: 2.8.1 typescript: 5.4.5 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) transitivePeerDependencies: - supports-color @@ -23512,10 +23512,10 @@ snapshots: react-dom: 18.3.1(react@18.3.1) storybook: 8.4.4(prettier@3.3.3) - '@storybook/react-webpack5@8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(@swc/core@1.7.18)(esbuild@0.24.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))': + '@storybook/react-webpack5@8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(@swc/core@1.7.18)(esbuild@0.24.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4)': dependencies: - '@storybook/builder-webpack5': 8.4.4(@swc/core@1.7.18)(esbuild@0.24.0)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) - '@storybook/preset-react-webpack': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(@swc/core@1.7.18)(esbuild@0.24.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + '@storybook/builder-webpack5': 8.4.4(@swc/core@1.7.18)(esbuild@0.24.0)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4) + '@storybook/preset-react-webpack': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(@swc/core@1.7.18)(esbuild@0.24.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5)(webpack-cli@5.1.4) '@storybook/react': 8.4.4(@storybook/test@8.4.4(storybook@8.4.4(prettier@3.3.3)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.4(prettier@3.3.3))(typescript@5.4.5) '@types/node': 22.9.0 react: 18.3.1 @@ -24368,11 +24368,11 @@ snapshots: anymatch: 3.1.3 source-map: 0.6.1 - '@types/webpack@5.28.5(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))': + '@types/webpack@5.28.5(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4)': dependencies: '@types/node': 20.12.12 tapable: 2.2.1 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) transitivePeerDependencies: - '@swc/core' - esbuild @@ -24881,19 +24881,19 @@ snapshots: '@webassemblyjs/ast': 1.12.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.94.0)': dependencies: - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.94.0)': dependencies: - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))(webpack-dev-server@4.15.1(webpack-cli@5.1.4)(webpack@5.94.0))(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)))': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack-dev-server@4.15.1)(webpack@5.94.0)': dependencies: - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0) optionalDependencies: webpack-dev-server: 4.15.1(webpack-cli@5.1.4)(webpack@5.94.0) @@ -26086,10 +26086,10 @@ snapshots: clean-stack@2.2.0: {} - clean-webpack-plugin@4.0.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + clean-webpack-plugin@4.0.0(webpack@5.94.0): dependencies: del: 4.1.1 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) cli-boxes@3.0.0: {} @@ -26342,7 +26342,7 @@ snapshots: cookie@0.6.0: {} - copy-webpack-plugin@12.0.2(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + copy-webpack-plugin@12.0.2(webpack@5.94.0): dependencies: fast-glob: 3.3.2 glob-parent: 6.0.2 @@ -26350,7 +26350,7 @@ snapshots: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) core-js-compat@3.38.1: dependencies: @@ -26514,7 +26514,7 @@ snapshots: postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 - css-loader@6.11.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + css-loader@6.11.0(webpack@5.94.0): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -26525,9 +26525,9 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) - css-loader@7.1.2(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + css-loader@7.1.2(webpack@5.94.0): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -26538,7 +26538,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) css-prefers-color-scheme@10.0.0(postcss@8.4.47): dependencies: @@ -27105,10 +27105,10 @@ snapshots: dependencies: dotenv: 16.4.5 - dotenv-webpack@8.1.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + dotenv-webpack@8.1.0(webpack@5.94.0): dependencies: dotenv-defaults: 2.0.2 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) dotenv@16.4.5: {} @@ -27405,12 +27405,12 @@ snapshots: get-value: 2.0.6 sliced: 1.0.1 - esbuild-loader@4.2.2(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + esbuild-loader@4.2.2(webpack@5.94.0): dependencies: esbuild: 0.21.5 get-tsconfig: 4.8.1 loader-utils: 2.0.4 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) webpack-sources: 1.4.3 esbuild-register@3.6.0(esbuild@0.21.5): @@ -28028,11 +28028,11 @@ snapshots: dependencies: flat-cache: 3.2.0 - file-loader@6.2.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + file-loader@6.2.0(webpack@5.94.0): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) file-size@1.0.0: {} @@ -28152,7 +28152,7 @@ snapshots: forever-agent@0.6.1: {} - fork-ts-checker-webpack-plugin@6.5.3(eslint@8.56.0)(typescript@5.4.5)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + fork-ts-checker-webpack-plugin@6.5.3(eslint@8.56.0)(typescript@5.4.5)(webpack@5.94.0): dependencies: '@babel/code-frame': 7.24.7 '@types/json-schema': 7.0.15 @@ -28168,11 +28168,11 @@ snapshots: semver: 7.6.3 tapable: 1.1.3 typescript: 5.4.5 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) optionalDependencies: eslint: 8.56.0 - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.4.5)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.4.5)(webpack@5.94.0): dependencies: '@babel/code-frame': 7.26.2 chalk: 4.1.2 @@ -28187,7 +28187,7 @@ snapshots: semver: 7.6.3 tapable: 2.2.1 typescript: 5.4.5 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) form-data-encoder@2.1.4: {} @@ -28785,7 +28785,7 @@ snapshots: relateurl: 0.2.7 terser: 5.31.6 - html-webpack-plugin@5.6.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + html-webpack-plugin@5.6.0(webpack@5.94.0): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -28793,7 +28793,7 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) htmlparser2@6.1.0: dependencies: @@ -32067,14 +32067,14 @@ snapshots: '@csstools/utilities': 2.0.0(postcss@8.4.47) postcss: 8.4.47 - postcss-loader@8.1.1(postcss@8.4.47)(typescript@5.4.5)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + postcss-loader@8.1.1(postcss@8.4.47)(typescript@5.4.5)(webpack@5.94.0): dependencies: cosmiconfig: 9.0.0(typescript@5.4.5) jiti: 1.21.6 postcss: 8.4.47 semver: 7.6.3 optionalDependencies: - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) transitivePeerDependencies: - typescript @@ -32341,11 +32341,11 @@ snapshots: process@0.11.10: {} - progress-bar-webpack-plugin@2.1.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + progress-bar-webpack-plugin@2.1.0(webpack@5.94.0): dependencies: chalk: 3.0.0 progress: 2.0.3 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) progress@1.1.8: {} @@ -32507,7 +32507,7 @@ snapshots: react: 18.3.1 tween-functions: 1.2.0 - react-dev-utils@12.0.1(eslint@8.56.0)(typescript@5.4.5)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + react-dev-utils@12.0.1(eslint@8.56.0)(typescript@5.4.5)(webpack@5.94.0): dependencies: '@babel/code-frame': 7.24.7 address: 1.2.2 @@ -32518,7 +32518,7 @@ snapshots: escape-string-regexp: 4.0.0 filesize: 8.0.7 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(eslint@8.56.0)(typescript@5.4.5)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + fork-ts-checker-webpack-plugin: 6.5.3(eslint@8.56.0)(typescript@5.4.5)(webpack@5.94.0) global-modules: 2.0.0 globby: 11.1.0 gzip-size: 6.0.0 @@ -32533,7 +32533,7 @@ snapshots: shell-quote: 1.8.1 strip-ansi: 6.0.1 text-table: 0.2.0 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: @@ -33796,10 +33796,10 @@ snapshots: transitivePeerDependencies: - supports-color - speed-measure-webpack-plugin@1.5.0(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + speed-measure-webpack-plugin@1.5.0(webpack@5.94.0): dependencies: chalk: 4.1.2 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) split2@4.2.0: {} @@ -34024,9 +34024,9 @@ snapshots: structured-headers@0.4.1: {} - style-loader@3.3.4(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + style-loader@3.3.4(webpack@5.94.0): dependencies: - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) style-to-object@0.4.4: dependencies: @@ -34111,11 +34111,11 @@ snapshots: csso: 5.0.5 picocolors: 1.1.0 - swc-loader@0.2.6(@swc/core@1.7.18)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + swc-loader@0.2.6(@swc/core@1.7.18)(webpack@5.94.0): dependencies: '@swc/core': 1.7.18 '@swc/counter': 0.1.3 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) symbol-tree@3.2.4: {} @@ -34183,14 +34183,14 @@ snapshots: ansi-escapes: 4.3.2 supports-hyperlinks: 2.3.0 - terser-webpack-plugin@5.3.10(@swc/core@1.7.18)(esbuild@0.24.0)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + terser-webpack-plugin@5.3.10(@swc/core@1.7.18)(esbuild@0.24.0)(webpack@5.94.0): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.31.6 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) optionalDependencies: '@swc/core': 1.7.18 esbuild: 0.24.0 @@ -35093,9 +35093,9 @@ snapshots: webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))(webpack-dev-server@4.15.1(webpack-cli@5.1.4)(webpack@5.94.0))(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.94.0) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.94.0) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack-dev-server@4.15.1)(webpack@5.94.0) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.5 @@ -35104,20 +35104,20 @@ snapshots: import-local: 3.2.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) webpack-merge: 5.10.0 optionalDependencies: webpack-bundle-analyzer: 4.10.2 webpack-dev-server: 4.15.1(webpack-cli@5.1.4)(webpack@5.94.0) - webpack-dev-middleware@5.3.4(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))): + webpack-dev-middleware@5.3.4(webpack@5.94.0): dependencies: colorette: 2.0.20 memfs: 3.5.3 mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.2.0 - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) webpack-dev-server@4.15.1(webpack-cli@5.1.4)(webpack@5.94.0): dependencies: @@ -35149,10 +35149,10 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 5.3.4(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + webpack-dev-middleware: 5.3.4(webpack@5.94.0) ws: 8.17.1 optionalDependencies: - webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)) + webpack: 5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0) transitivePeerDependencies: - bufferutil @@ -35184,7 +35184,7 @@ snapshots: webpack-virtual-modules@0.6.2: {} - webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0)): + webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4): dependencies: '@types/estree': 1.0.5 '@webassemblyjs/ast': 1.12.1 @@ -35206,7 +35206,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.7.18)(esbuild@0.24.0)(webpack@5.94.0(@swc/core@1.7.18)(esbuild@0.24.0)(webpack-cli@5.1.4(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@4.15.1)(webpack@5.94.0))) + terser-webpack-plugin: 5.3.10(@swc/core@1.7.18)(esbuild@0.24.0)(webpack@5.94.0) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: diff --git a/scripts/generate-manifest.js b/scripts/generate-manifest.js index 37f88b9652d..b5bc847deda 100644 --- a/scripts/generate-manifest.js +++ b/scripts/generate-manifest.js @@ -69,7 +69,7 @@ const manifest = { manifest_version: 3, author: 'Leather Wallet, LLC', description: 'Leather Bitcoin Wallet - Your Bitcoin Wallet for DeFi, NFTs, Ordinals, and dApps', - permissions: ['contextMenus', 'storage', 'unlimitedStorage', 'alarms', 'notifications'], + permissions: ['contextMenus', 'storage', 'unlimitedStorage', 'notifications'], commands: { _execute_browser_action: { suggested_key: { diff --git a/src/app/features/address-monitor/use-monitorable-addresses.ts b/src/app/features/address-monitor/use-monitorable-addresses.ts new file mode 100644 index 00000000000..79c0c4df907 --- /dev/null +++ b/src/app/features/address-monitor/use-monitorable-addresses.ts @@ -0,0 +1,78 @@ +import { useMemo } from 'react'; + +import type { HDKey } from '@scure/bip32'; +import type { P2Ret } from '@scure/btc-signer/payment'; + +import { + type SupportedPaymentType, + deriveAddressIndexZeroFromAccount, + getNativeSegwitPaymentFromAddressIndex, + getTaprootPaymentFromAddressIndex, +} from '@leather.io/bitcoin'; +import type { BitcoinNetworkModes } from '@leather.io/models'; +import { createNullArrayOfLength, isDefined } from '@leather.io/utils'; + +import { useCurrentAccountIndex } from '@app/store/accounts/account'; +import { useGenerateNativeSegwitAccount } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks'; +import { useGenerateTaprootAccount } from '@app/store/accounts/blockchain/bitcoin/taproot-account.hooks'; +import { useStacksAccounts } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks'; +import { useCurrentNetworkId } from '@app/store/networks/networks.selectors'; +import type { MonitoredAddress } from '@background/monitors/address-monitor'; + +const paymentFnMap: Record< + SupportedPaymentType, + (keychain: HDKey, network: BitcoinNetworkModes) => P2Ret +> = { + p2tr: getTaprootPaymentFromAddressIndex, + p2wpkh: getNativeSegwitPaymentFromAddressIndex, +}; + +export function useMonitorableAddresses() { + const currentAccountIndex = useCurrentAccountIndex(); + const currentNetworkId = useCurrentNetworkId(); + const createNativeSegwitAccount = useGenerateNativeSegwitAccount(); + const createTaprootAccount = useGenerateTaprootAccount(); + + const stacksAccounts = useStacksAccounts(); + + return useMemo(() => { + if (!stacksAccounts || !currentNetworkId) return; + + const stacksAddresses = stacksAccounts.map( + account => + ({ + accountIndex: account.index, + address: account.address, + chain: 'stacks', + isCurrent: account.index === currentAccountIndex, + }) as MonitoredAddress + ); + const btcAddresses = createNullArrayOfLength(stacksAccounts.length).flatMap((_, index) => + [createNativeSegwitAccount(index), createTaprootAccount(index)] + .filter(isDefined) + .map(account => { + const addressIndexKeychain = deriveAddressIndexZeroFromAccount(account.keychain); + if (account.type !== 'p2tr' && account.type !== 'p2wpkh') return undefined; + const payment = paymentFnMap[account.type](addressIndexKeychain, 'mainnet'); + return { + accountIndex: index, + address: payment.address, + chain: 'bitcoin', + isCurrent: index === currentAccountIndex, + } as MonitoredAddress; + }) + .filter(isDefined) + ); + // if one address array is empty and the other not, we're in an intermediate state + return (stacksAddresses.length === 0 && btcAddresses.length > 0) || + (btcAddresses.length === 0 && stacksAddresses.length > 0) + ? undefined + : [...stacksAddresses, ...btcAddresses]; + }, [ + createNativeSegwitAccount, + createTaprootAccount, + stacksAccounts, + currentNetworkId, + currentAccountIndex, + ]); +} diff --git a/src/app/features/address-monitor/use-sync-address-monitor.ts b/src/app/features/address-monitor/use-sync-address-monitor.ts new file mode 100644 index 00000000000..d420d1e6abb --- /dev/null +++ b/src/app/features/address-monitor/use-sync-address-monitor.ts @@ -0,0 +1,29 @@ +import { useEffect, useRef } from 'react'; + +import isEqual from 'lodash.isequal'; + +import { logger } from '@shared/logger'; +import { InternalMethods } from '@shared/message-types'; +import { sendMessage } from '@shared/messages'; + +import { useMonitorableAddresses } from '@app/features/address-monitor/use-monitorable-addresses'; +import type { MonitoredAddress } from '@background/monitors/address-monitor'; + +export function useSyncAddressMonitor() { + const addresses = useMonitorableAddresses(); + const prevAddresses = useRef([]); + + useEffect(() => { + if (addresses && !isEqual(addresses, prevAddresses.current)) { + prevAddresses.current = addresses; + + logger.debug('Syncing Monitored Addresses: ', addresses); + sendMessage({ + method: InternalMethods.AddressMonitorUpdated, + payload: { + addresses, + }, + }); + } + }, [addresses]); +} diff --git a/src/app/features/container/container.tsx b/src/app/features/container/container.tsx index bc819ce393a..904417fe2ae 100644 --- a/src/app/features/container/container.tsx +++ b/src/app/features/container/container.tsx @@ -19,6 +19,7 @@ import { useOnWalletLock } from '@app/routes/hooks/use-on-wallet-lock'; import { useAppDispatch, useHasStateRehydrated } from '@app/store'; import { stxChainSlice } from '@app/store/chains/stx-chain.slice'; +import { useSyncAddressMonitor } from '../address-monitor/use-sync-address-monitor'; import { useRestoreFormState } from '../popup-send-form-restoration/use-restore-form-state'; export function Container() { @@ -28,7 +29,7 @@ export function Container() { const dispatch = useAppDispatch(); const hasStateRehydrated = useHasStateRehydrated(); - + useSyncAddressMonitor(); useOnWalletLock(() => closeWindow()); useOnSignOut(() => closeWindow()); useRestoreFormState(); diff --git a/src/app/pages/unlock.tsx b/src/app/pages/unlock.tsx index 9e6777ee018..fd087ebeb2a 100644 --- a/src/app/pages/unlock.tsx +++ b/src/app/pages/unlock.tsx @@ -4,6 +4,8 @@ import { Content } from '@app/components/layout'; import { RequestPassword } from '@app/components/request-password'; import { UnlockHeader } from '@app/features/container/headers/unlock.header'; +import { useGetAddresses } from './rpc-get-addresses/use-get-addresses'; + export function Unlock() { const navigate = useNavigate(); // Here we want to return to the previous route. The user could land on any diff --git a/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts b/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts index 7b102daf32c..f7ee892e687 100644 --- a/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts +++ b/src/app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks.ts @@ -45,7 +45,7 @@ const selectCurrentNetworkNativeSegwitAccountBuilder = createSelector( nativeSegwitKeychains[bitcoinNetworkToNetworkMode(network.chain.bitcoin.bitcoinNetwork)] ); -function useNativeSegwitAccountBuilder() { +export function useGenerateNativeSegwitAccount() { return useSelector(selectCurrentNetworkNativeSegwitAccountBuilder); } @@ -72,7 +72,7 @@ export function useNativeSegwitNetworkSigners() { } export function useNativeSegwitSigner(accountIndex: number) { - const account = useNativeSegwitAccountBuilder()(accountIndex); + const account = useGenerateNativeSegwitAccount()(accountIndex); const extendedPublicKeyVersions = useBitcoinExtendedPublicKeyVersions(); return useMemo(() => { diff --git a/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts b/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts index 26c5a08acc1..4ed01a33fc3 100644 --- a/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts +++ b/src/app/store/accounts/blockchain/bitcoin/taproot-account.hooks.ts @@ -45,6 +45,11 @@ const selectCurrentTaprootAccount = createSelector( (taprootKeychain, accountIndex) => taprootKeychain(accountIndex) ); +export function useGenerateTaprootAccount() { + const generateTaprootAccount = useSelector(selectCurrentNetworkTaprootAccountBuilder); + return useMemo(() => generateTaprootAccount, [generateTaprootAccount]); +} + export function useTaprootAccount(accountIndex: number) { const generateTaprootAccount = useSelector(selectCurrentNetworkTaprootAccountBuilder); return useMemo( diff --git a/src/app/store/chains/stx-chain.selectors.ts b/src/app/store/chains/stx-chain.selectors.ts index 567a6754286..7e2affdec39 100644 --- a/src/app/store/chains/stx-chain.selectors.ts +++ b/src/app/store/chains/stx-chain.selectors.ts @@ -1,3 +1,9 @@ +import { useSelector } from 'react-redux'; + import { RootState } from '@app/store'; export const selectStacksChain = (state: RootState) => state.chains.stx; + +export function useStacksChain() { + return useSelector(selectStacksChain); +} diff --git a/src/background/alarms/transaction-monitor.ts b/src/background/alarms/transaction-monitor.ts deleted file mode 100644 index 7eb943cbc76..00000000000 --- a/src/background/alarms/transaction-monitor.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable no-console */ -import { z } from 'zod'; - -import { supportedBlockchains } from '@leather.io/models'; - -export const pendingConfirmationSchema = z.object({ - chain: z.enum(supportedBlockchains), - txid: z.string(), -}); - -export type PendingConfirmation = z.infer; - -export const pendingConfirmationsAlarm = 'pending-confirmation-alarm2'; -const PENDING_CONFIRMATIONS_STORE = 'pendingConfirmations'; - -export async function monitorPendingConfirmations() { - console.log('monitoring confirmations'); - const alarm = await chrome.alarms.get(pendingConfirmationsAlarm); - console.log(JSON.stringify(alarm)); - - if (!alarm) { - console.log('starting pending confirmation alarm'); - await chrome.alarms.create(pendingConfirmationsAlarm, { - periodInMinutes: 1, - }); - await chrome.alarms.onAlarm.addListener(alarm => { - if (alarm.name === pendingConfirmationsAlarm) { - // eslint-disable-next-line no-console - console.log('alarm running'); - } - }); - } -} - -interface PendingConfirmationStore { - pendingConfirmations: PendingConfirmation[]; -} - -export async function readPendingConfirmationsStore() { - const { pendingConfirmations = [] } = chrome.storage.local.get( - PENDING_CONFIRMATIONS_STORE - ) as unknown as PendingConfirmationStore; - - return pendingConfirmations; -} - -export async function writeTransaction(pendingConfirmation: PendingConfirmation) { - const exisitingPendingConfirmations = await readPendingConfirmationsStore(); - return await chrome.storage.local.set({ - [PENDING_CONFIRMATIONS_STORE]: [pendingConfirmation, ...exisitingPendingConfirmations], - }); -} diff --git a/src/background/background.ts b/src/background/background.ts index 9e53b04c52a..10fb4f7aa68 100755 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -6,10 +6,6 @@ import { CONTENT_SCRIPT_PORT, type LegacyMessageFromContentScript } from '@share import { WalletRequests } from '@shared/rpc/rpc-methods'; import { warnUsersAboutDevToolsDangers } from '@shared/utils/dev-tools-warning-log'; -import { - monitorPendingConfirmations, - pendingConfirmationsAlarm, -} from './alarms/transaction-monitor'; import { initContextMenuActions } from './init-context-menus'; import { internalBackgroundMessageHandler } from './messaging/internal-methods/message-handler'; import { @@ -17,6 +13,7 @@ import { isLegacyMessage, } from './messaging/legacy/legacy-external-message-handler'; import { rpcMessageHandler } from './messaging/rpc-message-handler'; +import { initAddressMonitor } from './monitors/address-monitor'; initContextMenuActions(); warnUsersAboutDevToolsDangers(); @@ -64,13 +61,6 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { return true; }); -console.log('hello from background'); - -monitorPendingConfirmations() - .then(() => { - console.log('confirmation called'); - }) - .catch(() => { - // eslint-disable-next-line no-console - console.error('whoops!'); - }); +initAddressMonitor().catch(e => { + logger.error('Unable to Initialise Address Monitor: ', e); +}); diff --git a/src/background/messaging/internal-methods/message-handler.ts b/src/background/messaging/internal-methods/message-handler.ts index a4aa99cd3cd..3689bbffad2 100644 --- a/src/background/messaging/internal-methods/message-handler.ts +++ b/src/background/messaging/internal-methods/message-handler.ts @@ -1,6 +1,9 @@ import { logger } from '@shared/logger'; +import { InternalMethods } from '@shared/message-types'; import { BackgroundMessages } from '@shared/messages'; +import { syncAddressMonitor } from '@background/monitors/address-monitor'; + function validateMessagesAreFromExtension(sender: chrome.runtime.MessageSender) { // Only respond to internal messages from our UI, not content scripts in other applications return sender.url?.startsWith(chrome.runtime.getURL('')); @@ -28,5 +31,16 @@ export async function internalBackgroundMessageHandler( return; } logger.debug('Internal message', message); + + switch (message.method) { + case InternalMethods.AddressMonitorUpdated: + await syncAddressMonitor(message.payload.addresses); + break; + } + + if (message.method.includes('bitcoinKeys/signOut')) { + await syncAddressMonitor([]); + } + sendResponse(); } diff --git a/src/background/monitors/address-monitor.ts b/src/background/monitors/address-monitor.ts new file mode 100644 index 00000000000..54c1070fb0e --- /dev/null +++ b/src/background/monitors/address-monitor.ts @@ -0,0 +1,54 @@ +/* eslint-disable no-console */ +import { z } from 'zod'; + +import { BitcoinTransactionMonitor } from './address-monitors/bitcoin-transaction-monitor'; + +export const monitoredAddressSchema = z.object({ + chain: z.enum(['bitcoin', 'stacks']), + accountIndex: z.number(), + isCurrent: z.boolean(), + address: z.string(), +}); + +export type MonitoredAddress = z.infer; + +export interface AddressMonitor { + syncAddresses(addresses: MonitoredAddress[]): void; +} + +export class AddressMonitorContainer { + private _monitors: AddressMonitor[] = []; + + init(addresses: MonitoredAddress[]) { + this._monitors = [new BitcoinTransactionMonitor(addresses)]; + } + sync(addresses: MonitoredAddress[]) { + this._monitors.forEach(monitor => monitor.syncAddresses(addresses)); + } +} + +const monitorContainer = new AddressMonitorContainer(); + +export async function initAddressMonitor() { + const addresses = await readMonitoredAddressStore(); + monitorContainer.init(addresses); +} + +export async function syncAddressMonitor(addresses: MonitoredAddress[]) { + await writeMonitoredAddressStore(addresses); + monitorContainer.sync(addresses); +} + +const ADDRESS_MONITOR_STORE = 'addressMonitorStore'; + +export async function readMonitoredAddressStore() { + const result = await chrome.storage.local.get(ADDRESS_MONITOR_STORE); + const addresses = result[ADDRESS_MONITOR_STORE] || []; + return addresses; +} + +export async function writeMonitoredAddressStore(addresses: MonitoredAddress[]) { + await chrome.storage.local.set({ + [ADDRESS_MONITOR_STORE]: addresses, + }); +} diff --git a/src/background/monitors/address-monitors/bitcoin-transaction-monitor.ts b/src/background/monitors/address-monitors/bitcoin-transaction-monitor.ts new file mode 100644 index 00000000000..5fd0ff0b2c3 --- /dev/null +++ b/src/background/monitors/address-monitors/bitcoin-transaction-monitor.ts @@ -0,0 +1,222 @@ +/* eslint-disable no-console */ +import axios from 'axios'; + +import { isDefined, sumNumbers } from '@leather.io/utils'; + +import { logger } from '@shared/logger'; + +import type { AddressMonitor, MonitoredAddress } from '../address-monitor'; + +interface MempoolWsBitcoinTxMessage { + 'multi-address-transactions': { + [address: string]: { + mempool: MempoolWsBitcoinTx[]; + confirmed: MempoolWsBitcoinTx[]; + removed: MempoolWsBitcoinTx[]; + }; + }; +} + +interface MempoolWsBitcoinTx { + txid: string; + vin: MempoolWsBitcoinVin[]; + vout: MempoolWsBitcoinVout[]; +} + +interface MempoolWsBitcoinVin { + txid: string; + prevout: MempoolWsBitcoinVout; +} + +interface MempoolWsBitcoinVout { + scriptpubkey_address: string; + value: number; +} + +interface MempoolBtcPrice { + time: number; + USD: number; +} + +export class BitcoinTransactionMonitor implements AddressMonitor { + private _ws: WebSocket | null = null; + private _addresses: MonitoredAddress[]; + private _keepAliveInterval: NodeJS.Timeout | null = null; + private _btcPriceUsd: number = 0; + + constructor(addresses: MonitoredAddress[]) { + this._addresses = this._filterAddresses(addresses); + // only connect if we have addresses + if (addresses.length > 0) { + this._connect(); + } + } + + public syncAddresses(addresses: MonitoredAddress[]) { + this._addresses = this._filterAddresses(addresses); + + if (this._addresses.length > 0) { + if (!this._ws || this._ws.readyState >= 2) { + this._connect(); + } else if (this._ws.readyState === this._ws.OPEN) { + this._sendWsTrackAddressSubscribe(); + } + } else { + logger.debug('Disconnecting Bitcon Tx Monitor'); + this._cleanup(); + } + } + + private _filterAddresses(addresses: MonitoredAddress[]) { + return addresses.filter(a => a.chain === 'bitcoin'); + } + + private _startKeepAlive() { + if (this._keepAliveInterval) { + clearInterval(this._keepAliveInterval); + } + + this._keepAliveInterval = setInterval(() => { + if (this._ws?.readyState === WebSocket.OPEN) { + this._ws.send( + JSON.stringify({ + ping: 'keep-alive', + }) + ); + } + }, 20 * 1000); + } + + private _sendWsTrackAddressSubscribe() { + const addresses = this._addresses.map(a => a.address); + logger.debug(`Subscribing to ${addresses.length} Track Addresses`); + this._ws!.send( + JSON.stringify({ + 'track-addresses': addresses, + }) + ); + } + + private _cleanup() { + if (this._keepAliveInterval) { + clearInterval(this._keepAliveInterval); + this._keepAliveInterval = null; + } + + if (this._ws) { + this._ws.close(); + this._ws = null; + } + } + + private _connect() { + logger.debug('Connecting Bitcoin Tx Monitor'); + + this._cleanup(); + + this._ws = new WebSocket('wss://leather.mempool.space/api/v1/ws'); + + this._ws.onopen = async () => { + logger.debug('Connected to Mempool WebSocket'); + this._sendWsTrackAddressSubscribe(); + this._startKeepAlive(); + this._fetchBtcPrice(); + }; + + this._ws.onmessage = async event => { + logger.debug('Mempool WS Message Received', event.data); + await this._handleMessageEvent(event); + }; + + this._ws.onerror = error => { + console.error('Mempool WebSocket Error, ', error); + }; + + this._ws.onclose = event => { + logger.debug('Disconnected from Mempool WebSocket.', event.reason); + if (this._addresses.length > 0) { + setTimeout(() => { + this._connect(); + }, 300); + } + }; + } + + private _fetchBtcPrice() { + axios + .get('https://leather.mempool.space/api/v1/prices') + .then(res => { + this._btcPriceUsd = res.data.USD; + }) + .catch(e => { + logger.debug('Unable to fetch BTC price, ', e); + }); + } + + private async _handleMessageEvent(event: MessageEvent) { + const message = JSON.parse(event.data); + if (message['multi-address-transactions']) { + await this._handleTransactionMessage(message); + } else if (message['conversions']) { + const prices = message['conversions'] as MempoolBtcPrice; + this._btcPriceUsd = prices.USD; + } else { + logger.debug('Unrecognized Message Type: ', event.data); + } + } + + private async _handleTransactionMessage(msg: MempoolWsBitcoinTxMessage) { + try { + for (const address of Object.keys(msg['multi-address-transactions']) + .filter(address => msg['multi-address-transactions'][address].confirmed.length > 0) // only confirmed transactions + .map(address => this._addresses.find(a => a.address === address)) // get monitored address + .filter(isDefined)) { + const transaction = msg['multi-address-transactions'][address.address].confirmed[0]; + let satValue = 0; + let isSender; + + const vin = transaction.vin.find( + vin => vin.prevout.scriptpubkey_address === address.address + ); + if (vin) { + // address is sender, value is sum of all vouts not to same address + isSender = true; + satValue = sumNumbers( + transaction.vout + .filter(vout => vout.scriptpubkey_address !== address.address) + .map(vout => vout.value) + ).toNumber(); + } else { + const vout = transaction.vout.find(vout => vout.scriptpubkey_address === address.address); + if (vout) { + // address is receiver, value is in matching vout + isSender = false; + satValue = vout.value; + } + } + + if (satValue > 0) { + const btcValue = satValue / 100_000_000; + const usdValue = btcValue * this._btcPriceUsd; + await this._sendNotification( + `You ${isSender ? 'sent' : 'received'} Bitcoin!`, + `Account ${address.accountIndex + 1} ${isSender ? 'sent' : 'received'} ${btcValue} BTC ($${usdValue.toFixed(2)})` + ); + } + } + } catch (e) { + console.error('Unable to handle WS message: ', e); + } + } + + private async _sendNotification(title: string, message: string) { + const iconUrl = chrome.runtime.getURL('assets/icons/leather-icon-128.png'); + chrome.notifications.create({ + type: 'basic', + iconUrl, + title, + message, + priority: 0, + }); + } +} diff --git a/src/shared/message-types.ts b/src/shared/message-types.ts index 768c7ea8f0a..e8752736b1b 100644 --- a/src/shared/message-types.ts +++ b/src/shared/message-types.ts @@ -29,7 +29,7 @@ export enum InternalMethods { RequestDerivedStxAccounts = 'RequestDerivedStxAccounts', OriginatingTabClosed = 'OriginatingTabClosed', AccountChanged = 'AccountChanged', - TransactionBroadcast = 'TransactionBroadcast', + AddressMonitorUpdated = 'AddressMonitorUpdated', } export type ExtensionMethods = ExternalMethods | InternalMethods; diff --git a/src/shared/messages.ts b/src/shared/messages.ts index 90418eb7306..42c03fd3805 100644 --- a/src/shared/messages.ts +++ b/src/shared/messages.ts @@ -1,5 +1,7 @@ import { ExtensionMethods, InternalMethods, Message } from '@shared/message-types'; +import type { MonitoredAddress } from '@background/monitors/address-monitor'; + /** * Popup <-> Background Script */ @@ -15,7 +17,12 @@ type OriginatingTabClosed = BackgroundMessage< type AccountChanged = BackgroundMessage; -export type BackgroundMessages = OriginatingTabClosed | AccountChanged; +type AddressMonitorUpdated = BackgroundMessage< + InternalMethods.AddressMonitorUpdated, + { addresses: MonitoredAddress[] } +>; + +export type BackgroundMessages = OriginatingTabClosed | AccountChanged | AddressMonitorUpdated; export function sendMessage(message: BackgroundMessages) { return chrome.runtime.sendMessage(message);